<

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

>> CHECK OUT THE COURSE

1. Overview

In this tutorial we’ll explore different ways to read from a File in Java; we’ll make use of BufferedReader, Scanner, StreamTokenizer, DataInputStream, SequenceInputStream and FileChannel.

Then, we will discuss how to read a UTF-8 encoded file and how to create String from contents of a file.

Finally, we’ll explore the new techniques to read from file in Java 7.

This article is part of the “Java – Back to Basic” series here on Baeldung.

2. Read with BufferedReader

Let’s start with a simple way to read from file using BufferedReader; the file itself contains:

Hello world

The following code reads from the file using BufferedReader:

@Test
public void whenReadWithBufferedReader_thenCorrect()
  throws IOException {
     String expected_value = "Hello world";
     String file ="src/test/resources/test_read.txt";
     
     BufferedReader reader = new BufferedReader(new FileReader(file));
     String currentLine = reader.readLine();
     reader.close();

    assertEquals(expected_value, currentLine);
}

Note that readLine() will return null when the end of the file is reached.

3. Read with Scanner

Next, let’s use a Scanner to read from the File – the file contains:

Hello world 1

We’ll use a simple whitespace as the delimiter:

@Test
public void whenReadWithScanner_thenCorrect()
  throws IOException {
    String file = "src/test/resources/test_read.txt";
    Scanner scanner = new Scanner(new File(file));
    scanner.useDelimiter(" ");

    assertTrue(scanner.hasNext());
    assertEquals("Hello", scanner.next());
    assertEquals("world", scanner.next());
    assertEquals(1, scanner.nextInt());

    scanner.close();
}

Note that the default delimiter is the whitespace, but multiple delimiters can be used with a Scanner.

4. Read with StreamTokenizer

Next, let’s read a text file into tokens using a StreamTokenizer.

The way the tokenizer works is – first, we need to figure 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

The file simply contains:

Hello 1

The following code reads from the file both the String and the number:

@Test
public void whenReadWithStreamTokenizer_thenCorrectTokens()
  throws IOException {
    String file = "src/test/resources/test_read.txt";
   FileReader reader = new FileReader(file);
    StreamTokenizer tokenizer = new StreamTokenizer(reader);

    // token 1
    tokenizer.nextToken();
    assertEquals(StreamTokenizer.TT_WORD, tokenizer.ttype);
    assertEquals("Hello", tokenizer.sval);

    // token 2    
    tokenizer.nextToken();
    assertEquals(StreamTokenizer.TT_NUMBER, tokenizer.ttype);
    assertEquals(1, tokenizer.nval, 0.0000001);

    // token 3
    tokenizer.nextToken();
    assertEquals(StreamTokenizer.TT_EOF, tokenizer.ttype);
    reader.close();
}

Note how the end of file token is used at the end.

5. Read with DataInputStream

We can use DataInputStream to read binary or primitive data type from file.

Let’s start with the actual file itself:

Hello

The following test reads the file using a DataInputStream:

@Test
public void whenReadWithDataInputStream_thenCorrect()
  throws IOException {
    String expectedValue = "Hello";
    String file ="src/test/resources/test_read.txt";
    DataInputStream reader = new DataInputStream(new FileInputStream(file));
    String result = reader.readUTF();
    reader.close();

    assertEquals(expectedValue, result);
}

6. Read with SequenceInputStream

Now, let’s look at how to concatenate two input streams into one using SequenceInputStream; the 2 input files will simply contain:

2000

and:

5000

Let’s now use a SequenceInputStream to read the two files and merge them into one:

@Test
public void whenReadingTwoFilesWithSequenceInputStream_thenCorrect()
  throws IOException {
    int expectedValue1 = 2000;
    int expectedValue2 = 5000;
    String file1 = "src/test/resources/test_read1.txt";
    String file2 = "src/test/resources/test_read2.txt";
    FileInputStream stream1 = new FileInputStream(file1);
    FileInputStream stream2 = new FileInputStream(file2);

    SequenceInputStream sequence = new SequenceInputStream(stream1, stream2);
    DataInputStream reader = new DataInputStream(sequence);

    assertEquals(expectedValue1, reader.readInt());
    assertEquals(expectedValue2, reader.readInt());

    reader.close();
    stream2.close();
}

7. Read with FileChannel

If we are reading a large file, FileChannel can be faster than standard IO.

The contents of the file:

 Hello world

The following code reads data bytes from the file using FileChannel and RandomAccessFile:

@Test
public void whenReadWithFileChannel_thenCorrect()
  throws IOException {
    String expected_value = "Hello world";
    String file = "src/test/resources/test_read.txt";
    RandomAccessFile reader = new RandomAccessFile(file, "r");
    FileChannel channel = reader.getChannel();

    int bufferSize = 1024;
    if (bufferSize > channel.size()) {
        bufferSize = (int) channel.size();
    }
    ByteBuffer buff = ByteBuffer.allocate(bufferSize);
    channel.read(buff);
    buff.flip();
    
    assertEquals(expected_value, new String(buff.array()));
    channel.close();
    reader.close();
}

8. Read UTF-8 encoded file

Now, let’s see how to read a UTF-8 encoded file using BufferedReader:

@Test
public void whenReadUTFEncodedFile_thenCorrect()
  throws IOException {
    String expected_value = "青空";
    String file = "src/test/resources/test_read.txt";
    BufferedReader reader = new BufferedReader
      (new InputStreamReader(new FileInputStream(file), "UTF-8"));
    String currentLine = reader.readLine();
    reader.close();

    assertEquals(expected_value, currentLine);
}

9. Read a file into a String

We can make good use of StringBuilder to read the entire contents of a file into a String. Let’s start with the file:

Hello world

Test line

The following code append data read from the file into a StringBuilder line by line:

@Test
public void whenReadFileContentsIntoString_thenCorrect()
  throws IOException {
    String expected_value = "Hello world n Test line n";
    String file = "src/test/resources/test_read.txt";
    BufferedReader reader = new BufferedReader(new FileReader(file));
    StringBuilder builder = new StringBuilder();
    String currentLine = reader.readLine();
    while (currentLine != null) {
        builder.append(currentLine);
        builder.append("n");
        currentLine = reader.readLine();
    }
    
    reader.close();
    assertEquals(expected_value, builder.toString());
}

10. Read from File using Java 7

Java 7 introduces a new way of working with files and the filesystem – let’s make use of that to read files.

10.1. Read a Small File with Java 7

The file contents:

 Hello world

The following code shows how to read small file using the new Files class:

@Test
public void whenReadSmallFileJava7_thenCorrect()
  throws IOException {
    String expected_value = "Hello world";

    Path path = Paths.get("src/test/resources/test_read.txt");

    String read = Files.readAllLines(path).get(0);
    assertEquals(expected_value, read);
}

Note that you can use the readAllBytes() method as well if you need binary data.

10.2. Read a Large File with Java 7

If we want to read a large file with Files class, we can use the BufferedReader.

The file contents:

 Hello world

The following code reads the file using the new Files class and BufferedReader:

@Test
public void whenReadLargeFileJava7_thenCorrect()
  throws IOException {
    String expected_value = "Hello world";

    Path path = Paths.get("src/test/resources/test_read.txt");

    BufferedReader reader = Files.newBufferedReader(path);
    String line = reader.readLine();
    assertEquals(expected_value, line);
}

11. Conclusion

As you can see, there are many possibilities of reading data from a file using plain Java. You can go for BufferedReader to read line by line, Scanner to read using different delimiters, StreamTokenizer to read 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.

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

>> CHECK OUT THE LESSONS