Java relative path start from my src folder - java

I wanna use relative path start from my src folder to get file from resource folder.
File myFile = new File("/src/main/resources/filefolder/file.xml");
When I try this:
File myFile = new File("../src/main/resources/filefolder/file.xml");
Or this:
File myFile = new File("../../../../src/main/resources/filefolder/file.xml");
I get:
java.io.FileNotFoundException: /srv/../src/main/resources/filefolder/file.xml(No such file or directory)
My file structure:
-src
-main
-java
-com.my.site
-task
-MyClass.java
-resources

I see you are asking about the relative path but seems like you want to just read the file from resources, I believe the most common way to read resources is by using the class loader, example:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("filefolder/file.xml").getFile());

your path is correct, just add dot before src, to indicate that you are searching relative path to project root directory, in other case you'll search by absolute path
File myFile = new File("./src/resources/filefolder/file.xml");
if doesn't work - try this:
File myFile = new File("src/resources/filefolder/file.xml");
anyway you can run this to check what is your root dir:
public static void main(String[] args) {
System.out.println(new File("").getAbsolutePath());
}

Just a little explanation... What you want to do is get a resource from the resource folder, that's a quite typical task.
What you do have to realize is, that the whole /src/main/etc. structure is there to structure your source code, in other words, the .java files (and resource files). In your compiled program, this structure will not longer exist in the same way, so relying on a src directory is a very, very bad idea.
This structure is there for maven:
src/main -> Everything that should be part of the "program" all the time
src/test -> Everything that should only be part of the "program" when running automated tests
src/main/java -> .java files that need to be there always
src/main/resources -> Resources (images, templates, etc.) that need to be there always
src/test/java -> .java files that are only needed during automated tests (for example, the automated tests themselves)
src/test/resources -> Resources that are only used in automated tests, for example, files to compare results against, etc.
Where does this lead us? It leads to the simple fact, that, in the end, the whole src/main and src/test will simply not exist and indeed, java and resources will be added together (you can check this by looking at a .jar file - it can be opened with any Zip-Program). This is, why #LazerBanana is entirely correct: You do not try to navigate directories, you ask for resources and the resources are inside your classpath - and it does not matter, if they are in the resources or java folder (because that's just to keep your source code structured). In your class path, both folders come together.

Related

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.

Relative path's to images and sound in Java

Currently the project that I am making is game made with Jframe/Jpanel. I am using imports of images and sound through:
images:
ImageIcon a = new ImageIcon("C:/Users/Home/IdeaProjects/Game/src/DragonRoll/sprites/user_sprite_down.png");
player = a.getImage();
//sign
Sound:
String gongFile = ("C:/Users/Home/IdeaProjects/Game/src/DragonRoll/music/game_track.wav");
InputStream in = new FileInputStream(gongFile);
AudioStream audioStream = new AudioStream(in);
AudioPlayer.player.start(audioStream);
The images and the soundtrack from the example is seen to be imported from a direct path not a relative one meaning that it does not work on other computer or devices since they do not have the exact same path. Can someone recommend any solutions to this, please provide example code. I have tried just removing the path except the folder which contains the images and the image name itself but that did not work.
I am using Intellij and running as an executable java file.
Also the folder which contains all of the project goes like:
- Main project folder
- Branches into .idea, out and src
- src contains classes of the game and 2 folders called images and music
By convention source files in a Java project (everything that ends with .java) should be in a folder called src/main/java. Resources such as images, audio files, default config files, etc. are usually placed in a second source folder called src/main/resources. This way the compiled sources (i.e. the .class files) and the resource files will be on the classpath at run time of your application.
To load for example the src/main/resources/DragonRole/music/game_track.wav resource from your classpath you can simply do this:
InputStream gameTrackIn = MyClass.class.getResourceAsStream(
"/DragonRole/music/game_track.wav");
To load the src/main/resources/DragonRoll/sprites/user_sprite_down.png resource from your classpath you can simply do this:
ImageIcon userSpriteDownImg = new ImageIcon(MyClass.class.getResource(
"/DragonRoll/sprites/user_sprite_down.png"));
Your project structure should look like this:
Game (project root)
└ src/main
├ java (source root)
└ resources (resource root)
Basing on your comment responses, I propose you to place your resource files inside the jar.
After, Accessing to a resource file can be done in a such way : YourClass.class.getResource("sun.png") if the file is at the correct place.
Your main task now is placing the resource files to the convenient place and ensuring that you build allows to create the JAR with the expected files in the expected directory.
You don't seem to use Maven. It is not a prerequisite but it could easy your work to create the jar.
It's a common question. You should find some good examples about it.
Ended up using:
ImageIcon c = new ImageIcon("src/main/resources/sprites/new_background_panel.png");
Meaning it was looking from the source folder and not the whole computers path, thanks all others who helped out.

