I have a products.jar file. Inside that there is one class com.ClassA. The structure of the project is like
products
|--test
|--com
|--ClassA.java
|--dependencies
|---inputs.txt
Inside eclipse, ClassA.java is accessing the inputs.txt file by the following path and it is working fine
private static final String PROPERTIES_FILE_PATH = "test/dependencies/inputs.txt";
test package is in the java build path -> sources
But when I am exporting this project as products.jar, I find that in the jar file there is no test directory. There are two dirs com and dependencies at the root of the jar file. So when I am trying to execute the ClassA (residing in jar file) through command line, I am getting the following exception:
JUnit version 4.8.2
java.io.FileNotFoundException: test/dependencies/inputs.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:137)
at java.io.FileInputStream.<init>(FileInputStream.java:96)
So after finding that test dir is not being exported in jar file, I changed the path of the file in my ClassA.java to dependencies/inputs.txt. It didn't work in eclipse but I thought that it would work in jar because jar file is in classpath and dependencies folder is at the root of the jar file so the java launcher will be able to locate the dependencies folder and then inputs.txt file.
But unfortunately it is also not working.
You can't use FileInputStream to read a file packed inside a JAR - it's not a file any more. FileInputStream only works for actual disk files.
You need to read the resource using Class.getResourceAsStream (javadoc), e.g.
InputStream stream = getClass().getResourceAsStream("/dependencies/inputs.txt");
You leave off the test prefix because it's not in the JAR file structure.
FileInputStream() will not read inside your jar, only files on the file system. Use .getClass().getResourceAsStream(resourcename) or .getClass().getClassLoader().getResourceAsStream(resourcename)
More info on the javadocs for class getResourceAsStream and classloader getResourceAsStream()
Related
I have a runnable jar file which is not able to access my resources which reside outside of the default src directory. Based on my understanding from What is the difference between Class.getResource() and ClassLoader.getResource(), I should be able to access root/res/img/img1.png (see folder setup below) by using the following getResourceFile function:
public class Foo {
private static final ClassLoader CLASS_LOADER = Foo.class.getClassLoader();
public static File getResourceFile(String relativePath) {
// Since I'm using getClassLoader, the path will resolve starting from
// the root of the classpath and it'll take an absolute resource name
// usage: getResourceFile("img/img1.png")
// result: Exception in thread "main" java.lang.NullPointerException
return new File(CLASS_LOADER.getResource(relativePath).getFile());
}
}
folder setup:
root/
src/
foo/
bar/
res/
img/
img1.png
audio/
audio1.wav
The problem arises when I try to execute the jar executable itself. However, the strange thing is that I was not able to replicate this through eclipse IDE which was actually able to resolve the path correctly. I have added the resource directory to the build path via (Project -> Properties -> Java Build Path -> Add Folder) so Java should be able to find the resource folder at runtime.
Is there something I'm missing in terms of generating the jar file? When unpacking the jar file everything seems to be in order with the img and audio directories being in the root (given the above initial folder setup):
foo/
/bar
img/
img1.png
audio/
audio1.wav
Files can only be used to represent actual files in your filesystem. And once you package your files into a JAR, the resource (img/img1.png) is not a file anymore, but an entry in the JAR file. As long as you use the folder structure from within Eclipse, the resources are individual files so everything is fine.
Try this:
System.out.println(CLASS_LOADER.getResource(relativePath));
It will print a URL, but it will not be a valid path to a file in your file system, but to an entry within the JAR file.
Usually, you will only want to read a resource. In that case, use getResourceAsStream() to open an InputStream.
Given a Spring Boot Maven Project with this structure:
src
main
resources
static
file.txt
This gets packaged into a jar file:
static
file.txt
I have tried the following ways to try to read file.txt:
File file = ResourceUtils.getFile("file.txt");
File file = ResourceUtils.getFile("/file.txt");
File file = ResourceUtils.getFile("static/file.txt");
File file = ResourceUtils.getFile("/static/file.txt");
None of these work.
It's a resource. Packaged inside a jar file. A File represents a path on the file system. So it can't represent an entry of a jar file.
Use MyClass.class.getResourceAsStream("/static/file.txt"). That uses the class loader, and thus loads resources from all the directories and jar files in the classpath.
So currently my netbeans project folders looks like this:
Block_Breaker <--Project
build
dist
Block_Breaker.jar
nbproject
src
packageONE
packageTWO
data.txt
manifest.mf
applet.policy
build.xml
I want to know how can i acces a data.txt file in packageTWO(when i run Block_Breaker through a jar file and not netbeans). Normally if run through netbeans the following code will work:
FileWriter x=new FileWriter("src/packageTWO/data.txt");
PrintWriter pr=new PrintWriter(x);
But if i run a jar file that netbeans created it doesnt work.
You can't write to that file once it is packaged into a jar file.
Yet reading is still possible using one of the following:
<YourClass>.class.getClassLoader().getResourceAsStream("packageTWO/data.txt");
// or
this.getClass().getResourceAsStream("/packageTWO/data.txt");
witch gives you an InputStream witch you can use to retrieve the content of the file.
If you are required to wite to that file then the simplest way is not to pack it into the jar but have it standalone some where on the filesystem.
More infos about getResourceAstream in the javadoc
This is because your .jar file does not include a folder named src/
Please use ClassLoader.getResource to load resources.
I have the problem running executable .jar file. I've created a project which contains a .properties file. It works just fine when I start it from eclipse, but when I export it to executable .jar file and try to run it with:
java -jar myfile.jar
I get the following exception:
(couldn't post image here)
http://imageshack.us/photo/my-images/824/29583616.png/
I've checked my manifest file in the .jar and it contains the
Class-Path: .
And here's the properties file loading:
properties = new Properties();
properties.load(new FileInputStream(
"src/com/resources/treeView.properties"));
Any idea what causes this exception?
If the properties file is inside the jar file, you cannot access it as a file.
You need to ask the classloader to get the resource as an inputstream. See Getting the inputstream from a classpath resource (XML file)
In Eclipse (and in most IDEs) the current directory is the project's root directory. This means that Class-Path: . means something else in Eclipse than when you run it from the command line. This is why you wrote "src/com/...". Remove "src":
properties.load(new FileInputStream("com/resources/treeView.properties"));
Your properties file is within JAR file. So, use : ClassLoader.getResourceAsStream().
I need to acces (create and read) a file from a JAR file (executable jar),
and that file should be created in the same directory as the JAR
I tried
this.getClass().getResource("myFile")
but since the jar has packages in it, it won't work..
I also tried write just
File f = new File("myFile");
f.createNewFile();
and that works if i execute the JAR from the terminal, but if i execute the JAR by double-clicking it, the file is created in my home directory -.-''
how do i access a file being SURE that that file is in the SAME directory as the JAR file?
(of course also getting the jar absolute path would do the trick since i can get the parent folder from it)
This will give you the full path to the Jar:
String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
EDIT: sorry, was in javascript mode when I wrote that :). As was so politely requested, in a static method you should be able to do this:
String path = Me.class.getProtectionDomain().getCodeSource().getLocation().getPath();
(where the class name is Me).