How to Read a File in Java

1. Introduction

In this article, we will see how we can read a file from a classpath, URL or inside a JAR file, using standard Java classes.

Further reading:

Java – Create a File

How to create a File in Java using JDK 6, JDK 7 with NIO or Commons IO.

Read more

Java – Write to File

The many ways to write data to File using Java.

Read more

2. Setup

We will use a set of test examples using core Java classes only, and in the tests, we’ll use assertions using Hamcrest matchers.

Tests will share a common readFromInputStream method that transforms an InputStream to String for easier asserting of results:

private String readFromInputStream(InputStream inputStream)
  throws IOException {
    StringBuilder resultStringBuilder = new StringBuilder();
    try (BufferedReader br
      = new BufferedReader(new InputStreamReader(inputStream))) {
        String line;
        while ((line = br.readLine()) != null) {
            resultStringBuilder.append(line).append("\n");
        }
    }
  return resultStringBuilder.toString();
}

Note that there are other ways of achieving the same result. You can consult this article for some alternatives.

3. Read File from Classpath

This section explains how to read a file that is available on a classpath. We will read the “fileTest.txt” available under src/main/resources:

@Test
public void givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData() {
    String expectedData = "Hello World from fileTest.txt!!!";

    Class clazz = FileOperationsTest.class;
    InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt");
    String data = readFromInputStream(inputStream);

    Assert.assertThat(data, containsString(expectedData));
}

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:

ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("fileTest.txt");
String data = readFromInputStream(inputStream);

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:

InputStream inputStream = null;
try {
    File file = new File(classLoader.getResource("fileTest.txt").getFile());
    inputStream = new FileInputStream(file);

    //...
}
finally {
    if (inputStream != null) {
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. Read File with JDK7

In JDK7 the NIO package was significantly updated. Let’s look at an example using the Files class and the readAllBytes method. The readAllBytes method accepts a Path. Path class can be considered as an upgrade of the java.io.File with some additional operations in place:

@Test
public void givenFilePath_whenUsingFilesReadAllBytes_thenFileData() {
   String expectedData = "Hello World from fileTest.txt!!!";

   Path path = Paths.get(getClass().getClassLoader()
     .getResource("fileTest.txt").toURI());
   byte[] fileBytes = Files.readAllBytes(path);
   String data = new String(fileBytes);

   Assert.assertEquals(expectedData, data.trim());
}

This method also offers a convenient way to read the contents of a file into a String.

5. Read File with JDK8

JDK8 offers 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 using UTF-8 charset:

@Test
public void givenFilePath_whenUsingFilesLines_thenFileData() {
    String expectedData = "Hello World from fileTest.txt!!!";

    Path path = Paths.get(getClass().getClassLoader()
      .getResource("fileTest.txt").toURI());

    Stream<String> lines = Files.lines(path);
    String data = lines.collect(Collectors.joining("\n"));
    lines.close();

    Assert.assertEquals(expectedData, data.trim());
}

Using Stream with IO channels like file operations, we need to close the stream explicitly using close() method.

As we can see, the Files API offers another easy way to read the file contents into a String.

6. Read File with FileUtils

Another common option is using the FileUtils class of the commons package. We’ll need to add the following dependency:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>

Make sure to check the latest dependency version here.

The file reading code may look like:

@Test
public void givenFileName_whenUsingFileUtils_thenFileData() {
    String expectedData = "Hello World from fileTest.txt!!!";

    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("fileTest.txt").getFile());
    String data = FileUtils.readFileToString(file, "UTF-8");

    Assert.assertEquals(expectedData, data.trim());
}

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.

7. Read File with IOUtils

Another common option is using the IOUtils class of the commons package. You’ll need to add the same common-io dependency as mentioned in the previous FileUtils example.

Let’s have a look at an example of use:

@Test
public void givenFileName_whenUsingIOUtils_thenFileData() {
    String expectedData = "This is a content of the file";

    FileInputStream fis = new FileInputStream("src/test/resources/fileToRead.txt");
    String data = IOUtils.toString(fis, "UTF-8");

    assertEquals(expectedData, data.trim());
}

Here we pass the FileInputStream object to the method toString() of IOUtils 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.

8. Read Content from URL

To read content from URL, we will use “/” URL in our example as:

@Test
public void givenURLName_whenUsingURL_thenFileData() {
    String expectedData = "Baeldung";

    URL urlObject = new URL("/");
    URLConnection urlConnection = urlObject.openConnection();
    InputStream inputStream = urlConnection.getInputStream();
    String data = readFromInputStream(inputStream);

    Assert.assertThat(data, containsString(expectedData));
}

There are also alternative ways of connecting to a URL. Here we used the URL and URLConnection class available in the standard SDK.

9. Read 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:

@Test
public void givenFileName_whenUsingJarFile_thenFileData() {
    String expectedData = "BSD License";

    Class clazz = Matchers.class;
    InputStream inputStream = clazz.getResourceAsStream("/LICENSE.txt");
    String data = readFromInputStream(inputStream);

    Assert.assertThat(data, containsString(expectedData));
}

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.

10. Conclusion

In this tutorial we’ve seen how to read a file from various locations like classpath, URL or jar files.

We also saw several ways to read the content from a file

You can find the source code in the following GitHub repo.

Leave a Reply

Your email address will not be published.