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
Getting resource file from inside jar
Maven uses something called the Standard Directory Layout. If you don't follow this layout then the plugins can't do their job correctly. Technically, you can configure Maven to use different directories but 99.999% of the time this is not necessary.
One of the features of this layout is that production files go in:
<project-dir>/src/main/java
- All
*.java
files
- All
<project-dir>/src/main/resources
- All non-
*.java
files (that are meant to be resources)
- All non-
When you build your project the Java source files are compiled and the *.class
files are put into the target/classes
directory; this is done by the maven-compiler-plugin
. Meanwhile, the resource files are copied from src/main/resources
into target/classes
as well; the maven-resources-plugin
is responsible for this.
Note: See Introduction to the Build Lifecycle for more information about phases and which plugins are executed by which phase. This Stack Overflow question may also be useful.
When you launch your application from the IDE (possibly via the exec-maven-plugin
) the target/classes
directory is put on the classpath. This means all the compiled classes from src/main/java
and all the copied resources from src/main/resources
are available to use via the classpath.
Then, when you package your application in a JAR file, all the files in target/classes
are added to the resulting JAR file (handled by the maven-jar-plugin
). This includes the resources copied from src/main/resources
. When you launch the application using this JAR file the resources are still available to use via the classpath, because they're embedded in the JAR file.
To make resource.txt
available on the classpath, just move:
<project-dir>/resource.txt
To:
<project-dir>/src/main/resources/resource.txt.
Then you can use Class#getResource
with /resource.txt
as the path and everything should work out for you. The URL
returned by getResource
will be different depending on if you're executing against target/classes
or against the JAR file.
When executing against target/classes
you'll get something like:
file:///.../<project-dir>/target/classes/resource.txt
When executing against the JAR file you'll get something like:
jar:file:///.../<project-dir>/target/projectname-version.jar!/resource.txt
Note: This all assumes resource.txt
is actually supposed to be a resource and not an external file. Resources are typically read-only once deployed in a JAR file; if you need a writable file then it's up to you to use a designated location for the file (e.g. a folder in the user's home directory). One typically accesses external files via either java.io.File
or java.nio.file.*
. Remember, resources are not the same thing as normal files.
Now, if you were to put resource.txt
directly under <project-dir>
that would mean nothing to Maven. It would not be copied to target/classes
or end up in the JAR file which means the resource is never available on the classpath. So just to reiterate, all resources go under src/main/resources
.
Check out the Javadoc of java.lang.Class#getResource(String)
for more information about the path, such as when to use a leading /
and when not to. The link points to the Javadoc for Java 12 which includes information about resources and modules (JPMS/Jigsaw modules, not Maven modules); if you aren't using modules you can ignore that part of the documentation.
How do I read a resource file from a Java jar file?
The problem was that I was going a step too far in calling the parse method of XMLReader. The parse method accepts an InputSource, so there was no reason to even use a FileReader. Changing the last line of the code above to
xr.parse( new InputSource( filename ));
works just fine.
Get resource file from jar file
String fontFilePath = Paths.get(System.getProperty("user.dir"), "prova.jar", "Retro Gaming.ttf").toString();
That.. rather obviously won't work.
You need to use the gRAS (getResourceAsStream) system. File
in java (as in, what new FileInputStream
needs, the java.io.File
object) are actual files. entries inside jar files don't count. It is not possible to refer to that ttf file with a File
object, nor to open it with FileInputStream.
Fortunately, the createFont
method doesn't demand that you pass a FileInputStream
; any old InputStream
will do.
The ttf file needs to be in the same classpath root as the this very class you are writing (for example, the same jar). Once you've ensured that is the case, you can use gRAS:
try (var fontIn = FontLoader.class.getResourceAsStream("/Retro Gaming.ttf")) {
Font.createFont(Font.TRUETYPE_FONT, fontIn).deriveFont(.., ...);
}
gRAS looks in the same place as where FontLoader.class
lives. From your snippet it sounds like you put the ttf in the 'root' of the jar and not next to FontLoader. The leading slash in the string argument to getResourceAsStream
means: Look relative to the root of the place FontLoader is in (so, your jar, presumably).
Get resources from a jar file
There is a reason why getResource()
returns a URL
, and not a File
, because the resource may not be a file, and since your code is packaged in the Jar file, it's not a file but a zip entry.
The only safe way to read the content of the resource, is as an InputStream
, either by calling getResourceAsStream()
or by calling openStream()
on the returned URL
.
Java: Cannot load a JPG image as a resource in a JAR file
To load *.jpg
image (or any other) from a *.jar
file use this schema:
Create a project, which then be compiled to the
*.jar
fileproject-with-resources
│
├── src
│ └── main
│ ├── java
│ │ ├── . . .
│ │ └── Project.java
│ └── resources
│ ├── . . .
│ └── image1.jpg
└── pom.xmlConfigure
maven-resources-plugin
(there may be several resources folders)<build>
<defaultGoal>package</defaultGoal>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>resources</targetPath>
</resource>
. . .
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
. . .
</plugins>
</build>In
Java
code useImageIO
class to read pictures to theBufferedImage
objectspublic class Project {
public static void main(String[] args) throws IOException {
BufferedImage image =
ImageIO.read(Project.class
.getResourceAsStream("/resources/image1.jpg"));
}
}Prepare getters, if necessary
public class Project {
private BufferedImage image;
. . .
public BufferedImage getImage() {
return image;
}
}Build project to the
*.jar
file using Mavenpackage
goal in your IDE
Related Topics
Jsp Tricks to Make Templating Easier
How to Count the Number of Occurrences of an Element in a List
Java.Lang.Classnotfoundexception: Com.Mysql.Jdbc.Driver in Eclipse
How to Convert a Stack Trace to a String
String, Stringbuffer, and Stringbuilder
How to Catch an Exception from a Thread
How Are Spring Data Repositories Actually Implemented
Good Java Graph Algorithm Library
Spring Data JPA - Zoneddatetime Format for JSON Serialization
How to Initialise a Static Map
How to Override Class Variables in Java
Switch Tabs Using Selenium Webdriver with Java
Java 8 Iterable.Foreach() VS Foreach Loop
How to Monitor the Computer's Cpu, Memory, and Disk Usage in Java
Best Way to List Files in Java, Sorted by Date Modified
Why Do People Still Use Primitive Types in Java
Where Are Static Methods and Static Variables Stored in Java