Reading txt files within a jar - java

I've already looked at many other questions that are similar to mine, but unfortunately none of their answers have so far worked.
I have a Java project that looks like this:
MyProject/
src/
abc/
MyClass.java
xyz/
file1.txt
file2.txt
...
Essentially, I'm trying to read all of the txt files above in MyClass.java. This is what I'm currently doing:
File dir = new File("src/xyz/");
for (File child : dir.listFiles()) {
...
}
This works fine until I put everything into a JAR format, at which point dir.listFiles() returns null and the above no longer works. Is there anyway I can still read these txt files even when they are packed into a JAR? Also, I am using Eclipse if it makes any difference.

You can access files on your classpath via the classloader.
getClass().getResourceAsStream("/xyz/file1.txt");
Then you would use the InputStream as usual. Note that I use absolute path, but relative to the current package works as well.
Since Java 6 it is also possible to list all the resources under a package quite easily:
Enumeration urls = getClass().getClassLoader().getResources("xyz");
urls.nextElement().openStream();

Is there anyway I can still read these txt files even when they are packed into a JAR?
Given you mean 'without knowing their names in advance' no.
OTOH you can include a resource at a known location in a Jar and list the possibles texts in that. Path from root or class-path, one per line would work well. Gain an URL to the resource using something like:
URL url = this.getClass().getResource("/path/to/the.resource");

Related

NPE while try to get Resource in jar

I have tried many variants but I cant find correct.
I have something like
Inside my jar, which created by Maven I can see that
That is my folder with classes. And, by the way, If I start my program in IDEA, not from Console, there is not any exception with paths
Here, I am in debug mode start my jar trying to see, where is the problem.
If I do 'file.exists()' it would be false but file inside. I think, that problem because of '.jar!\' in the path, but I don`t know how to remove that.
Anyway I've tried absolute and relative path, I've tried
Thread.getCurrentThread.getContextLoader.getResource()
GUI.class.getResource()
GUI.class.getClassLoader.getResource()
Nothing help
You can't use File to open resources inside a jar file. File can only be used with normal files and directories.
Note: using File works fine within in the IDE, since all files are not packaged in a jar file yet. But the program will break after you package it.
Once you locate the resource eg. URL res = GUI.class.getResource("/rxtx64/myres.dll") , you can open that resource as a stream InputStream is = res.openStream(); .
See also related answers Utils to read resource text file to String (Java) and How to read a text-file resource into Java unit test?

how to find a local resource from dependent jar?

