Reading a resource file from within jar
Rather than trying to address the resource as a File just ask the ClassLoader to return an InputStream for the resource instead via getResourceAsStream:
try (InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
// Use resource
}
As long as the file.txt
resource is available on the classpath then this approach will work the same way regardless of whether the file.txt
resource is in a classes/
directory or inside a jar
.
The URI is not hierarchical
occurs because the URI for a resource within a jar file is going to look something like this: file:/example.jar!/file.txt
. You cannot read the entries within a jar
(a zip
file) like it was a plain old File.
This is explained well by the answers to:
- How do I read a resource file from a Java jar file?
- Java Jar file: use resource errors: URI is not hierarchical
Load a resource contained in a jar
It sounds like you're then trying to load the resource using a FileInputStream
or something like that. Don't do that: instead of calling getResource
, call getResourceAsStream
and read the data from that.
(You could load the resources from the URL instead, but calling getResourceAsStream
is a bit more convenient.)
EDIT: Having seen your updated answer, it seems other bits of code rely on the data being in a physical single file in the file system. The answer is therefore not to bundle it in a jar file in the first place. You could check whether it's in a separate file, and if not extract it to a temporary file, but that's pretty hacky IMO.
Loading resource files within a jar
This snippet of code worked for me:
Clip clip = null;
ClassLoader cl = this.getClass().getClassLoader();
AudioInputStream ais;
URL url = cl.getResource("com/example/project/assets/TestSound.wav");
System.out.println(url);
try {
ais = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(ais);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
The important thing is not adding the /src/
folder to the class path.
The critical change is changing cl.getResource("/com/example/project/assets/TestSound.wav")
to cl.getResource("com/example/project/assets/TestSound.wav");
because /com/...
indicates that the path is absolute, whereas com/...
indicates that the path is relative.
For example,
System.out.println(new File("/Test.File").getAbsolutePath());
System.out.println(new File("Test.File").getAbsolutePath());
return
/Test.File
/Users/alphadelta/Documents/Workspace/TestProject/Test.File
respectively.
The first File created is created using "/Test.File"
, which is absolute. The second is created using "Test.File"
, which is relative to the project root in eclipse.
How to access resources in JAR file?
To load an image from a JAR resource use the following code:
Toolkit tk = Toolkit.getDefaultToolkit();
URL url = getClass().getResource("path/to/img.png");
Image img = tk.createImage(url);
tk.prepareImage(img, -1, -1, null);
How to load a resource in both IDE and .jar using the same String
If you load a resource in Java you alway can use '/' as separator.
Try
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("res/shader/some_shader.glsl"); // no leading slash
Make shure your JAR with the resource is in your JVM Classpath (-cp
or -classpath
).
Edit:
You must use url.openStream()
to get an InputStream - not new File(). Your resource is not a file, becaus it is inside the JAR
Load resource from class's own JAR file
Alternatively you could use the JarURLConnection if you know the exact jar in which your file resides:
jar:<url>!/{entry}
Related Topics
How to Attach Source in Eclipse
How to Mock Private Method for Testing Using Powermock
How to Read Integer Value from the Standard Input in Java
Simpledateformat and Locale Based Format String
How Come Invoking a (Static) Method on a Null Reference Doesn't Throw Nullpointerexception
Simpledateformat Parsing Date with 'Z' Literal
How to Count Occurrences with Groupby
Convert Integer into Byte Array (Java)
Regex to Match Only Commas Not in Parentheses
How to Use an Internet Time Server to Get the Time
Java Cannot Make a Static Reference to Non-Static Field
Why Java Classes Do Not Inherit Annotations from Implemented Interfaces
Where Is Java_Home on MACos Mojave (10.14) to Lion (10.7)
How to Inject a Property Value into a Spring Bean Which Was Configured Using Annotations
How to Increase Heap Size of Jvm
Can't Read and Write a Tiff Image File Using Java Imageio Standard Library