What is the Path.get(".") refering to in my Java project? - java

In my current project the root directory is C:\Users\Duke. The Java class which calls Path.get(".") is in the path of C:\Users\Duke\src\dependencies\storage\Store.java. I needed to write and save data to a file, but since it has to run on different systems, I could not specify the absolute path.
I did a call on Path.get(".").forEach(System.out::println) and it printed out all the directories in src instead of storage. This has left me extremely confused. Shouldn't the Path.get(".") refer to current directory of where the code resides, which is in the storage directory?

A . denotes a relative path to the "working directory", namely the directory your program is run from. This is typically not the directory or path of the source file(s) your program is compiled from. You can do Paths.get(".").toAbsolutePath() to see the exact directory it represents.
If you're using an IDE it can be hard to tell which directory it uses as its working directory, but typically it will be the project root. You can usually configure the working directory from within the IDE.
If you're trying to load files, such as data files, that are part of the project you may find resources better than accessing the filesystem directly.

. returns the application's working directory. In general that's the directory from where you are starting the Java Virtual Machine in order to execute Java classes.
It can't refer to the location of the code because that can be everywhere, e.g. some place in the internet where your classloader downloaded the classes that are executed (something that was very common in the Old Days[TM] when Java Applets were still a thing or with Webstart-applications).

Related

Getting resources from java project [duplicate]

I know the file needs to be where the getClass().getResource(filename) can find it, but I don't know where that is.
I'm interested both in where to put the files on the filesystem itself, and how to go about using Eclipse's functionality to set up the resources.
For Eclipse, typically all you need to do is set up a folder somewhere within your source code directory. For instance, if the directory containing your source is /src then you can create a /src/resources folder to place your images/files in. Then, within your class you do a getResource("/resources/image.png") to retrieve it.
You can also place the image/file within the same folder/package as the class trying to access it if you wish (example: place the image.png in the com.mycompany package with the com.mycompany.Foo class that needs to access it and call getResource("image.png")), but I've found it's easier to keep resources like images and other files in their own special directory outside of the class folders -- they're just easier to manage that way.
In Eclipse, whenever you do a build, the files within this resource directory will be copied over into your build directory along with your compiled classes.
It's important to note that if you have "Build Automatically" turned on in Eclipse (as most people do) any resources in this directory that get changed outside of Eclipse (i.e. you edit an image using an image editing tool) that the IDE may not always detect this change. Usually doing a refresh on the project folder will ensure that the file gets updated in the build in these situations.
You can either put them in the src folder alongside your classes, or you can create a new source folder for the purpose (usually called resources), although you'll locate them identically from code.
Then you get at them using getResource("/com/x/y/foo.png").

How is current working directory determined when running from Eclipse? [duplicate]

I was trying to load a file in a webapp, and I was getting a FileNotFound exception when I used FileInputStream. However, using the same path, I was able to load the file when I did getResourceAsStream().
What is the difference between the two methods, and why does one work while the other doesn't?
The java.io.File and consorts acts on the local disk file system. The root cause of your problem is that relative paths in java.io are dependent on the current working directory. I.e. the directory from which the JVM (in your case: the webserver's one) is started. This may for example be C:\Tomcat\bin or something entirely different, but thus not C:\Tomcat\webapps\contextname or whatever you'd expect it to be. In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname. You can learn about the current working directory the following way:
System.out.println(new File(".").getAbsolutePath());
However, the working directory is in no way programmatically controllable. You should really prefer using absolute paths in the File API instead of relative paths. E.g. C:\full\path\to\file.ext.
You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y). The normal practice is to place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the src folder and the "build path" respectively). This way you can grab them with help of the ClassLoader by ClassLoader#getResource() or ClassLoader#getResourceAsStream(). It is able to locate files relative to the "root" of the classpath, as you by coincidence figured out. In webapplications (or any other application which uses multiple classloaders) it's recommend to use the ClassLoader as returned by Thread.currentThread().getContextClassLoader() for this so you can look "outside" the webapp context as well.
Another alternative in webapps is the ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream(). It is able to access files located in the public web folder of the webapp project, including the /WEB-INF folder. The ServletContext is available in servlets by the inherited getServletContext() method, you can call it as-is.
See also:
Where to place and how to read configuration resource files in servlet based application?
What does servletcontext.getRealPath("/") mean and when should I use it
Recommended way to save uploaded files in a servlet application
How to save generated file temporarily in servlet based web application
getResourceAsStream is the right way to do it for web apps (as you already learned).
The reason is that reading from the file system cannot work if you package your web app in a WAR. This is the proper way to package a web app. It's portable that way, because you aren't dependent on an absolute file path or the location where your app server is installed.
FileInputStream will load a the file path you pass to the constructor as relative from the working directory of the Java process. Usually in a web container, this is something like the bin folder.
getResourceAsStream() will load a file path relative from your application's classpath.
The FileInputStream class works directly with the underlying file system. If the file in question is not physically present there, it will fail to open it. The getResourceAsStream() method works differently. It tries to locate and load the resource using the ClassLoader of the class it is called on. This enables it to find, for example, resources embedded into jar files.
classname.getResourceAsStream() loads a file via the classloader of classname. If the class came from a jar file, that is where the resource will be loaded from.
FileInputStream is used to read a file from the filesystem.
I am here by separating both the usages by marking them as File Read(java.io) and Resource Read(ClassLoader.getResourceAsStream()).
File Read -
1. Works on local file system.
2. Tries to locate the file requested from current JVM launched directory as root
3. Ideally good when using files for processing in a pre-determined location like,/dev/files or C:\Data.
Resource Read -
1. Works on class path
2. Tries to locate the file/resource in current or parent classloader classpath.
3. Ideally good when trying to load files from packaged files like war or jar.

