Get resource(jar) path in java - java

I have a class XYZ in application that is executed as jar in any directory. I want to find the current directory path in which jar is executing for this I have used following code.
String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
I write this code in public constructor of XYZ class but it is not working though I am using it since long time it works fine, but now it is not returning the current directory path.
please mark and suggest what is going wrong in this.

When you execute your statement within "this" - it means that you are trying to locate current instance of the class but you need to find the class itself.
In your case you can use this:
String path = XYZ.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
It will give you the path you are looking for and will solve issues with whitespaces and special characters inside this path.
In case you are doing this for Linux it might be useful to use:
URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(‌​), "UTF-8");

...but now it is not returning the current directory path.
It shouldn't return the current directory path. It should return the path of the jar file the class is coming from, or the root folder where the class files are loaded from (if not packed in a jar). It might and it might not be the current folder.
Calling
this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
will try to locate the path the class of the current instance (this) is coming from.
Make sure that the Class you start from is part of the jar file. E.g. do not use this but use an explicit class which you're sure is from the jar file, e.g.
SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath()
Also note that this won't work if you start the application from your IDE in which case the result would be the bin folder (the root folder of compiled class files).

return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
OR
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath().toURI());

Related

How to read a file that is located in any location on the computer?

So I have a project, and this is one of the demands:
You should have a class named Project3, containing a main method.
This program reads the levels information from a file whose name is
specified as a command-line parameter (The file should also be
relative to the class-path as described here:)
All the file names specified in the levels and block definition files
should be relative to the class path. The reason we want them to be
relative to the class path is that later we will be able to read the
files from inside a jar, something we can not do with regular File
references.
To get an input stream relative to the class path (even if it's inside
a jar), use the following:
InputStream is =
ClassLoader.getSystemClassLoader().getResourceAsStream("image.png");
The idea is to keep a folder with files(definitions and images) and
then add that folder to the class path when running the JVM:
java -cp bin:resources ... If you don't add the resources folder to
you class path you wont be able to load them with the command from
above.
When run without parameters, your program should read a default level
file, and run the game accordingly. The location of the default level
file should be hard-coded in your code, and be relative to the
classpath_.
When run without parameters, your program should read a default level file, and run the game accordingly. The location of the default level file should be hard-coded in your code, and be relative to the classpath_.
The part of the code that handles the input is:
public Void run() throws IOException {
LevelReader level = new LevelReader();
List<level> chosenLevels = new ArrayList<>();
if (args.length >= 1) {
File f = new File(args[0]);
if (f.exists()) {
chosenLevels = level.makeLevel(args[0]);
}
}
if (chosenLevels.size() == 0) {
game.runLevels(defaultLevels);
} else {
game.runLevels(chosenLevels);
}
return null;
}
So my question is:
An argument should be the full path of a file which means:
D:\desktop\level3.txt
Is it possible to read a file from every location on my computer?
Because right now I can do it only if my text file is in the
project's directory (not even in the src folder).
I can't understand the rest of their demands. What does is mean "should be hard-coded in your code, and be relative to the
classpath_." and why is it related to InputStream method(?)
I'm confused all over this.
Thanks.
A classpath resource is not the same as a file.
As you have correctly stated, the full path of a file is something like D:\desktop\level3.txt.
But if ever want to distribute your application so it can run on other computers, which probably won’t have that file in that location, you have two choices:
Ask the user to tell the program where to find the file on their computer.
Bundle the file with the compiled program.
If you place a non-.class file in the same place as .class files, it’s considered a resource. Since you don’t know at runtime where your program’s class files are located,¹ you use the getResource or getResourceAsStream method, which is specifically designed to look in the classpath.
The getResource* methods have the additional benefit that they will work both when you are developing, and when the program is packaged as a .jar file. Individual entries in a .jar file are not separate files and cannot be read using the File or FileInputStream classes.
If I understand your assignment correctly, the default level file should be an application resource, and the name of that resource is what should be hard-coded in your program. Something like:
InputStream is;
if (args.length > 0) {
is = new BufferedInputStream(
new FileInputStream(args[0]));
} else {
// No argument provided, so use program's default level data.
is = ClassLoader.getSystemClassLoader().getResourceAsStream("defaultlevel.txt");
}
chosenLevels = level.makeLevel(is);
¹ You may find some pages that claim you can determine the location of a running program’s code using getProtectionDomain().getCodeSource(), but getCodeSource() may return null, depending on the JVM and ClassLoader implementation, so this is not reliable.
To answer your first question, it doesn't seem like they're asking you to read from anywhere on disk, just from within your class path. So that seems fine.
The second question, "What does is mean 'should be hard-coded in your code, and be relative to the classpath'?". You are always going to have a default level file in your project directory. Define the path to this file as a String in your program and that requirement will be satisfied. It's related to the InputStream because the stream requires a location to read in from.

Error message: The file "countries.geo.json" is missing or inaccessible

