Accessing .dat file from within a Jar file - java

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.

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");

Relative paths to getResourceAsStream method

I have a jav aproject which is build through ant. It write the class files to output/classes/com/... path. One of my java classes needs input stream read from a file that is in a folder one level above output folder. Looks like if copy the file to the package folder under outptu/classes, it seems to work. But I do not want to palce my config file in output folder as it will be cleaned when I do ant clean. I want it to find it look above the output folder, in config folder and load it.
public static final String CONFIG_FILE="/../../../../../../../Config.txt";
public static ConfigObj getConfigObj() throws IOException {
InputStream i=ConfigLoader.class.getResourceAsStream(CONFIG_FILE);
...
I want to know when I want to give raltivepath, what should it be relative to. I tried looking up , it says relative to classloader. What is classloader in this case? Is it output/classes/com....../config folder where my ConfigLoader.class lives?
The problem is that getResourceAsStream() will only load resources from the classpath. I guess you only have output/classes on your classpath, so you will never be able to load the config file via getResourceAsStream() if it's outside that directory. Use a File with an absolut path pointing to the file, or place it in your classpath.

Can getResourceAsStream() find files outside the jar file?

I'm developing an application that uses a library that loads a configuration file as:
InputStream in = getClass().getResourceAsStream(resource);
My application in then packed in a .jar file. If resource is inside the .jar file, I can specify the path as "/relative/path/to/resource/resource".
I'd like to know if is it possible to find the resource if it is outside the .jar file, and in this case, how would I specify the path.
(Assuming my application's jar is in app/ and the resource is in app/config).
The program uses a 3rd party library.
The library uses the resource as a configuration file.
I also want to tweak the configuration file without having to unzip/zip the jar file all the time.
In general, yes it can. Technically, the class's ClassLoader is used to locate the resource named in the parameter (see Javadoc here). If you're not using a special ClassLoader then you'll get the bootstrap class loader, which searches the class path. So, if you have directories or other jar files on the classpath, they will be searched.
It will get any resource which is available to the appropriate classloader (the one that getClass().getClassLoader() would return). Whether the classloader includes both the app directory and the jar files depends on the rest of your application context.
There is a way to get the current directory ( How to get the path of a running JAR file?), but for configuration you can just pass a -Dconfig.location to the JVM specifying an absolute path for the configuration

Accessing documents packaged in a jar file

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.

How do I reference a resource in Java?

I need to read a file in my code. It physically resides here:
C:\eclipseWorkspace\ProjectA\src\com\company\somePackage\MyFile.txt
I've put it in a source package so that when I create a runnable jar file (Export->Runnable JAR file) it gets included in the jar. Originally I had it in the project root (and also tried a normal sub folder), but the export wasn't including it in the jar.
If in my code I do:
File myFile = new File("com\\company\\somePackage\\MyFile.txt");
the jar file correctly locates the file, but running locally (Run As->Java Main application) throws a file not found exception because it expects it to be:
File myFile = new File("src\\com\\company\\somePackage\\MyFile.txt");
But this fails in my jar file. So my question is, how do I make this concept work for both running locally and in my jar file?
Use ClassLoader.getResourceAsStream or Class.getResourceAsStream. The main difference between the two is that the ClassLoader version always uses an "absolute" path (within the jar file or whatever) whereas the Class version is relative to the class itself, unless you prefix the path with /.
So if you have a class com.company.somePackage.SomeClass and com.company.other.AnyClass (within the same classloader as the resource) you could use:
SomeClass.class.getResourceAsStream("MyFile.txt")
or
AnyClass.class.getClassLoader()
.getResourceAsStream("com/company/somePackage/MyFile.txt");
or
AnyClass.class.getResourceAsStream("/com/company/somePackage/MyFile.txt");
If I have placed i file in a jar file, it only worked if and only if I used
...getResourceAsStream("com/company/somePackage/MyFile.txt")
If I used a File object it never worked. I got also the FileNotFound exception. Now, I stay with the InputStream object.

Categories