I have a maven project with typical project structure. At the base of the project, I have a directory names res that has some resources (> 500 MB).
I am trying to use
this.class().getClassLoader().getResourceAsStream("res/xxx")
this code fragment to read from that folder, but it returns a null resource stream.
I have a few workarounds below, but none of these are acceptable due to reasons explained below.
I can move the folder to {base}/target/classes, and it will be read, but it will also get cleaned when I do a mvn clean. Hence, this approach doesn't work. For some reason, specifying the path as ../../res/xxx also doesn't work.
I can move the folder to {base}/src/resources, but then it will get copied to target/classes and the jar. Hence this is also not acceptable.
Though I am open to trying some other java APIs, I may have to use the class loader mechanism only as there is some external library component that is also trying to access the res folder using the similar approach.
Is there some way I can read the res folder from projects base directory? Is there some setting in pom.xml file that can help me with that?
Use this.class().getClassLoader().getResourceAsStream("/res/xxx") and then you will be reading from the root of the classpath irrespective of the actual file/folder location in windows or Linux. This is actually one of the safest ways to read files especially when you do not know how your application will eventually be deployed.
It means though that your classpath must include the parent of res and that res/ must be copied over when you deploy your app
Otherwise, if you want to use relative paths, try this snippet (taken from this SO answer):
String filePath = new File("").getAbsolutePath();
filePath.concat("path to the property file");
If you use this.class().getClassLoader().getResourceAsStream("/res/xxx"), it is going to try to load resources from the classpath. If that's not want you want to do, you're going to need to specify an absolute path.
Resource on Classpath
If you don't want the resource built into your JAR, I'd suggest having a different maven project with the file in it, under the src/main/resources directory. This will create a jar file with the file in it, which will be ~500MB.
After this, you can include a dependency on this project in your project containing your application code. This will then be able to reference it from the jar file using getResourceAsStream(...).
If you don't want this large jar file to ship with your application, make sure you mark the dependency with <scope>provided</scope>.
File from Absolute Path
You will need to take the file location as a parameter in your main method, and then use new File("C:\\path\\to\\your\\file.txt") and then use a FileReader to read it in.
Related
Hy,
I want to get the resource folder (ex: C:\Users\Raul\workspace\Serial\src\test\resources) in a Maven project but every time I run this java code:
System.out.println(getClass().getResource("").getPath());
it returns me this path: C:/Users/Raul/workspace/Serial/target/test-classes/
The last time I used Maven, worked that way without any changes from me.
Thx in advance.
With a typical setup, Maven copies the resources to the target/classes (or target/test-classes) directory. Also, the target/classes (or target/test-classes) directory is added to the classpath.
If you have a file src/test/resources/foo.txt, then you would access the file using getResource("/foo.txt").
Generally speaking, you would not want your code to refer to source folders to access resources. Resources might be put in multiple locations and it is pretty common to "filter" the resources (replace tokens with build property values). In the filtering case, you absolutely do not want the processed resource files to be in the source directory.
I am using an external jar (stored in my lib file within an eclipse project) and that jar needs access to a file to which I am supposed to pass the path. So far I have only been able to make it work properly if I store the file in a completely separate area on the server.
I'd like to be able to store this file neatly within the project. For examples sake lets say that testfile.txt is in the projects src/testfolder. From within java I try to reference the file like so:
File file = new File("src/testfolder/testfile.txt").getAbsolutePath();
But that returns a path on my pc. In this case its:
"/home/me/testfolder/testfile.txt"
I'd like to application to be portable so I can move the jar file around if necessary without having to worry about bringing external folders. How can I reference this file within the application and pass that url to an external jar?
Does the jar includes this file as well. If yes, then it should not be an issue as the absolute path will be taken care of automatically.
I have a Java project and used the standard maven archetype to create the dir structure.
It looks like this:
|-src/main/java
|-src/main/resources
|-target/classes
|- ...
Now one of my classes uses a .properties file to read in some settings. I placed it in src/main/resources and read it through File propertiesFile = new File("./src/main/resources/starter.properties");.
When I use the eclipse run-configuration, everything works fine. But recently I tried to start the same Java-class from my console using java some.package.Class, and since the .class-file is located in target/classes I got the message, that ./src/main/resources/starter.properties couldn't be found.
What am I doing wrong? Is the .properties file not supposed to be located in the resources-folder or do I have to use an other way to load it?
The two previous answers are correct, but I wanted to give a bit more context.
This file is in two places. It starts off in /src/main/resources and when you build the project, Maven copies it to /target/classes.
At runtime, you shouldn't access the copy that is in your source code. Otherwise, your software would need access to the source code in order to run. Rather, you should access the copy that is in your deliverable. At execution time, you can safely assume that you will find it on the classpath. It's in the same place as your compiled classes, so if it weren't on the classpath, you wouldn't have been able to run the program in the first place. This is why you should use getResourceAsStream() as mentioned by the other answerers.
(Though for production software, I do recommend Spring's Resource abstraction for accessing these kinds of things.)
use
YourClass.class.getResourceAsStream("/filename.properties");
To expand on the two answers already given, when you build your Maven project the files in src/main/resources are copied into your JAR at the root of the classpath. If you did a jar tvf *yourjarname* you would notice there is neither a src/main/java or src/main/resources folder in it. So trying to manually read from those (now non-existent) paths will fail when you run via JAR. The other two answers have excellent suggestions, use the getResourceAsStream method to read in your file. Theres even a method on the Properties object that makes this very convenient and easy to use:
URL resourceURL = Thread.currentThread().getContextClassLoader()
.getResource(yourpropertyfilename);
Properties props = new Properties();
props.load(resourceURL.openStream());
At runtime this file will be in your classpath. Use Class.getResourceAsStream() to access it.
In one of my JUnit tests, I am trying to load all the files contained in a directory. I used .getClassLoader().getResource("otherresources") to find the directory. I then made a new java.io.File. I then used listFiles() to get all the children files and then used .getClassLoader().getResource() again to load each of those files.
URL url = FileLoadTest.class.getClassLoader().getResource("otherresources");
File directory = new File(url.getPath());
File[] files = directory.listFiles();
Basically, I want to be able to load all the files in a directory without knowing exactly what they are.
I can properly run the test in Eclipse. When I go to build the project with Maven (mvn install) or run the test case by itself using surefire (mvn -Dtest=FileTest test) the test case fails with a NullPointerException. I think the issue has something to do with the File api not working as intended within the JAR file that the resources are deployed to.
Any tips on how to fix this?
Correct, the File API can only read from the file system, and not within JAR files.
Unfortunately, there's not a good way to do exactly what you're trying to do, without using some additional libraries that utilize some hacks in an attempt to accomplish just this. Resources on the classpath are not meant to be enumerable, as there is no guarantee where they are loaded from (could be from disk, in a JAR file, HTTP, a database, or other exotic resources - including ones where the enumeration of available files would not be feasible). The best approach is to include an "index" or other similar file with a well-known name, which can be referenced to find other resources you're interested in.
One of these "hacks" would be, if you know the path to the JAR file(s), you could read from them using JarFile (or even just ZipFile).
.getClassLoader().getResource("otherresources")
Untested. Once you have the 'directory', use it to get back to the archive itself.
Establish a ZipInputStream to the archive.
Call getNextEntry() until null and add the entries matching the required location to an expandable list (e.g. ArrayList).
Construct an URL from the location of the archive and ZipEntry.getName()
Of course, I would normally suggest creating a list of the target resources when making the archive, then including that list at a known location in the archive. But the above might suffice for this use case.
I am writing a java application with a matlab ui. For this I use java objects in matlab as explained here: http://www.mathworks.com/help/techdoc/matlab_external/f4873.html
those java classes reference (using a relative path) to resources in some other folder in the parent map. In eclipse or as an executable jar this all works fine.
The problem is that when classes are used in matlab the homefolder changes. So instead of looking in JAR/resources or PROJECTMAP/resources it looks for the resources in MATLAB/resources and returns a file not found exception.
how I currently solved it is kinda lame:
I simply put a copy of the resource folder in the MATLAB directory which makes the code execute.
Yet this is a poor solution.
What I would want is
1: to include the resource folder in the jar (generated in eclipse) an make it possible to use these classes in matlab (in short: independency current directory)
2: Being able to run the same code from eclipse (to debug/profile...).
3: That the code should execute independantly of the location the jar is in as long as it is added to the matlab classpath. (so the jar does not have to be in a specific folder (eg MATLAB folder))
So I 'simply' need a way to specify the location of the resource folder in my code as to achieve 1,2,3 (1,2 most important).
Not sure how you're reading and what you're doing with these resources (so this might not be the correct solution for your case), but you indeed might want to put these on your classpath. If you put them in their own source folder in eclipse you can setup your build to include them in your jar. (Maven by convention has a /src/main/resources directory that is for sticking arbitrary files into a the compiled jar).
With these resources on the classpath... You can then use the classloader to load files through getClass().getResourceAsStream() or getResource() and run with it.