home folder changes when using java classes from matlab

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.

getResourceAsStream() vs FileInputStream

I was trying to load a file in a webapp, and I was getting a FileNotFound exception when I used FileInputStream. However, using the same path, I was able to load the file when I did getResourceAsStream().
What is the difference between the two methods, and why does one work while the other doesn't?
The java.io.File and consorts acts on the local disk file system. The root cause of your problem is that relative paths in java.io are dependent on the current working directory. I.e. the directory from which the JVM (in your case: the webserver's one) is started. This may for example be C:\Tomcat\bin or something entirely different, but thus not C:\Tomcat\webapps\contextname or whatever you'd expect it to be. In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname. You can learn about the current working directory the following way:
System.out.println(new File(".").getAbsolutePath());
However, the working directory is in no way programmatically controllable. You should really prefer using absolute paths in the File API instead of relative paths. E.g. C:\full\path\to\file.ext.
You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y). The normal practice is to place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the src folder and the "build path" respectively). This way you can grab them with help of the ClassLoader by ClassLoader#getResource() or ClassLoader#getResourceAsStream(). It is able to locate files relative to the "root" of the classpath, as you by coincidence figured out. In webapplications (or any other application which uses multiple classloaders) it's recommend to use the ClassLoader as returned by Thread.currentThread().getContextClassLoader() for this so you can look "outside" the webapp context as well.
Another alternative in webapps is the ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream(). It is able to access files located in the public web folder of the webapp project, including the /WEB-INF folder. The ServletContext is available in servlets by the inherited getServletContext() method, you can call it as-is.
See also:
Where to place and how to read configuration resource files in servlet based application?
What does servletcontext.getRealPath("/") mean and when should I use it
Recommended way to save uploaded files in a servlet application
How to save generated file temporarily in servlet based web application
getResourceAsStream is the right way to do it for web apps (as you already learned).
The reason is that reading from the file system cannot work if you package your web app in a WAR. This is the proper way to package a web app. It's portable that way, because you aren't dependent on an absolute file path or the location where your app server is installed.
FileInputStream will load a the file path you pass to the constructor as relative from the working directory of the Java process. Usually in a web container, this is something like the bin folder.
getResourceAsStream() will load a file path relative from your application's classpath.
The FileInputStream class works directly with the underlying file system. If the file in question is not physically present there, it will fail to open it. The getResourceAsStream() method works differently. It tries to locate and load the resource using the ClassLoader of the class it is called on. This enables it to find, for example, resources embedded into jar files.
classname.getResourceAsStream() loads a file via the classloader of classname. If the class came from a jar file, that is where the resource will be loaded from.
FileInputStream is used to read a file from the filesystem.
I am here by separating both the usages by marking them as File Read(java.io) and Resource Read(ClassLoader.getResourceAsStream()).
File Read -
1. Works on local file system.
2. Tries to locate the file requested from current JVM launched directory as root
3. Ideally good when using files for processing in a pre-determined location like,/dev/files or C:\Data.
Resource Read -
1. Works on class path
2. Tries to locate the file/resource in current or parent classloader classpath.
3. Ideally good when trying to load files from packaged files like war or jar.

Java in Eclipse: Where do I put files on the filesystem that I want to load using getResource? (e.g. images for an ImageIcon)

I know the file needs to be where the getClass().getResource(filename) can find it, but I don't know where that is.
I'm interested both in where to put the files on the filesystem itself, and how to go about using Eclipse's functionality to set up the resources.
For Eclipse, typically all you need to do is set up a folder somewhere within your source code directory. For instance, if the directory containing your source is /src then you can create a /src/resources folder to place your images/files in. Then, within your class you do a getResource("/resources/image.png") to retrieve it.
You can also place the image/file within the same folder/package as the class trying to access it if you wish (example: place the image.png in the com.mycompany package with the com.mycompany.Foo class that needs to access it and call getResource("image.png")), but I've found it's easier to keep resources like images and other files in their own special directory outside of the class folders -- they're just easier to manage that way.
In Eclipse, whenever you do a build, the files within this resource directory will be copied over into your build directory along with your compiled classes.
It's important to note that if you have "Build Automatically" turned on in Eclipse (as most people do) any resources in this directory that get changed outside of Eclipse (i.e. you edit an image using an image editing tool) that the IDE may not always detect this change. Usually doing a refresh on the project folder will ensure that the file gets updated in the build in these situations.
You can either put them in the src folder alongside your classes, or you can create a new source folder for the purpose (usually called resources), although you'll locate them identically from code.
Then you get at them using getResource("/com/x/y/foo.png").

Categories

Resources