Spring does not find file in resources - java

i have following line
File file = ResourceUtils.getFile("classpath:calculation.csv");
and i also tried
File file = ResourceUtils.getFile("classpath:/calculation.csv");
but both will throw an error
java.io.FileNotFoundException: class path resource [calculation.csv] cannot be resolved to absolute file path because it does not exist
but i do have calculation.csv in by resources folder..
why is this?
I need to read file from resources folder, and it should also work in server enviroment
EDIT:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("calculation.csv").getFile());
works just as fine, so not at all..
EDIT2:
tried with folder.. i have both calculation.csv and csv/calculation.csv in my resources folder now..
none of the above work, with /csv/ added.
what kind of path does this thing want?!
EDIT3:
aaand
File file = new ClassPathResource("calculation.csv").getFile();
is also no go, what even is this..

Loading file (as FILE) wont work. You must use it as resource. Files inside JAR will not work as file anyway. This is also what your "check" code shows.
classLoader.getResource("calculation.csv") works, because you are using classloader to get resource, not filesystem to get file (which is what File api does). It could work, if you would deal with non packed application. Once you pack your app into JAR, file path will be like your/path/to/jar.jar!someResource - note ! mark (and that is what you would see as well). So basicly it will return File instance, you that you wont be able to use anyway, as file system has no access to it.
You could alternatively try to extract it first with ResourceUtiuls#extractJarFileURL(URL jarUrl) and then use extracted file.
I think, that in most cases Class#getResourceAsStream is the way to go and I think that it should fit your needs as well to read content of resource.

Related

Java read and write to the resource folder

