Directory list of JAR file within classpath - java

The typically method to reference a file contained with a JAR file is to use ClassLoader.getResource. Is there a way to get the contents of a directory within a JAR files (similar to java.io.File.listFiles())? Note that the JAR file is within the classpath and its filename might not be known during runtime.
Basically I have a bunch of non-.class resource files within a directory. At runtime I need to load each resource file contained within a known directory.

There is a system property called java.class.path, parse the path to your jar and then use JarURLConnection class to do what you want.

Related

Can't enumerate `class` files with ClassLoader#getResources()

I am trying to enumerate classes in the package with
Enumeration<URL> resourceUrls = myObject.getClassLoader().getResources("path/to/my/package/");
while (resourceUrls.hasMoreElements()) {
...
Unfortunately it returns nothing. Why?
Assuming path is correct. Path starts with no slash and ends with slash. There are several public classes under path.to.my.package package.
I took this code from Spring.
You cannot walk a class path like you can walk a file path. Walking a file path is done on the file system, which does not apply to a class path.
While a java class path entries are formed like file paths and usually are folders and files (either on the file system or inside a JAR archive), it does not necessarily have to be that way. In fact, the classes of one single package may originate from various locations of differing nature: one might be loaded from a local JAR file while another one might be loaded from a remote URL.
The method ClassLoader.getResources() exists to provide access to all "occurrences" of a resource if it has the same name in different JAR files (or other locations). For example you can use
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
to access the manifest file of each JAR file in your class path.
Try with
Enumeration<URL> urls = ClassLoader.getSystemClassLoader().getResources("path/to/my/package");
while (urls.hasMoreElements()) {
System.out.println(urls.nextElement());
}

Using relative path in a maven project

I have a maven project with these standard directory structures:
src/main/java
src/main/java/pdf/Pdf.java
src/test/resources
src/test/resources/files/x.pdf
In my Pdf.java,
File file = new File("../../../test/resources/files/x.pdf");
Why does it report "No such file or dirctory"? The relative path should work. Right?
Relative paths work relative to the current working directory. Maven does not set it, so it is inherited from whatever value it had in the Java process your code is executing in.
The only reliable way is to figure it out in your own code. Depending on how you do things, there are several ways to do so. See How to get the real path of Java application at runtime? for suggestions. You are most likely looking at this.getClass().getProtectionDomain().getCodeSource().getLocation() and then you know where the class file is and can navigate relative to that.
Why does it report "No such file or dirctory"? The relative path should work. Right?
wrong.
Your classes are compiled to $PROJECT_ROOT/target/classes
and your resources are copied to the same folder keeping their relative paths below src/main/resources.
The file will be located relative to the classpath of which the root is $PROJECT_ROOT/target/classes. Therefore you have to write in your Pdf.java:
File file = new File("/files/x.pdf");
Your relative path will be evaluated from the projects current working directory which is $PROJECT_ROOT (AFAIR).
But it does not matter because you want that to work in your final application and not only in your build environment. Therefore you should access the file with getClass().getResource("/path/to/file/within/classpath") which searches the file in the class path of which the root is $PROJECT_ROOT/target/classes.
No the way you are referencing the files is according to your file system. Java knows about the classpath not the file system if you want to reference something like that you have to use the fully qualified name of the file.
Also I do not know if File constructor works with the classpath since it's an abstraction to manage the file system it will depend where the application is run from. Say it is run from the target directory at the same level as source in that case you have to go one directory up and then on src then test the resources the files and finally in x.pdf.
Since you are using a resources folder I think you want the file to be on the classpath and then you can load a resource with:
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("<path in classpath>");
Then you can create a FileInputStream or something to wrap around the file. Otherwise use the fully qualiefied name and put it somewere like /home/{user}/files/x.pdf.

Cannot load resource in jar

I am trying to load a resource in a jar, here is the exported jar:
'main' is the package with all my classes, and in one of those classes I am trying to load the background.png file. In my Eclipse project I put the resources under a "res/" folder, which I added to the build path to include it. When I try to use
new File("background.png");
It can't find the file.
When I use
MyClass.class.getClass().getClassLoader().getResource("background.png");
It still can't find the file.
Files packaged in a jar can't be accessed as File objects.
When you try
MyClass.class.getClass().getClassLoader().getResource("background.png");
you are actually using the ClassLoader of java.lang.Class and not of main.MyClass which may not be able to find the resource (in case it is the system classloader). Try
MyClass.class.getClassLoader().getResource("background.png");
instead.

Load a file outside of a Jar

I have a folder called lib that contains all my Jar files and in one of the Jar files class, I have a main method which is called by a batch file. In the same folder location as my lib, I have another folder structure path/to/a/resource/myresource.txt
How can I load this file from a class inside the Jar file? I tried the following and both resulted in null:
getClass().getResource("path/to/a/resource/myresource.txt")
getClass().getClassLoader().getResource("path/to/a/resource/myresource.txt")
Any ideas? Even with an absolute path, it failed! Any suggestions?
You can use:
getClass().getResourceAsStream("path/to/a/resource/myresource.txt")
However, for this to work, you need to add the path '.' to the Class-Path entry of the JAR's MANIFEST.MF file.
http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
Two things you tried are used to read files from class-path since this folder is not on your classpath you can read it directly with any of the java File IO classes.
File file = new File("C:/folder/myFile.txt");
or if you know the relative path:
File file = new File("../../path/myFile.txt");
Your path seems not to be precise enough. Further, this question has been worked before.
Have a look here:
How to Load File Outside of, but Relative to, the JAR?
How to get the path of a running JAR file?
You can either load the file from file system
new FileReader(relativeOrAbsoluteFilesystemLocation)
or you can add the directory in question to your classpath:
java -cp "lib/*;lib" ...
and then use your original method.
(Unix uses : rather than ; as classpath separator)

Getting XML file not in the same root as the source file in Java

I have a problem where I can't seem to link to a xml file, see the layout below:
Folder Name
-Folder
-Folder
-SourceFiles
-packagename
-all my java files
-myXml.xml
Build is where all the class files etc is stored.
src is where the projectFolder is, and within it the java files
Code I am using to link XML File for Synth: SynthDialog.class.getResourceAsStream("synthtest/synthDemo.xml")
Now I want to link to the myXML.xml file in the top-level folder. It would be the PHP Equivelent of ../../Folder/
Thanks
You appear to be attempting to access the file using getResourceAsStream with a relative name. If that is the case, then the resource should be in located in a JAR file or directory on the classpath, and the location will be resolved relative to the FQN of the class.
I can't tell where the ".class" files are located in the tree, or how your classpath is set up, so I can't be more specific.
UPDATED
If you are executing out of that build directory, then your build process needs to copy the XML file to the appropriate place in the build tree so that the class-relative path ends up referring to the file. (Or use a path that starts with "/" so that you don't depend on the classes FQN at all.)
In the long term, you will probably execute out of a JAR file, and the data file will need to be inside it.
Use "getSystemResourceAsStream" instead of "getResourceAsStream" to access files outside of your codebase.

Categories

Resources