I have written a code that is packed to 1.jar
with this code:
return isProd? "/etc/waze/automation/devices.json":
DeviceRepositoryFromJsonFile.class.getClassLoader().getResource("devices.json").getPath().toString();
devices.json is here:
I have another project that depends on 1.jar
however the classLoader doesn't find the local devices.json file but rather one packed in the jar
anyhow it shows the file doesn't exist.
How can I fix this? just use a absolute path anyhow?
If as in your screenshot the devices.json locate in the src/main/resources and the package have successfully treat that as the package path and put in the jar file root directory, then you can just find the file via:
DeviceRepositoryFromJsonFile.class.getResource("/devices.json");
Note the "/" slash is important to indicate that to search from the root of the classpath.
It does not answer your question directly, but it may solve your problems faster.
As far as I can see you try to detect the absolute path to json file and pass it to another method so this file could be processed. Instead, it could be done simpler:
public byte[] getDevicesJsonBytes() {
return isProd
? IOUtils.toByteArray(ABSOLUTE_PATH_TO_PROD_FILE)
: IOUtils.toByteArray(DeviceRepositoryFromJsonFile.class.getResourceAsStream(RESOURCE_CLASSPATH);
}
The common way to read classpath resources it to use getResourceAsStream on class or classLoader instance. Also, many frameworks have their own resources abstractions, but I guess you don't need them now.

Getting location of file as string in resource folder

I have completed a program in eclipse and now I would like to export it as a single runnable jar file. The program contains a resource folder with images and text files in it. This is located beneath the source folder.
The res file is not added to the build path however when I run the program in Eclipse it still works.
The thing that is confusing me is that the res file is being saved into the runnable jar file when I export it as I can open the Jar file with WinRar and I see the folder is there with all the objects in it. But when I run the problem it stops at the point that the resource folder is referenced. To add to my confusion when I manually copy and paste the res folder next to where the runnable jar file is saved and run the program it works exactly as it should do.
Now I know this is something to do with how I reference the files in my code. At the moment I have it like this
reader = new LineNumberReader(new FileReader("res/usernames.txt"));
This works exactly how I want and accesses the res folder without any exceptions - in Eclipse and when I move the resource folder next to the Jar file.
I would like it to work normally but without having a folder outside of the Jar file I would like it all encapsulated in one Jar file.
I did a lot of research and what seems to be a common fix - may I add I don't really know how it works but everyone seems to mention it - is to somewhere use:
myClass().getResource()
When I create a new FileReader it needs a String input however when I use myClass().getResource() it returns a resource and not a string. I also don't have a clue how it is meant to reference the resource folder. Should I move the resource folder into the source folder?
Does anyone know how I can reference the resource folder from within the runnable jar file?
Sorry for rambling question I know what I want for my final product but I'm getting confused by the build paths and referencing from within classes and I have searched online for a long time trying to figure it out.
Resources, when you deploy your software, are not deployed as files in a folder. They are packaged as part of the jar of your application. And you access them by retrieving them from inside the jar. The class loader knows how to retrieve stuff from the jar, and therefore you use your class's class loader to get the information.
This means you cannot use things like FileReader on them, or anything else that expects a file. The resources are not files anymore. They are bundles of bytes sitting inside the jar which only the class loader knows how to retrieve.
If the resources are things like images etc., that can be used by java classes that know how to access resource URLs (that is, get the data from the jar when they are given its location in the jar), you can use the ClassLoader.getResource(String) method to get the URL and pass it to the class that handles them.
If you have anything you want to do directly with the data in the resource, which you would usually do by reading it from a file, you can instead use the method ClassLoader.getResourceAsStream(String).
This method returns an InputStream, which you can use like any other InputStream - apply a Reader to it or something like that.
So you can change your code to something like:
InputStream is = myClass().getResourceAsStream("res/usernames.txt");
reader = new LineNumberReader( new InputStreamReader(is) );
Note that I used the getResourceAsStream() method from Class rather than ClassLoader. There is a little difference in the way the two versions look for the resource inside the jar. Please read the relevant documentation for Class and ClassLoader.

Java & JTar - how to add a file inside a folder using JTar?

Windows - I am trying to create a new Tar file with with the JTar lib with the following inside...
MyTarFile.tar--|
|--MyFolder--|
|--MyFile.zip
I can create it with the folder and the zip file right in the root of MyTarFile but I don't know (and I looked around) how to create that folder AND have the zip file inside. I need to know what to use (the File object(s)) for the TarEntry(s) (is it one for folder and one for file...or one for both?) and what the InputStream should look like (I believe just a single one for the zip file but not sure). I am trying to create a file to mimic an existing format so I don't have the option of just losing that folder as the software that uses the file will be looking for it. I can add the zip file to the MyFolder folder on the actual file system (again, this is on Windows) before tarring or not...whatever works is fine.
I have tried full paths and relative paths (seems the InputStream MUST have a full path though) with no luck. Running out of ideas other than switching libraries (perhaps JTar doesn't support this).
Thanks!
Without seeing what you have already written, here is my best attempt at answering. I am unfamiliar with JTar, but after taking a look at the example on their main page, I wrote a quick test program that created a tar with one file in the root of the tar and one file in a directory in the tar, which I believe is what you are attempting to do. The code of interest to you is this:
TarEntry tarEntry = new TarEntry(new File("/Users/userGuy/Documents/students.xml"),"students.xml");
TarEntry otherTarEntry = new TarEntry(new File("/Users/userGuy/Documents/students2.xml"),"inner-dir/students2.xml");
Note that the second tar entry, otherTarEntry is instantiated with a relative path as the entryName argument in the TarEntry constructor. This is a poorly named argument, as it is technically the path of the file in the tar, not just the name.
With your example file names above, your code might look something like this:
TarEntry tarEntry = new TarEntry(new File("<path to file>"),"MyFolder/MyFile.zip");

Get path of a file from a subdirectory of a directory in CLASSPATH

Given the following directory structure:
working-directory
subfolder1
file1.wav
file2.wav
file3.wav
subfolder2
file4.wav
file5.wav
file6.wav
subfolder3
file7.wav
file8.wav
file9.wav
jar-that-im-running.jar
I need to get the path to each wav file. I figured that since the folder is in the working directory, and is thus part of the classpath (if my assumption is wrong, I'd just add the working directory to the classpath), I could just run:
String path = ClassLoader.getSystemResource("file1.wav");
or
String path = ClassLoader.getSystemResource("/file1.wav");
but it wouldn't work, unless I specified the folder the wave file was in. This would be fine, but I wouldn't know what folder each wave file is in; I only know their names. I'm going to process all the files one way or another, but the order that I do depends on a config file. Also, I am not going to edit these files directly. Instead, I'm going to be passing them off as arguments to a ProcessBuilder. Since some of the directories in the path may have spaces, which get converted to %20 in URLs, I figured I could convert them with path.replaceAll("%20", " "). Will I be better off using files, or is there a way to get a specific wav file, without knowing its parent folder.
Did you try getting from the class loader as a system resource? Here's a snippet of code to illustrate:
String path = ClassLoader.getSystemResource("subfolder1/file1.wav");

Categories