<

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

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.

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());
}

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());
         
    StringBuilder data = new StringBuilder();
    Stream<String> lines = Files.lines(path);
    lines.forEach(line -> data.append(line).append("\n"));
    lines.close();
         
    Assert.assertEquals(expectedData, data.toString().trim());
}

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

6. Read File with FileUtils

Another common option is using the FileUtils class of the commons package. You’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);
        
    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 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.

8. Read File from 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.

9. Conclusion

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

We also demonstrated a data reading from files using core Java API.

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

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

  Subscribe  
newest oldest most voted
Notify of
Francois Marot
Guest

Thanks for the article ! One note though: I think your first example coule be better rewritten as this: private String readFromInputStream(InputStream inputStream) throws IOException { StringBuilder resultStringBuilder = new StringBuilder(); try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = bufferedReader.readLine()) != null) { resultStringBuilder.append(line); resultStringBuilder.append(“n”); } } return resultStringBuilder.toString(); } This way we use the try-with-resource & Autoclosable feature where we do not have to explicitly call the close() method. And closing only the BufferedReader will also close the wrapped InputStreamReader. So I think a noob should better copy/paste this code 😉

Grzegorz Piwowarek
Guest
Grzegorz Piwowarek

Nice idea, thanks 🙂 We will update the article

Xavier
Guest
Xavier

In java 8, when using Files.lines(), you are supposed to close the stream afterwards or use it in a try-with-resource block.

Grzegorz Piwowarek
Guest
Grzegorz Piwowarek

Great catch, thanks! We will add this to the article soon.