How to create a runnable jar that uses files and images as - java

I want to understand the best or the standard technique to write a java project when using internal files. To be precise, I want to develop a project that uses text files and images that are needed when the program runs. My goal is to create a runnable jar from the project in which the user does not need to see all these files. Therefore, I decided to create a package called resources and put it inside the folder that contains the source codes. I.e. it is in the same level as other packages. Now, in my codes when I want to use the images I use the following statement:
URL url = getClass().getResource("/resources/image1.gif");
It is working!
Then, to open a text file for reading/writing, I use the following:
String filename= "/resources/"+file1.txt;
Now, this is not working and it complains that it cannot find the file. I am not sure how to go about this?
A google search suggested that I put the resources folder on the project root directory. It is working then but when I created the runnable jar I had to put the resources folder on the same directory as the jar. This means that the user can have access to all the files in there. Any help is much appreciated.

You can use the getResource method for files too.
URL url = getClass().getResource("/resources/file1.txt");
try {
File f = new File(fileUrl.toURI());
} catch (URISyntaxException e) {
//dealing with the exception
}

Related

Java read and write to the resource folder

When someone opens my jar up I am opening a file selector gui so they can choose where they want to store their jar's files like config files and such. This should only take place the first time they open the jar. However, one issue with this approach is that I would have no way to know if it's their first time opening the jar since I will need to save the selected path somewhere. The best solution to this sounds like saving the selected path inside a file in the resource folder which is what I am having issues with. Reading and writing to this resource file will only need to be done when the program is actually running. These read and write operations need to work for packaged jar files (I use maven) and in the IDE.
I am able to read a resources file inside of the IDE and then save that file to the designated location specified in the file selector by doing this. However, I have not been able to do the same from a jar despite trying multiple other approaches from other threads.
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("config.yml");
try {
if(is != null) {
Files.copy(is, testFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
So just to clarify when my project is loaded I need to listen for the user to select a valid path for files like my config. Then I want to write my config to that path which I can do from my IDE and is shown above but I cant figure this out when I compile my project into a jar file since I always receive a file not found error in my cmd. However, the main point of this post is so that I can figure out how to save that selected path to my resource folder to a file (it can be json, yml or whatever u like). In the code above I was able to read a file but I have no idea how to go from that to get the files path since then reading and writing to it would be trivial. Also keep in mind I need to be able to read and write to a resource folder from both my IDE and from a compiled jar.
The following code shows my attempt at reading a resource from a compiled jar. When I added a print statement above name.startWith(path) I generated a massive list of classes that reference config.yml but I am not sure which one I need. I assume it has to be one of the paths relating to my project or possible the META-INF or META-INF/MANIFEST.MF path. Either way how am I able to copy the file or copy the contents of the file?
final String path = "resources/config.yml";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
try {
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path)) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
Also if you were wondering I got the above code from the following post and my first block of code I pasted above is actually in the else statement since the IDE code from that post also did not work.
How can I access a folder inside of a resource folder from inside my jar File?
You can't write to files inside your JAR file, because they aren't actually files, they are ZIP entries.
The easiest way to store configuration for a Java application is to use Preferences:
Preferences prefs = Preferences.userNodeForPackage(MyApp.class);
Now all you have to do is use any of the get methods to read, and put methods to write.
There is absolutely no need to write files into your resource folder inside a jar. All you need to have is a smart classloader structure. Either there is a classloader that allows changing jars (how difficult is that to implement?), or you just setup a classpath that contains an empty directory before listing all the involved jars.
As soon as you want to change a resource, just store a file in that directory. When loading the resource next time, it will be searched on the classpath and the first match is returned - in that case your changed file.
Now it could be that your application needs to be started with that modified classpath, and on top of that it needs to be aware which directory was placed first. You could still setup that classloader structure within a launcher application, which then transfers control to the real application loaded via the newly defined classloader.
You could also check on application startup whether a directory such as ${user.home}/${application_name}/data exists.
If not, create it by extracting a predefined zip into this location.
Then just run your application which would load/write all the data in this directory.
No need to read/write to the classpath. No need to include 3rd party APIs. And modifying this initial data set would just mean to distribute a new zip to be extracted from.

In netbeans, how to save or access an image after deploying jar file

I am trying to make a mess management application in Java using NetBeans. I want to save images of Members in a specified folder inside my src directory. I just created folder named EmpImgs for storing employees images. Here is my code:
File srcDir = new File(file); // current path of image
File dstDir = new File("src\\J_Mess_Mgnt\\EmpImgs\\"+Txt_C_G_M_M_ID.getText());
objm.copyFile(srcDir, dstDir);` // copy image from srcDir to dstDir
Here I use another class for copying images to predefined folders and renaming the images based on their ID.
Everything is working properly in Java IDE.
But unfortunately after making an executable .jar file, this code will not work. I cannot save or access any image file in that directory.
I just went through this site, but I didn't find a suitable answer.
All I need is saving and editing images inside jar folder
Hehe hi mate you need some help. This is a duplicate but I will cut you some slack and maybe you should delete this later. So back to basics, the jvm runs byte code, which you get from compiling java source code to .class files. Now this is different to C and C++ were you just get a .exe. You don't want to give your users a bunch of .class files in all these folders which they can edit and must run a command on the command line, but instead give them what is known as an 'archive' which is just an imutable file structure so they can't screw up the application, known as a jar in java. They can just double click on the archive (which is a jar), and the jvm will call the main method specified in the MetaInf directory (just some information about the jar, same as a manifest in other programming languages).
Now remember your application is now a jar! It is immutable! for the resasons I explained. You can't save anymore data there! Your program will still work on the command line and in IDEs because it is working as if you used your application is distrubuted as bunch of folders with the .class files, and you can write to this location.
If you want to package resources with your application you need to use streams (google it). BUT REMEMBER! you cant then save more resources into the jar! You need to write somewhere else! Maybe use a user.home directory! or a location specified from the class path and the photos will be right next to the jar! Sometimes you might need an installer for your java application, but usually you don't want to create the extra work if you don't need to.
At last I find an answer suit for my question.It is not possible to copy images or files to a executive jar folder.So I used a different Idea.Create some folders(as per our requirement),Where my executable jar folder is located(No matter which drive or where the location is).The code is..
String PRJT_PATH=""; //variable to store path of working directory.
private void getdire() throws IOException{
File f=new File(".");
File[] f1=f.listFiles();
PRJT_PATH=f.getCanonicalPath(); //get path details.for eg:-E:/java/dist
}
private void new_Doc_folder(){ //function for creating new folders
try{
String strManyDirectories="Docs"+File.separator+"Bil_Img"; //i need to create 2 folders,1st a folder namedDocs and In Docs folder another folder named Bil_Img
String SubDirectories="Docs"+File.separator+"EmpImgs"; //same as above but keep in mind that It will not create a Same folder again if already exists,
// Create one directory
boolean success = (new File(strManyDirectories)).mkdirs(); //create more than one directory
boolean success1 = (new File(SubDirectories)).mkdir(); //Creates a single directory
if (success && success1) {
}
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
It works Successfully.
Regds

Java code cannot find resource file after build and clean in Netbeans IDE?

I really need your help to solve my own problem. Now, I'm dealing with small code app. In that project folder contain some resource files (*.xlsx, *.png,...). I placed them in current folder with code file. I just wonder that when I run my code in netbean ide, it just worked find.
After I build code project, I get a jar file in "dist" directory. I run it. It open normally since app used JFrame as user interface. However, when I execute some function of that app, it showed me the error log. Here is the error message:
java.io.FileNotFoundException:
src\sample.xlsx (The system cannot find the path specified)
What's the matter out there?
Here is some pieces of my code:
copyFile(new File("src\\sample.xlsx"),
new File(txtout.getText()+"\\sample.xlsx"));
Node: copyFile function is used for copy file from source to dest.
Here is my project folder structure in Netbean IDE:
Project Name
Source Pakage(src)
myClass.java, sample.xlsx, etc
First, never reference src directly, the directory will not exist once the program is built. Second, you can not access resources which have been embedded within in the application context via a File reference, they simply no longer exist on the file system.
Instead, you need to use Class#getResource or Class#getResourceAsStream
URL url = getClass().getResource("/sample.xlsx");
InputStream is = getClass().getResourceAsStream("/sample.xlsx");
// Don't forget to manage your streams appropriately...
Well you can create a folder named resources under the src folder put your resources in it and use them in your code by using getResourceAsStream() and getResource() methods that can access the embedded resources.Clean and Build will compile the code and embed the contents of the resources folder into the application’s .jar file.
Ways of Accessing resources :
String pathToImage = "resources/images/filling.png";
InputStream stream= ClassName.class.getResourceAsStream(pathToImage );
String pathToImage = "resources/images/filling.png";
InputStream stream= ClassName.class.getResource(pathToImage );
please refer the link information

How to read file with different canonical paths

I am making an java application which reads a file from a particular location. The location of the file is in the folder retrived from
getCanonicalPath().
The problem i am facing is that when i am running my application in Eclipse the canonical path is different from the one which Dr Java sees. So, what should i do before delivering my application to the client to make sure that it sees the file no matter which ide/command prompt is used to run the application. Obviously it would not be a good idea to copy the same file across all possible folders to cover different possibilities of getCanonicalPath.
Thanks
One of the solution is to have this file in your classpath and load it from your classpath, with a code like
URL url = getClass().getClassLoader().getResource(path);
if(url != null) {
try {
return new File(url.toURI().getPath());
} catch (URISyntaxException e) {
return null;
}
}
This is standard if this file is a configuration file. Usually in a standard java project layout you put this in the folder src/main/resources.
If this is more of a data file, you should put in a configuration file its path, and have different configurations, one for your station and one for production on the client machine. Of course in this case the configuration file is in the class path ;).
A common solution is to place the file in a directory which is in the class path. If you use getResource or getResourceAsInputStream you can find the file regardless of where it is provided its in the class path. if you use maven you can be sure how the classpath is setup regardless of the IDE used.
You should always load file ClassLoader using API like Test.class.getClassLoader().getResource(name),Test.class.getClassLoader().getResourceAsStream(name) More Information available here

Where to put a textfile I want to use in eclipse?

I need to read a text file when I start my program. I'm using eclipse and started a new java project. In my project folder I got the "src" folder and the standard "JRE System Library" + staedteliste.txt... I just don't know where to put the text file. I literally tried every folder I could think off....I cannot use a "hard coded" path because the text file needs to be included with my app...
I use the following code to read the file, but I get this error:
Error:java.io.FileNotFoundException:staedteliste.txt(No such file or directory)
public class Test {
ArrayList<String[]> values;
public static void main(String[] args) {
// TODO Auto-generated method stub
URL url = Test.class.getClassLoader().getResource("src/mjb/staedteliste.txt");
System.out.println(url.getPath()); // I get a nullpointerexception here!
loadList();
}
public static void loadList() {
BufferedReader reader;
String zeile = null;
try {
reader = new BufferedReader(new FileReader("src/mjb/staedteliste.txt"));
zeile = reader.readLine();
ArrayList<String[]> values = new ArrayList<String[]>();
while (zeile != null) {
values.add(zeile.split(";"));
zeile = reader.readLine();
}
System.out.println(values.size());
System.out.println(zeile);
} catch (IOException e) {
System.err.println("Error :"+e);
}
}
}
Ask first yourself: Is your file an internal component of your application?
(That usually implies that it's packed inside your JAR, or WAR if it is a web-app; typically, it's some configuration file or static resource, read-only).
If the answer is yes, you don't want to specify an absolute path for the file. But you neither want to access it with a relative path (as your example), because Java assumes that path is relative to the "current directory". Usually the preferred way for this scenario is to load it relatively from the classpath.
Java provides you the classLoader.getResource() method for doing this. And Eclipse (in the normal setup) assumes src/ is to be in the root of your classpath, so that, after compiling, it copies everything to your output directory ( bin/ ), the java files in compiled form ( .class ), the rest as is.
So, for example, if you place your file in src/Files/myfile.txt, it will be copied at compile time to bin/Files/myfile.txt ; and, at runtime, bin/ will be in (the root of) your classpath. So, by calling getResource("/Files/myfile.txt") (in some of its variants) you will be able to read it.
Edited: Further, if your file is conceptually tied to a java class (eg, some com.example.MyClass has a MyClass.cfg associated configuration file), you can use the getResource() method from the class and use a (resource) relative path: MyClass.getResource("MyClass.cfg"). The file then will be searched in the classpath, but with the class package pre-appended. So that, in this scenario, you'll typically place your MyClass.cfg and MyClass.java files in the same directory.
One path to take is to
Add the file you're working with to the classpath
Use the resource loader to locate the file:
URL url = Test.class.getClassLoader().getResource("myfile.txt");
System.out.println(url.getPath());
...
Open it
Suppose you have a project called "TestProject" on Eclipse and your workspace folder is located at E:/eclipse/workspace. When you build an Eclipse project, your classpath is then e:/eclipse/workspace/TestProject. When you try to read "staedteliste.txt", you're trying to access the file at e:/eclipse/workspace/TestProject/staedteliste.txt.
If you want to have a separate folder for your project, then create the Files folder under TestProject and then access the file with (the relative path) /Files/staedteliste.txt. If you put the file under the src folder, then you have to access it using /src/staedteliste.txt. A Files folder inside the src folder would be /src/Files/staedteliste.txt
Instead of using the the relative path you can use the absolute one by adding e:/eclipse/workspace/ at the beginning, but using the relative path is better because you can move the project without worrying about refactoring as long as the project folder structure is the same.
Just create a folder Files under src and put your file there.
This will look like src/Files/myFile.txt
Note:
In your code you need to specify like this Files/myFile.txt
e.g.
getResource("Files/myFile.txt");
So when you build your project and run the .jar file this should be able to work.
Depending on your Java class package name, you're probably 4 or 5 levels down the directory structure.
If your Java class package is, for example, com.stackoverflow.project, then your class is located at src/com/stackoverflow/project.
You can either move up the directory structure with multiple ../, or you can move the text file to the same package as your class. It would be easier to move the text file.
MJB
Please try this
In eclipse "Right click" on the text file u wanna use,
see and copy the complete path stored in HDD like (if in UNIX "/home/sjaisawal/Space-11.4-template/provisioning/devenv/Test/src/testpath/testfile.txt")
put this complete path and try.
if it works then class-path issue else GOK :)
If this is a simple project, you should be able to drag the txt file right into the project folder. Specifically, the "project folder" would be the highest level folder. I tried to do this (for a homework project that I'm doing) by putting the txt file in the src folder, but that didn't work. But finally I figured out to put it in the project file.
A good tutorial for this is http://www.vogella.com/articles/JavaIO/article.html. I used this as an intro to i/o and it helped.
Take a look at this video
All what you have to do is to select your file (assuming it's same simple form of txt file), then drag it to the project in Eclipse and then drop it there. Choose Copy instead of Link as it's more flexible. That's it - I just tried that.
You should probably take a look at the various flavours of getResource in the ClassLoader class: https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html.

Categories

Resources