- How to Read a File in Java
- Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:
- 1. Overview
- Further reading:
- Java – Create a File
- Java – Write to File
- 2. Setup
- 2.1 Input File
- 2.2 Helper Method
- 3. Reading a File from the Classpath
- 3.1. Using Standard Java
- 3.2. Using the commons-io Library
- 4. Reading with BufferedReader
- 5. Reading from a File Using Java NIO
- 5.1. Reading a Small File
- 5.2. Reading a Large File
- 5.3. Reading a File Using Files.lines()
- 6. Reading with Scanner
- 7. Reading with StreamTokenizer
- 8. Reading with DataInputStream
- 9. Reading with FileChannel
- 10. Reading a UTF-8 Encoded File
- 11. Reading Content from URL
- 12. Reading a File from a JAR
- 13. Conclusion
- How to load JAR files dynamically at Runtime?
- 20 Answers 20
- Assign the current thread
- Do not include
How to Read a File in Java
Last modified: January 30, 2021
Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:
If you have a few years of experience in the Java ecosystem, and you’re interested in sharing that experience with the community (and getting paid for your work of course), have a look at the «Write for Us» page. Cheers, Eugen
1. Overview
In this tutorial, we’ll explore different ways to read from a File in Java.
First, we’ll learn how to load a file from the classpath, a URL, or from a JAR file using standard Java classes.
Second, we’ll see how to read the content with BufferedReader, Scanner, StreamTokenizer, DataInputStream, SequenceInputStream, and FileChannel. We will also discuss how to read a UTF-8 encoded file.
Finally, we’ll explore the new techniques to load and read a file in Java 7 and Java 8.
This article is part of the “Java – Back to Basic” series on Baeldung.
Further reading:
Java – Create a File
Java – Write to File
2. Setup
2.1 Input File
In most examples throughout this article, we’ll read a text file with filename fileTest.txt that contains one line:
For a few examples, we’ll use a different file; in these cases, we’ll mention the file and its contents explicitly.
2.2 Helper Method
We’ll use a set of test examples with core Java classes only, and in the tests, we’ll use assertions with Hamcrest matchers.
Tests will share a common readFromInputStream method that transforms an InputStream to String for easier asserting of results:
Note that there are other ways of achieving this same result. We can consult this article for some alternatives.
3. Reading a File from the Classpath
3.1. Using Standard Java
This section explains how to read a file that is available on a classpath. We’ll read the “ fileTest.txt ” available under src/main/resources :
In the above code snippet, we used the current class to load a file using getResourceAsStream method and passed the absolute path of the file to load.
The same method is available on a ClassLoader instance as well:
We obtain the classLoader of the current class using getClass().getClassLoader() .
The main difference is that when using the getResourceAsStream on a ClassLoader instance, the path is treated as absolute starting from the root of the classpath.
When used against a Class instance , the path could be relative to the package, or an absolute path, which is hinted by the leading slash.
Of course, note that in practice, open streams should always be closed, such as the InputStream in our example:
3.2. Using the commons-io Library
Another common option is using the FileUtils class of the commons-io package:
Here we pass the File object to the method readFileToString() of FileUtils class. This utility class manages to load the content without the necessity of writing any boilerplate code to create an InputStream instance and read data.
The same library also offers the IOUtils class:
Here we pass the FileInputStream object to the method toString() of IOUtils class. This utility class acts in the same way as the previous one in order to create an InputStream instance and read data.
4. Reading with BufferedReader
Now let’s focus on different ways to parse the content of a file.
We’ll start with a simple way to read from a file using BufferedReader:
Note that readLine() will return null when the end of the file is reached.
5. Reading from a File Using Java NIO
In JDK7, the NIO package was significantly updated.
Let’s look at an example using the Files class and the readAllLines method. The readAllLines method accepts a Path.
Path class can be considered an upgrade of the java.io.File with some additional operations in place.
5.1. Reading a Small File
The following code shows how to read a small file using the new Files class:
Note that we can use the readAllBytes() method as well if we need binary data.
5.2. Reading a Large File
If we want to read a large file with Files class, we can use the BufferedReader.
The following code reads the file using the new Files class and BufferedReader:
5.3. Reading a File Using Files.lines()
JDK8 offers the lines() method inside the Files class. It returns a Stream of String elements.
Let’s look at an example of how to read data into bytes and decode it using UTF-8 charset.
The following code reads the file using the new Files.lines():
Using Stream with IO channels like file operations, we need to close the stream explicitly using the close() method.
As we can see, the Files API offers another easy way to read the file contents into a String.
In the next sections, we’ll look at other less common methods of reading a file that may be appropriate in some situations.
6. Reading with Scanner
Next let’s use a Scanner to read from the File. Here we’ll use whitespace as the delimiter:
Note that the default delimiter is the whitespace, but multiple delimiters can be used with a Scanner.
The Scanner class is useful when reading content from the console, or when the content contains primitive values, with a known delimiter (eg: a list of integers separated by space).
7. Reading with StreamTokenizer
Now let’s read a text file into tokens using a StreamTokenizer.
The tokenizer works by first figuring out what the next token is, String or number. We do that by looking at the tokenizer.ttype field.
Then we’ll read the actual token based on this type:
- tokenizer.nval – if the type was a number
- tokenizer.sval – if the type was a String
In this example, we’ll use a different input file which simply contains:
The following code reads from the file both the String and the number:
Note how the end of file token is used at the end.
This approach is useful for parsing an input stream into tokens.
8. Reading with DataInputStream
We can use DataInputStream to read binary or primitive data types from a file.
The following test reads the file using a DataInputStream:
9. Reading with FileChannel
If we are reading a large file, FileChannel can be faster than standard IO.
The following code reads data bytes from the file using FileChannel and RandomAccessFile:
10. Reading a UTF-8 Encoded File
Now let’s see how to read a UTF-8 encoded file using BufferedReader. In this example, we’ll read a file that contains Chinese characters:
11. Reading Content from URL
To read content from a URL, we will use “/” URL in our example:
There are also alternative ways of connecting to a URL. Here we used the URL and URLConnection class available in the standard SDK.
12. Reading a File from a JAR
To read a file which is located inside a JAR file, we will need a JAR with a file inside it. For our example, we will read “LICENSE.txt” from the “hamcrest-library-1.3.jar” file:
Here we want to load LICENSE.txt that resides in Hamcrest library, so we will use the Matcher’s class that helps to get a resource. The same file can be loaded using the classloader too.
13. Conclusion
As we can see, there are many possibilities for loading a file and reading data from it using plain Java.
We can load a file from various locations like classpath, URL, or jar files.
Then we can use BufferedReader to read line by line, Scanner to read using different delimiters, StreamTokenizer to read a file into tokens, DataInputStream to read binary data and primitive data types, SequenceInput Stream to link multiple files into one stream, FileChannel to read faster from large files, etc.
We can find the source code for this article in the following GitHub repo .
How to load JAR files dynamically at Runtime?
Why is it so hard to do this in Java? If you want to have any kind of module system you need to be able to load JAR files dynamically. I’m told there’s a way of doing it by writing your own ClassLoader , but that’s a lot of work for something that should (in my mind at least) be as easy as calling a method with a JAR file as its argument.
Any suggestions for simple code that does this?
20 Answers 20
The reason it’s hard is security. Classloaders are meant to be immutable; you shouldn’t be able to willy-nilly add classes to it at runtime. I’m actually very surprised that works with the system classloader. Here’s how you do it making your own child classloader:
Painful, but there it is.
The following solution is hackish, as it uses reflection to bypass encapsulation, but it works flawlessly:
You should take a look at OSGi, e.g. implemented in the Eclipse Platform. It does exactly that. You can install, uninstall, start and stop so called bundles, which are effectively JAR files. But it does a little more, as it offers e.g. services that can be dynamically discovered in JAR files at runtime.
Or see the specification for the Java Module System.
How about the JCL class loader framework? I have to admit, I haven’t used it, but it looks promising.
While most solutions listed here are either hacks (pre JDK 9) hard to configure (agents) or just don’t work anymore (post JDK 9) I find it really surprising that nobody mentioned a clearly documented method.
You can create a custom system class loader and then you’re free to do whatever you wish. No reflection required and all classes share the same classloader.
When starting the JVM add this flag:
The classloader must have a constructor accepting a classloader, which must be set as its parent. The constructor will be called on JVM startup and the real system classloader will be passed, the main class will be loaded by the custom loader.
To add jars just call ClassLoader.getSystemClassLoader() and cast it to your class.
Check out this implementation for a carefully crafted classloader. Please note, you can change the add() method to public.
Here is a version that is not deprecated. I modified the original to remove the deprecated functionality.
With Java 9, the answers with URLClassLoader now give an error like:
This is because the class loaders used have changed. Instead, to add to the system class loader, you can use the Instrumentation API through an agent.
Create an agent class:
Add META-INF/MANIFEST.MF and put it in a JAR file with the agent class:
Run the agent:
This uses the byte-buddy-agent library to add the agent to the running JVM:
The best I’ve found is org.apache.xbean.classloader.JarFileClassLoader which is part of the XBean project.
Here’s a short method I’ve used in the past, to create a class loader from all the lib files in a specific directory
Then to use the classloader, just do:
Here is a quick workaround for Allain’s method to make it compatible with newer versions of Java:
Note that it relies on knowledge of internal implementation of specific JVM, so it’s not ideal and it’s not a universal solution. But it’s a quick and easy workaround if you know that you are going to use standard OpenJDK or Oracle JVM. It might also break at some point in future when new JVM version is released, so you need to keep that in mind.
If you are working on Android, the following code works:
Another version of the hackish solution from Allain, that also works on JDK 11:
On JDK 11 it gives some deprecation warnings but serves as a temporary solution those who use Allain solution on JDK 11.
The solution proposed by jodonnell is good but should be a little bit enhanced. I used this post to develop my application with success.
Assign the current thread
Firstly we have to add
or you will not able to load resource (such as spring/context.xml) stored into the jar.
Do not include
your jars into the parent class loader or you will not able to understand who is loading what.
However, OSGi framework remain the best way.
In case anyone searches for this in the future, this way works for me with OpenJDK 13.0.2.
I have many classes that I need to instantiate dynamically at runtime, each potentially with a different classpath.
In this code, I already have an object called pack, that holds some metadata about the class I am trying to load. The getObjectFile() method returns the location of the class file for the class. The getObjectRootPath() method returns the path to the bin/ directory containing the class files that include the class I am trying to instantiate. The getLibPath() method returns the path to a directory containing the jar files constituting the classpath for the module the class is a part of.
I was using the Maven dependency: org.xeustechnologies:jcl-core:2.8 to do this before, but after moving past JDK 1.8, it sometimes froze and never returned being stuck «waiting for references» at Reference::waitForReferencePendingList().
I am also keeping a map of class loaders so that they can be reused if the class I am trying to instantiate is in the same module as a class that I have already instantiated, which I would recommend.