.jar export does not understand relative paths within project folder

I have a java project for which I have used Intellij Idea. The project runs fine, and I have exported it as a jar. The jar export also runs properly, except for one issue:
I have an additional "resources" folder within my project, and there are two csv files (very simple structure with two columns). In the code, I have used their relative paths as follows
private static final __MY_FILE = new File("resources/filename.csv");
As expected, this works properly when I run from the IDE. But when I export the project as a jar, the code crashes with FileNotFoundException because these relative paths are no longer treated as being relative to project folder.
Temporarily, I have resorted to providing the full path in the code (i.e. __MY_FILE = new File("/home/.../resources/filename.csv")), but this is clearly a disastrous practice!
How can I use paths relative to the project folder so that the exported .jar works?
The directory structure is as follows:
networkmeasurements
/matrixmethods
/src
/probabilisticmethods
/src
/utils
/src
/resources
filename.csv
I am trying to get the resource filename.csv from a class inside matrixmethods.
You can't use File, since this file does not exist independently on the file system. Instead you need getResourceAsStream(), for example
...
InputStream in = getClass().getResourceAsStream("/resources/filename.csv");
BufferedReader input = new BufferedReader(new InputStreamReader(in));
...
http://www.jetbrains.com/idea/webhelp/resource-files.html might have good insight. You have to get Intellij to recognise .csv files as property files so it will bundle them.

Java get folder in same directory as Jar

Say I have an exported Jar file on my Desktop, and then a folder I want to access so my jar file can load files from it. How can I access that folder without hard coding the path?
See here: https://stackoverflow.com/a/6849255/514463
Pick one of your classes that you want the directory of, e.g.: Test:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
If I clearly understand, you may use relative path when you try to access folder. For example, if you run your jar as a standalone application, relative path "." will be a folder that contains your jar. So, when you place names.txt file next to your jar, you can get access to it with:
new File("./names.txt");
Hope I understood you right way and this will help.
The following code should provide the directory containing the JAR file:
URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
File directory = new File(url.toURI()).getParentFile();
Hmmm...
I heard this question so often, and it always boils down to this: How to load resources at runtime?
The main reason for this type of question is, that one is developping an application and now wants to create a distributable package. This normally ends in something like that:
... / my-application-folder
| -- lib / *.jar
| -- main.jar
| -- config.properties
There could be several configuration files. A configuration for the application itself, a configuration for a logging framework that is used, etc. It does not matter. If you want to access such resources, you should do it in two steps:
1) Make sure all folders containing your resources (such configuration files are resources) are part of the classpath. If you run your JAR file (here main.jar) with a java -jar main.jar command, this JAR file should contain a manifest file containing the directory . and all needed library JARs in the class-path entry. [Alternative: Maybe all your config files are located in a config/ subfolder. Then this folder must be part of the class-path.]
2) Inside your application you access such resources with a class loader:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL url = loader.getResource(neededResource);
// do something with url, e.g. open stream, read from it, and close stream
If you have a user customizable path, there are several possibilities. You could for example pass a system property to the application, as Reddy suggested in his comment. You could also have a property in a configuration file, which you are loading in the beginning part of your application. However, you have the path to this customizable folder in hand (at runtime). Then you do the following:
String customizablePath = getCustomizablePath();
URL customizablePathURL = new File(customizablePath).toURI().toURL();
ClassLoader loader = new URLClassLoader(new URL[] {customizablePathURL});
Then you can continue like above.
File f = new File("Folder")
This File object points to "Folder" directory in the the working directory of the Jar.

open resource with relative path in Java

