Accessing documents packaged in a jar file - java

Im trying to get the file path of a document that is packaged as a resource in a jar file so that i can display it in a swing application. The way I have it now works when I run it from eclipse but if I export it to a runnable jar file I can't access the the documents that are packaged in the jar file. How can I get the file path of the document when its inside the jar file?
Here is the line of code showing how I am trying to access the document:
File document = new File(getClass().getResource("/resources/documents/document.pdf").getPath());

The only kind of "file path" that exists for something inside a JAR file is the path relative to the root of the JAR. But in your case it seems that you know it already (it's "/resources/documents/document.pdf"). Files inside a JAR file have no path that you can use to access them directly as they don't exist within the real file system. You need to use either getResource() or getResourceAsStream() to access them. I don't remember right now which classes are used for images in Swing, but look closely at those classes - they should have overloaded methods that accept something like InputStream or URL instead of file path.

Related

File relative to jar using Spring

I work on a Java console application. There is a property in my application.properties file, which contains another file name as a value of a property, like
my.file.location=file:myDir/myFileName
In the code I try to get the file like this:
#Value("${my.file.location}")
private File myfileLocation;
If I start the application from the directory, which contains jar file, the file is resolved, but when I run my application from a different location, the file location is not valid.
I can't have this file on classpath, it must be external to the jar file.
How can I make the file path to be relative to my jar file and not to the current working directory?
I believe this has nothing to do with Spring right? You just want to load configuration file, that is inside your application, unpacked, so the user can modify it, ok?
First, you may try to always setup the working directory, which I believe is more "standard" solution. In windows you can make a link, that specifies the Start in section and contains the path to your jar file (or bat or cmd, whatever).
If you insist on using the jar path, you could use How to get the path of a running JAR file solution. Note, that the jar must be loaded from filesystem:
URI path = MySpringBean.class.getProtectionDomain().getCodeSource().getLocation().toURI();
File myfileLocation = new File(new File(path).getParent(), "/myDir/jdbc.properties");

Creating and executable JAR file that uses an external XML file

I have a java application in Eclipse that uses an eml file like so
File matches = new File("matches.xml");
The file is located in the default package as all the other classes. When I create the JAR it bundles in the XML file with it. My application require me to be able to make changes to the XML file. How can I set it up so the JAR can reference the XML file outside of itself?
My application require me to be able to make changes to the XML file.
Then you will need to extract it from the Jar and save it somewhere on the local file system.
See How can an app use files inside the JAR for read and write? for more details.
If you're using new File("matches.xml") that won't use a file within a jar file at all. It will only look on the external file system.
If you need to be able to use an external file if it's present, or the version in the jar file as a fallback, you'll need to test for the file's existence (File.exists()) and use Class.getResourceAsStream("matches.xml") for the fallback behaviour.
As you want to keep the file outside the jar and want to update it so the jar can read, so you can put the file in the same directory where the jar is and use the following code to access the file
FileInputStream file = new java.io.FileInputStream("matches.xml");
So this can be the directory structure.
- matches\
- matches.jar
- matches.xml

finding static file in jar

I am trying to use a jar file which itself is a web application in another web project. In my jar which i have created using eclipse's export to jar functionality, I have stored a csv file in a folder. To use relative paths in the code in the jar I access it using
MyClass.class.getResource(ApplicationConstants.ALIASESFILE).getPath();
and this works fine when I deploy (glassfish) and use the project as a separate application. But when I am using the same from within another project, it gives a path as shown below
D:\javaProjects\AutomodeGS_Prachi\lib\internal\RESTWSGS.jar!\aliases\aliases.csv
I am getting a file notfound exception.What could be wrong?
The getResource() method is returning a "jar:" URL. The path component of that URL is not a normal filesystem pathname, and can't be opened directly using Java's file classes.
The simple way to do this is to use Class.getResourceAsStream(...) to open the stream. If you need an "identifier" for the JAR entry, use Class.getResource(...), but then open the stream using URL.openStream().
This works fine from glassfish may be because glassfish has exploded jar on file system so that your csv file is acutually a file to the file system,
if you try to read it from another project it fails because the jar containing your file is in classpath that is fine, but the csv file is under jar file and it is no longer a File
You can read it as Stream
InputStream is = MyClass.class.getResourceAsStream(ApplicationConstants.ALIASESFILE);

Accessing .dat file from within a Jar file

I am trying to access a data file from a public class, both of which are located within a JAR file. However, when I execute the jar on a Hadoop cluster, the system throws a FileNotFoundException. The bottom line is: is it possible to access resources within a Jar when running an application on a cluster, or does the resource need to be copied to the HDFS individually, and for either of the above, how would you go about implementing it?
Thanks!
Yes, if the JAR is in the CLASSPATH you can call getResourceAsStream() using a class loader or servlet context to get a reference to an InputStream for that file.
You will NOT have access to the file path. You give a path relative to the CLASSPATH and the classloader finds the file. You can get the contents, but not the absolute location.
You shouldn't want the absolute location. What will you do with it?
You can't write to the file. You can't alter anything. If your app is packaged in a WAR file, you can't alter its contents.

Java JAR: Writing to a file

Currently, in my eclipse project, I have a file that I write to. However, I have exported my project to a JAR file and writing to that directory no longer works. I know I need to treat this file as a classpath resource, but how do I do this with a BufferedWriter?
You shouldn't have to treat it as a classpath resource to write to a file. You would only have to do that if the file was in your JAR file, but you don't want to write to a file contained within your JAR file do you?
You should still be able to create and write to a file but it will probably be relative to the working directory - the directory you execute your JAR file from (unless you use an absolute path). In eclipse, configure the working directory from within the run configuration dialog.
You're probably working in Linux. Because, in Linux, when you start your application from a JAR, the working directory is set to your home folder (/home/yourname/). When you start it from Eclipse, the working directory is set to the project folder.
To make sure you really know the files you are using are located in the project folder, or the folder where your JAR is in, you can use this piece of code to know where the JAR is located, then use the File(File parent, String name) constructor to create your files:
// Find out where the JAR is:
String path = YourClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
path = path.substring(0, path.lastIndexOf('/')+1);
// Create the project-folder-file:
File root = new File(path);
And, from now on, you can create all your File's like this:
File myFile = new File(root, "config.xml");
Of course, root has to be in your scope.
Such resources (when altered) are best stored in a sub-directory of user.home. It is a reproducible path that the user should have write access to. You might use the package name of the main class as a basis for the sub-directory. E.G.
our.com.Main -> ${user.home}/our/com/

Categories