I am taking the Coursera OOP in Java class. In the module 4 assignment, I run the code that the course provides in EarthquakeCityMap.java,
and I get an error as "The file "countries.geo.json" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.
Exception in thread "Animation Thread" java.lang.NullPointerException"
I tried to set countryFile as
"../data/countries.geo.json",
"data/countries.geo.json",
and the complete path of countries file,
but still didn't solve the problem.
//this error points to the code
private String countryFile = "countries.geo.json";
List<Feature> countries = GeoJSONReader.loadData(this, countryFile);"
//the countries file is saved in data folder.
Poject folder listing
"countries.geo.json" (unless changed in GeoJSONReader manipulates this path) will be relative to the compiled java .class files in the IntelliJ's project out folder.
If this in GeoJSONReader.loadData(this, countryFile); is a PApplet instance you can use sketchPath() to make that path relative to the folder from which the sketch runs:
List<Feature> countries = GeoJSONReader.loadData(this, this.sketchPath("data"+File.separator+countryFile));
The above snippet is based on an assumption so the syntax in your code might be slightly different, but hopefully this illustrates how you'd use sketchPath().
Additionally there's a dataPath() as well which you can test from your main PApplet in setup() as a test:
String fullJSONPath = dataPath("countries.geo.json");
println("fullJSONPath: " + fullJSONPath);//hopefully this prints the full path to the json file on your machine
println(new File(fullJSONPath).exists());//hopefully this prints true
If you specified the full path and it didn’t work, you probably forgot to escape the \ character with another backslash. The backslash character is special and needs to be doubled for windows path to be interpreted properly. For instance “c:\\users\\...”. You can also specify / instead of \ and it would work : “c:/users/...”
That said, the path resolution of a file when relative (IE not being absolute to the file system root) is relative to the working directory of the executed app. Typically, in an IDE without any special configuration, the working directory would be the root path of the project. So in order to get the relative file path resolved properly, you would have to specify the path as “data/countries.geo.json”.
You can also find out what path you are in when you run the app by doing a System.out.println(new java.io.File(“.”).getAbsolutePath()) and craft the relative path according to this folder.

How to get the path to the java file with the main method (src dir) [duplicate]

I need to get a resource image file in a java project. What I'm doing is:
URL url = TestGameTable.class.getClass().
getClassLoader().getResource("unibo.lsb.res/dice.jpg");
The directory structure is the following:
unibo/
lsb/
res/
dice.jpg
test/
..../ /* other packages */
The fact is that I always get as the file doesn't exist. I have tried many different paths, but I couldn't solve the issue.
Any hint?
TestGameTable.class.getResource("/unibo/lsb/res/dice.jpg");
leading slash to denote the root of the classpath
slashes instead of dots in the path
you can call getResource() directly on the class.
Instead of explicitly writing the class name you could use
this.getClass().getResource("/unibo/lsb/res/dice.jpg");
if you are calling from static method, use :
TestGameTable.class.getClassLoader().getResource("dice.jpg");
One thing to keep in mind is that the relevant path here is the path relative to the file system location of your class... in your case TestGameTable.class. It is not related to the location of the TestGameTable.java file.
I left a more detailed answer here... where is resource actually located

File not found?

I have an assignment and we have a couple of classes given, one of them is a filereader class, which has a method to read files and it is called with a parameter (String) containing the file path, now i have a couple of .txt files and they're in the same folder as the .java files so i thought i could just pass along file.txt as filepath (like in php, relatively) but that always returns an file not found exception!
Seen the fact that the given class should be working correctly and that i verified that the classes are really in the same folder workspace/src as the .java files i must be doing something wrong with the filepath String, but what?
This is my code:
private static final String fileF = "File.txt";
private static final ArrayList<String[]> instructionsF =
CreatureReader.readInstructions(fileF);
Put this:
File here = new File(".");
System.out.println(here.getAbsolutePath());
somewhere in your code. It will print out the current directory of your program.
Then, simply put the file there, or change the filepath.
Two things to notice:
check if "File.txt" is really named like that, since it won't find "file.txt" -> case sensitivity matters!
your file won't be found if you use relative filenames (without entire directory) and it isn't on your classpath -> try to put it where your .class files are generated
So: if you've got a file named /home/javatest/File.txt, you have your source code in /home/javatest/ and your .class files in that same directory, your code should work fine.
If you class is in package and you have placed the files as siblings then your path must include the package path. As suggested in other answers, print out the path of the working directory to determine where Java is looking for the file relative from.

Get a resource using getResource()

I need to get a resource image file in a java project. What I'm doing is:
URL url = TestGameTable.class.getClass().
getClassLoader().getResource("unibo.lsb.res/dice.jpg");
The directory structure is the following:
unibo/
lsb/
res/
dice.jpg
test/
..../ /* other packages */
The fact is that I always get as the file doesn't exist. I have tried many different paths, but I couldn't solve the issue.
Any hint?
TestGameTable.class.getResource("/unibo/lsb/res/dice.jpg");
leading slash to denote the root of the classpath
slashes instead of dots in the path
you can call getResource() directly on the class.
Instead of explicitly writing the class name you could use
this.getClass().getResource("/unibo/lsb/res/dice.jpg");
if you are calling from static method, use :
TestGameTable.class.getClassLoader().getResource("dice.jpg");
One thing to keep in mind is that the relevant path here is the path relative to the file system location of your class... in your case TestGameTable.class. It is not related to the location of the TestGameTable.java file.
I left a more detailed answer here... where is resource actually located

Categories