In my Java app I need to get some files and directories.
This is the program structure:
./main.java
./package1/guiclass.java
./package1/resources/resourcesloader.java
./package1/resources/repository/modules/ -> this is the dir I need to get
./package1/resources/repository/SSL-Key/cert.jks -> this is the file I need to get
guiclass loads the resourcesloader class which will load my resources (directory and file).
As to the file, I tried
resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()
in order to get the real path, but this way does not work.
I have no idea which path to use for the directory.
I had problems with using the getClass().getResource("filename.txt") method.
Upon reading the Java docs instructions, if your resource is not in the same package as the class you are trying to access the resource from, then you have to give it relative path starting with '/'. The recommended strategy is to put your resource files under a "resources" folder in the root directory. So for example if you have the structure:
src/main/com/mycompany/myapp
then you can add a resources folder as recommended by maven in:
src/main/resources
furthermore you can add subfolders in the resources folder
src/main/resources/textfiles
and say that your file is called myfile.txt so you have
src/main/resources/textfiles/myfile.txt
Now here is where the stupid path problem comes in. Say you have a class in your com.mycompany.myapp package, and you want to access the myfile.txt file from your resource folder. Some say you need to give the:
"/main/resources/textfiles/myfile.txt" path
or
"/resources/textfiles/myfile.txt"
both of these are wrong. After I ran mvn clean compile, the files and folders are copied in the:
myapp/target/classes
folder. But the resources folder is not there, just the folders in the resources folder. So you have:
myapp/target/classes/textfiles/myfile.txt
myapp/target/classes/com/mycompany/myapp/*
so the correct path to give to the getClass().getResource("") method is:
"/textfiles/myfile.txt"
here it is:
getClass().getResource("/textfiles/myfile.txt")
This will no longer return null, but will return your class.
It is strange to me, that the "resources" folder is not copied as well, but only the subfolders and files directly in the "resources" folder. It would seem logical to me that the "resources" folder would also be found under `"myapp/target/classes"
Supply the path relative to the classloader, not the class you're getting the loader from. For instance:
resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
In the hopes of providing additional information for those who don't pick this up as quickly as others, I'd like to provide my scenario as it has a slightly different setup. My project was setup with the following directory structure (using Eclipse):
Project/
src/ // application source code
org/
myproject/
MyClass.java
test/ // unit tests
res/ // resources
images/ // PNG images for icons
my-image.png
xml/ // XSD files for validating XML files with JAXB
my-schema.xsd
conf/ // default .conf file for Log4j
log4j.conf
lib/ // libraries added to build-path via project settings
I was having issues loading my resources from the res directory. I wanted all my resources separate from my source code (simply for managment/organization purposes). So, what I had to do was add the res directory to the build-path and then access the resource via:
static final ClassLoader loader = MyClass.class.getClassLoader();
// in some function
loader.getResource("images/my-image.png");
loader.getResource("xml/my-schema.xsd");
loader.getResource("conf/log4j.conf");
NOTE: The / is omitted from the beginning of the resource string because I am using ClassLoader.getResource(String) instead of Class.getResource(String).
When you use 'getResource' on a Class, a relative path is resolved based on the package the Class is in. When you use 'getResource' on a ClassLoader, a relative path is resolved based on the root folder.
If you use an absolute path, both 'getResource' methods will start at the root folder.
#GianCarlo:
You can try calling System property user.dir that will give you root of your java project and then do append this path to your relative path for example:
String root = System.getProperty("user.dir");
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt
String abspath = root+filepath;
// using above path read your file into byte []
File file = new File(abspath);
FileInputStream fis = new FileInputStream(file);
byte []filebytes = new byte[(int)file.length()];
fis.read(filebytes);
For those using eclipse + maven. Say you try to access the file images/pic.jpg in src/main/resources. Doing it this way :
ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());
is perfectly correct, but may result in a null pointer exception. Seems like eclipse doesn't recognize the folders in the maven directory structure as source folders right away. By removing and the src/main/resources folder from the project's source folders list and putting it back (project>properties>java build path> source>remove/add Folder), I was able to solve this.
resourcesloader.class.getClass()
Can be broken down to:
Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();
Which means you're trying to load the resource using a bootstrap class.
Instead you probably want something like:
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()
If only javac warned about calling static methods on non-static contexts...
Doe the following work?
resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")
Is there a reason you can't specify the full path including the package?
Going with the two answers as mentioned above. The first one
resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()
Should be one and same thing?
In Order to obtain real path to the file you can try this:
URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;
Resourceloader is classname here.
"resources/repository/SSL-Key/cert.jks" is relative path to the file. If you had your guiclass in ./package1/java with rest of folder structure remaining, you would take "../resources/repository/SSL-Key/cert.jks" as relative path because of rules defining relative path.
This way you can read your file with BufferedReader. DO NOT USE THE STRING to identify the path to the file, because if you have spaces or some characters from not english alphabet in your path, you will get problems and the file will not be found.
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(fileUrl.openStream()));
I made a small modification on #jonathan.cone's one liner ( by adding .getFile() ) to avoid null pointer exception, and setting the path to data directory. Here's what worked for me :
String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next();
Use this:
resourcesloader.class.getClassLoader().getResource("/path/to/file").**getPath();**
One of the stable way to work across all OS would be toget System.getProperty("user.dir")
String filePath = System.getProperty("user.dir") + "/path/to/file.extension";
Path path = Paths.get(filePath);
if (Files.exists(path)) {
return true;
}

Categories

Resources