Get contents of a directory in a ZIP file in Java - java

I have some default configuration files inside my application jar that I would like to save to the file system if they don't already exist. I would like it to keep the directory structure too. Example:
Jar file
-configs/
-main-config.cfg
-another-file.txt
-stuff/
-another-file.cfg
-com/
-META-INF/
I would like the contents of configs/ to be mirrored to the file system, including the subfolder.

Use JarFile.entries to get an enumeration of all of the entries in your Jar file.

Related

Java listFiles in directory in jar

Is there any way to use listFiles() on a directory that's been packaged into a jar?
Let's say I have a directory in my resource directory with some text files: texts/text1.txt and texts/text2.txt.
And within this Java program I have a class that needs to use listFiles() to get a list of those files. I'll get something like jar:file:/home/soupkitchen.jar/!text. I'd expect that to be a directory. Is there any way to be able to treat it as a java.io.File directory containing files? Right now it seems to only be listed as neither a file nor directory.
No. java.io.File can only be used to list real directories.
However, you can treat it as a java.nio.file.Path.
Overall, you have three options:
Open the .jar as a Zip File System and use Files.newDirectoryStream or Files.list.
Iterate through all entries in the .jar file, looking for names that match.
Put a text file in your .jar that contains the names of all the entries in the directory, so you don't have to try to list them.

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

How to fix this java.io.FileNotFoundException?

I'm trying to load a .csv file in a program but for some reason, it's unable to find the file. Where should I place the file?
Console
It looks like the file is in the src directory... which almost certainly isn't the working directory you're running in.
Options:
Specify an absolute filename
Copy the file to your working directory
Change the working directory to src
Specify a relative filename, having worked out where the working directory is
Include it as a resource instead, and load it using Class.getResourceAsStream
The file is located in the src directory so in order to access it you should use
src/Elevator.csv
As long as files are located inside your project folder you can access them using relative paths.
For example if a file is located under the Elevator folder then you access the file by using only its filename.
Elevator.csv
A good principle when using additional files in your project is creating separate folders from the ones that the source files are located. So you could create a folder resources under the project folder and place your file there. You can access then the file by using
resources/Elevator.csv
the path which it is trying to read is surely not exact as the path in which that file is actually present.Try printing absolute path of that file and compare it with actual path of your file.
I tried with all the above mention solution, but it didn't work..
but i went to my project folder and delete the target and tried to compile the project again. it then worked successfully

access files and folders in executable jars

I am facing the following problem:
I use Eclipse for my Java projects and there I have the following structure:
--> src
--> package1
....
--> package2
...
-->dataFolder
--> Folder1
--> file1.xml
--> Folder2
file2.xml
In my java project I parse all files in the dataFolder directory. This is no problem because I can just use the root directory of the eclipse project, like this:
File dataStoreFolder = new File("dataFolder");
Some parsing......
But when I export my project as an executable jar file, I can not access these files anymore. Of course thats because they are not in the same folder where I put my exec.jar file. But I do not want to copy the whole folder with the data to my exec.jar file. Can I put it somehow inside my jar file? (I did it by adding the dataFolder to the Java Build Path but it still does not work as it does in Eclipse)
Can someone help me please?
When you're using a jar file, those files don't exist as files any more.
You can absolutely include the data in your jar file, but then you'll need to change the code which accesses it, too. Instead of creating a File object, you'll need something like:
InputStream input = Foo.class.getResourceAsStream("/dataFolder/Folder1/file.xml");
So you have two separable tasks:
Work out how to include the data folder within your jar file
Change your code to access the data appropriately
Yes, you can put them in your jar file. Just make dataFolder a source folder under Eclipse, and it will copy the non-Java files to the target directory, and add them to the jar file.
Once in the jar file, you would get file1.xml like this:
InputStream in = SomeClass.class.getResourceAsStream("/Folder1/file1.xml");

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