How to add resources into jar file - java

I need to add an exel file into my jar so it's portable. I know the answer is using getClass().getResource.... but i don't have a clue on how to go about using this code.
I have the exel file in the src folder with my class files, it works in netbeans but not when i open the jar file on another PC. i get filenotfound exception
here is the code i have used:
public class WindageLogic {
//....
public void GetValues() throws Exception
{
File exel=new File("src/Calculator/table1.xls");
Workbook w1; //reads from file
//reads from file
w1 = Workbook.getWorkbook(exel);
Can someone give me the code to implement which will allow me to access this file from the jar application, I've spent all weekend looking up stuff on the internet but i don't understand how i can use these getresource techniques.
thanks alot

If your excel file is a resource, then you can't use File to manipulate it but rather resources, and I believe that it is read-only -- are you sure that this is what you want to do? You could instead load a command line String that tells the program where to start looking for the file, or create a property file that tells where to first look.
Edit 1
If you are using JExcel then you can call Workbook.getWorkbook(java.io.InputStream is) and get your resource as a Stream via Class's getResourceAsStream(...) method.
e.g.,
public void GetValues() throws Exception {
Workbook w1; //reads from file
w1 = Workbook.getWorkbook(WindageLogic.class.
getResourceAsStream("/Calculator/table1.xls") );
//...

In order for the getClass().getResource() method to work the resource should be available in the classpath of the application (either packed in one of the jar files or simply on a folder on disk that is included in the classpath).
Depending on what IDE or code building tool you are using there are multiple ways of making sure it's done.
The simplest way is to put the src folder in the run classpath java -classpath src:%CLASSPATH% <your.class.name>

Related

Jar is not loading resources file

I have a project with a folder "src/main/resources" where inside there is the hibernate configuration file, I load it using this line of code
HibernateUtil.class.getResource("/hibernate.cgf.xml").getPath()
From inside the IDE it is working well, but when I create the jar it doesn't file the file.
How can I load it properly in the jar file too?
Thanks
Could you please try this:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileName").getFile());
I cannot say for ceratin that this is the issue without knowing how exactly you use the path extracted by:
HibernateUtil.class.getResource("/hibernate.cgf.xml").getPath()
but I can tell you this:
Run from an IDE the above line of code will return:
/path/to/project/src/main/resources/hibernate.cgf.xml
which is a valid filesystem path. You can then use this path to, for example, create an instance of File class and then use that instance to read the file contents.
However the same line of code run from inside a jar file will return:
file:/path/to/jar/jar_name.jar!/hibernate.cgf.xml
which is not a valid filesystem path. If you create an instance of File class using this path and then try to read the contents of the file you'll get an exception: java.io.FileNotFoundExeption
To read the contents of the file from inside of a jar you should use method Class.getResourceAsStream(String), which will return an instance of class sun.net.www.protocol.jar.JarURLConnection.JarURLInputStream (or equivalent in non-Oracle or non-OpenJDK Java). You can then use this object to read the contents of the file. For example:
InputStream inputStream = HibernateUtil.class.getResourceAsStream("/hibernate.cgf.xml");
Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
String fileContents = scanner.hasNext() ? sscanner.next() : "";
Most likely, the file is absent from the jar you create. There's too little information in your question, but I will try a guess:
Your hibernate.cgf.xml resides in the same directory as the Java sourcefles, and you are using a build tool (be it IDE, maven, gradle or an ant script) that expects resources to be stored in a separate directory.
It's easy to check: try to unzip your jar and see if the file is there (use any tool, you can just change the extension from .jar to .zip). I think you will see the file is absent.
Then come back with a question: "how to pack my non-java resources into a jar, using XXX", where XXX will be the name of the techology you are using for building the jar.
Most probably the slash in "/hibernate.cgf.xml" is not needed, if the hibernate.cgf.xml is in the same package as you class HibernateUtil.
You can access the file actually also via the classloader using the full path. Yet you never add to it the first slash.
Here is some code demonstrating how you can access the file using different methods:
public static void main(String[] args) {
// Accessing via class
System.out.println(SimpleTests.class.getResource("hibernate.cgf.xml").getPath());
// Accessing via classloader from the current thread
String path = Thread.currentThread().getContextClassLoader()
.getResource("simple/hibernate.cgf.xml").getPath();
System.out.println(path);
// Accessing via classloader used by the current class
System.out.println(SimpleTests.class.getClassLoader().getResource("simple/hibernate.cgf.xml").getPath());
}
In the example above the package 'simple' should be replaced by the package where your hibernate.cgf.xml is. But you should never have the slash at the beginning of the package declaration.

AbsolutePath not found when executing the JAR file but it works from the IDE [duplicate]

I need to add an exel file into my jar so it's portable. I know the answer is using getClass().getResource.... but i don't have a clue on how to go about using this code.
I have the exel file in the src folder with my class files, it works in netbeans but not when i open the jar file on another PC. i get filenotfound exception
here is the code i have used:
public class WindageLogic {
//....
public void GetValues() throws Exception
{
File exel=new File("src/Calculator/table1.xls");
Workbook w1; //reads from file
//reads from file
w1 = Workbook.getWorkbook(exel);
Can someone give me the code to implement which will allow me to access this file from the jar application, I've spent all weekend looking up stuff on the internet but i don't understand how i can use these getresource techniques.
thanks alot
If your excel file is a resource, then you can't use File to manipulate it but rather resources, and I believe that it is read-only -- are you sure that this is what you want to do? You could instead load a command line String that tells the program where to start looking for the file, or create a property file that tells where to first look.
Edit 1
If you are using JExcel then you can call Workbook.getWorkbook(java.io.InputStream is) and get your resource as a Stream via Class's getResourceAsStream(...) method.
e.g.,
public void GetValues() throws Exception {
Workbook w1; //reads from file
w1 = Workbook.getWorkbook(WindageLogic.class.
getResourceAsStream("/Calculator/table1.xls") );
//...
In order for the getClass().getResource() method to work the resource should be available in the classpath of the application (either packed in one of the jar files or simply on a folder on disk that is included in the classpath).
Depending on what IDE or code building tool you are using there are multiple ways of making sure it's done.
The simplest way is to put the src folder in the run classpath java -classpath src:%CLASSPATH% <your.class.name>

Reading file right outside jar

So I have a .jar file in a folder and I have some input files in that folder. However, the program looks for the file in the home folder (several layers up). I want it obviously to read it from the folder that it's in but I don't want to be explicit about the file path to my folder because other people won't necessarily put their .jar file in the same spot.
Is there a way to read a file directly outside of the jar file? If not, is there a way to do this without hard-coding the file path?
edit:
here's the code. It just checks if the input files exist.
package main;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
* Created by chris on 12/1/15.
* Control class that will be run when the jar is run.
*/
public class run {
public static void main(String[] args) throws Exception {
if (!(new File("settings.txt").exists())) {
start.run();
}
if (!(new File("api_key.txt").exists())) {
alert.display("Make your api_key.txt please.");
} else {
gatherData.run();
}
}
}
edit 2:
I've tried adding relative references with "./" at the beginning but that doesn't work either.
If you can rely on your .jar file being on the file system, you can get the absolute path of it by
new File(run.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
which can result in a SecurityException if a SecurityManager is present and not allowing this.
Another possibility would be to use
(new File(System.getProperty("java.class.path"))).getAbsolutePath();
The folder of the jar file can then be obtained using getParentFile()
If I am not wrong you are trying to access a file right in the same folder as that of the .jar file.
This can easily be done using the relative URL. By relative URL, I meant using
new File("./settings.txt"), this searches for the file in the folder same as that of the running .jar file. however you can use "../settings.txt" to look for the file one folder up.
"./" refers same directory "../" refers one directory up.
Just use ./ before file names.
The JAR files not neccesarly load from file system, and when loaded from file system can be any directory where the application start from - so relative path is not a good idea. The JAR files can from other types of source not only FileSystem, because it can be stream. I think the best way if there is a system parameter where you can pass the directory or working directory when you start the JAR file.

Referencing file from within the same JAR file as the application

I have a Java application in Eclipse that references .XML files as templates for other functionality. Usually I package the .JAR file without these files, because placing them within the same folder as the .JAR file seems to work fine with this reference:
File myFile = new File("templates/templateA.xsd");
I now require that these templates be placed within the same .JAR file as this application. I can include them with no problems, but these references no longer seem to work.
Is there a correct way of referencing the .XML file from within the same .JAR that the application is running from?
You need to know how to load the files from class path.
one of the ways is as follows
class XMLLoader {
public String loadXML(String fileName){
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
// do the loading of the file from the given input stream.
}
}
you know that the "templates" folder should be inside of your jar.
If you just need to read this file, you might not need a java.io.File but just an InputStream that you can get via
this.getClass().getResourceAsStream("templates/templateA.xsd")
If you really need a java.io.File... I do not know... The last time a really needed a File, I just copied the InputStream to a temporary file but this is ugly.

Open file; try filesystem first, then JARs

I'm trying to have my application load a resource (binary file) transparently:
If the file exists under the current directory, open it.
If not, try looking in the current JAR file if applicable.
If not, try looking in other JAR files. (This is optional and I don't mind explicitly specifying which JAR files.)
So far I know of File which opens a local file and ClassLoader which has getResource* for JAR contents.
Is there a class which combines the two? If not, how should I go about writing it myself? Should I write a ClassLoader which also checks the local filesystem? Using File? (I'm very unfamiliar with Java and don't even know what's a good type to return. InputStream?)
Thanks
P.S. By "file" I mean "path", e.g. "data/texture1.png".
Doing #1 and #3 is pretty easy. Doing #2 (just looking in the current JAR only) is much harder as it requires you figuring out what JAR you
If you wanted to check the filesystem first, otherwise load from classpath, it would be something like:
public java.io.InputStream loadByName(String name) {
java.io.File f = new java.io.File(name);
if (f.isFile()) {
return new FileInputStream(f);
} else {
return getClass().getResource(name);
}
}
If you want to prefer loading from the same JAR file first, you will need to figure out where it is. Check out Determine which JAR file a class is from for more info on figuring out the JAR file you want to load the resource from.
A URLClassLoader should be able to load both and try the file path first if the file path is on the class path ahead of the jar.
Regarding your comments:
I know that relative jar URLs don't
work. That's why the Spring guys came
up with the Resource abstraction.
Read about it here.
You might want to check the answers
to this Question: Loading a file
relative to the executing jar
file. The problem is similar to
yours.
Current jar file and current directory are not concepts in the JVM like they are when you're running a shell script. You would need to specify a directory to be used for loading the files that you're interested in, such as with a system property while executing the JVM:
java -Ddirectory.to.scan=/home/aib
Then retrieve this property:
String dir = System.getProperty("directory.to.scan");
Now when talking about JAR files, all JAR files specified explicitly on the classpath when you start the JVM are loaded by the ClassLoader. You can get the ClassLoader of a specific class by:
InputStream is = <Your class>.class.getClassLoader().getResourceAsStream("binary file");
Note that any jar file loaded by the current class loader is searched.

Categories