When someone opens my jar up I am opening a file selector gui so they can choose where they want to store their jar's files like config files and such. This should only take place the first time they open the jar. However, one issue with this approach is that I would have no way to know if it's their first time opening the jar since I will need to save the selected path somewhere. The best solution to this sounds like saving the selected path inside a file in the resource folder which is what I am having issues with. Reading and writing to this resource file will only need to be done when the program is actually running. These read and write operations need to work for packaged jar files (I use maven) and in the IDE.
I am able to read a resources file inside of the IDE and then save that file to the designated location specified in the file selector by doing this. However, I have not been able to do the same from a jar despite trying multiple other approaches from other threads.
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("config.yml");
try {
if(is != null) {
Files.copy(is, testFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
So just to clarify when my project is loaded I need to listen for the user to select a valid path for files like my config. Then I want to write my config to that path which I can do from my IDE and is shown above but I cant figure this out when I compile my project into a jar file since I always receive a file not found error in my cmd. However, the main point of this post is so that I can figure out how to save that selected path to my resource folder to a file (it can be json, yml or whatever u like). In the code above I was able to read a file but I have no idea how to go from that to get the files path since then reading and writing to it would be trivial. Also keep in mind I need to be able to read and write to a resource folder from both my IDE and from a compiled jar.
The following code shows my attempt at reading a resource from a compiled jar. When I added a print statement above name.startWith(path) I generated a massive list of classes that reference config.yml but I am not sure which one I need. I assume it has to be one of the paths relating to my project or possible the META-INF or META-INF/MANIFEST.MF path. Either way how am I able to copy the file or copy the contents of the file?
final String path = "resources/config.yml";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
try {
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path)) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
Also if you were wondering I got the above code from the following post and my first block of code I pasted above is actually in the else statement since the IDE code from that post also did not work.
How can I access a folder inside of a resource folder from inside my jar File?
You can't write to files inside your JAR file, because they aren't actually files, they are ZIP entries.
The easiest way to store configuration for a Java application is to use Preferences:
Preferences prefs = Preferences.userNodeForPackage(MyApp.class);
Now all you have to do is use any of the get methods to read, and put methods to write.
There is absolutely no need to write files into your resource folder inside a jar. All you need to have is a smart classloader structure. Either there is a classloader that allows changing jars (how difficult is that to implement?), or you just setup a classpath that contains an empty directory before listing all the involved jars.
As soon as you want to change a resource, just store a file in that directory. When loading the resource next time, it will be searched on the classpath and the first match is returned - in that case your changed file.
Now it could be that your application needs to be started with that modified classpath, and on top of that it needs to be aware which directory was placed first. You could still setup that classloader structure within a launcher application, which then transfers control to the real application loaded via the newly defined classloader.
You could also check on application startup whether a directory such as ${user.home}/${application_name}/data exists.
If not, create it by extracting a predefined zip into this location.
Then just run your application which would load/write all the data in this directory.
No need to read/write to the classpath. No need to include 3rd party APIs. And modifying this initial data set would just mean to distribute a new zip to be extracted from.

Eclipse can't read text file in src folder

I am implementing a Branch Predictor for one of my classes and I am trying to read files from my src folder in Eclipse but for some reason it is not able to open the files. I have done this before with the exact same process so I'm not sure what is different.
traceFile is set from the command line and if I print "input", it will print out the correct file path and I have confirmed it is there manually.
ClassLoader loader = BiModalPredictor.class.getClassLoader();
File input = new File(loader.getResource(traceFile).getFile());
Scanner fin = new Scanner(input);
Is there any insight as to why this might be happening? I've tried restarting Eclipse, refreshing the files, and I've also tested it on another program which worked. No idea why it can't find this file.
Resources on the classpath, i.e. available through the classloaders getResource method, will not be files on the file system when your application is deployed as a jar file, or deployed in general. Do not use File with such resources, instead use getResourceAsStream to access the resource content.
Besides, your code is wrong. getResource() returns a URL. If you want a File object from a URL, you should use new File(uri), where the URI is obtained by calling url.toURI().
File input = new File(loader.getResource(traceFile).toURI());

Absolute path of a file inside a project package

I've created a file inside a project package using this code:
File xmlFile = new File("src/com/company/project/xml/tags.xml");
I am able to read the file while running from eclipse. However, after creating .jar, I'm unable to read the file. So I want to put absolute path while reading the file from the project package. How it can be done? Help and suggestions are appreciated.
In most cases, IDE's will include no Java files in the resulting Jar. Most IDE's will also include the src directory in the classpath when you run/debug the program from within them.
As a general rule of thumb, never include src in any path, src will simply not exist once the program is built.
Instead you need to make use of Class#getResource or Class#getResourceAsStream, depending on your needs. You should remember, you should never treat an "embedded" resource as a File, as in most cases it won't be, it'll be a stream of bytes in a zip file.
Something like...
URL xmlFile = getClass().getResource("/com/company/project/xml/tags.xml");
will return a URL reference to the resource. Remember, if you need a InputStream, you'll have to Class#getResourceAsStream.
If you want the resource to be writable, then you will need to find a different location to store it, as embedded resources are read only
Try with getClass().getResource()
new File(getClass().getResource("src/com/company/project/xml/tags.xml").toURI());

Why does getResourceAsStream() work in the IDE but not the JAR?

I just want to read a file into my program. The file is located one directory above the working directory at "../f.fsh". So the following code runs correctly when I run it in the IDE
String name="../f.fsh";
InputStream is = getClass().getResourceAsStream(name);
InputStreamReader isreader=new InputStreamReader(is);//CRASHES HERE WITH NULL POINTER EXCEPTION
BufferedReader br = new BufferedReader(isreader);
but when I create a JAR file that has f.fsh zipped inside of it and run it, it crashes when creating the InputStreamReader, because the InputStream is null.
I've read a bunch of answers to questions about input streams and JAR files, and what I got out of it is that I should be using relative paths, but I am already doing that. From what I understand getResourceAsStream() can find files relative to the root of the project, that is what I want. Why does it not work in the JAR? What is going wrong, how can I fix it?
Does it have to do with the classpath? I thought that was only for including files external to the jar being run.
I have also tried, but still fail, when putting a slash in:
InputStream is = getClass().getResourceAsStream("\\"+name);
I looked at: How to get a path to a resource in a Java JAR file andfound that contents of a JAR may not necesarily be accesible as a file. So I tried it with copying the file relative to the jar (one directory up from the jar), and that still fails. In any case I'd like to leave my files in the jar and be able to read them there. I don't know what's going wrong.
You can't use .. with Class.getResourceAsStream().
To load a resource f.fsh in the same package as the class, use SomeClass.class.getResourceAsStream("f.fsh")
To load a resource f.fsh in a sub-package foo.bar of the package of the class, use SomeClass.class.getResourceAsStream("foo/bar/f.fsh")
To load a resource f.fsh in any package com.company.foo.bar, use SomeClass.class.getResourceAsStream("/com/company/foo/bar/f.fsh")
This is described in the javadoc of the getResource() method, although it lacks examples.
If .. works in Class.getResourceAsStream() while running from Eclipse, it's a bug in Eclipse. Eclipse and other IDEs implement custom class loaders to fetch resources from the project at runtime. It looks like the class loader implementation in Eclipse isn't performing all the necessary validations on input to getResourceAsStream() method. In this case the bug is in your favor, but you will still need to rethink how you structure your resources for your code to work in all cases.
it's mandatory that the name of the file is CASE SENSITIVE
it's mandatory to refresh (F5) the project explorer if the file is moved or copied outside Exclipse

Netbeans Built .jar doesn't work with class file inside

I had problems while finding the path of file(s) in Netbeans..
Problem is already solved (checked answer).
Today I noticed another problem: When project is finished,
I have to execute the generated .jar to launch the program, but it doesn't work because an error occurs: NullPointer (where to load a file) when accessing/openning jar outside Netbeans.
Is it possible to open a file with the class file in Java/Netbeans which works in Netbeans and even in any directory?
I've found already some threads about my problem in site but none was helpful.
Code:
File file = new File(URLDecoder.decode(this.getClass().getResource("file.xml").getFile(), "UTF-8"));
The problem you have is that File only refer to files on the filesystem, not files in jars.
If you want a more generic locator, use a URL which is what getResource provides. However, usually you don't need to know the location of the file, you just need its contents, in which case you can use getResourceAsInputStream()
This all assumes your class path is configured correctly.
Yes, you should be able to load a file anywhere on your file system that the java process has access to. You just need to have the path explicitly set in your getResource call.
For example:
File file = new File(URLDecoder.decode(this.getClass().getResource("C:\\foo\\bar\\file.xml").getFile(), "UTF-8"));

Categories

Resources