Cup of coffee on saucer

How to read a file to string in Java

You may want to read this tutorial to learn how to process files in Java. Very often, the data may be stored on disk in various formats. And to use that data in application, you have to write a special code that can read the content of a file into memory.

The Java language is very advanced and contains many different methods that may be used to get data from disk. There is an API that can do what you need in just a few lines. Also, there is a functionality that is more complicated and requires additional configuration.

This tutorial provides a deep review of the most popular methods that can be used to read some content into a string. You may review each option and choose the solution that works best for you.

Using the Files.readString() method

The Files class provides the readString() method. It can be used to get the content of a single file. The data will be stored into a variable with a type of String. The default character set is UTF-8.

This method is very simple. To use it, you have to create an instance of the Path class with a path to the file on disk. Then, that new object must be passed into the readString() method.

In addition, the try/catch block has to be added to the code. This is needed to catch various exceptions that may occur when reading the file.

Also, please pay attention that the readString() method is available only in Java version 11 or later.

Now, you can review our code sample. It prints the content of a file into the standard terminal.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            Path filePath = Path.of(contentFileName);

            String fileContent = Files.readString(filePath);

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

If you run the above application, the console output may be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the Files.readAllBytes() method

The Files class also has the readAllBytes() method. It's very simple as well. However, the difference is that it allows you to read the byte array from disk. There may be some cases when you need raw data. But if you need a string, then the byte array can be converted with help of the String class.

The code sample is given below. There you can see that the instance of the Path class is passed into the readAllBytes() method. And the same as in the previous method, we have to use the try/catch block to catch any unexpected issues.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            Path filePath = Path.of(contentFileName);
            String fileContent = "";

            byte[] fileBytes = Files.readAllBytes(filePath);

            fileContent = new String(fileBytes);
            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

The given code should produce output like it's shown below. The content of a file will appear in the terminal.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the Files.readAllLines() method

If you need to read a list of lines from the file, then Java may help you as well. The Files class provides the readAllLines() method that can be used for that purpose. It can be useful in some situations. For example, you have to process and parse each line separately from the other content.

The readAllLines() method returns an instance of the List class. It allows us to perform additional manipulations on the data.

However, if you need to convert that list into a single plain variable, then it's not an issue at all. You can use the String.join() method to combine the lines into a single value. To do that, you also need to specify the line separator. It must be passed as a first argument. The following sample demonstrates how this method works.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            Path filePath = Path.of(contentFileName);
            String fileContent = "";

            List<String> lines = Files.readAllLines(filePath);
            fileContent = String.join(System.lineSeparator(), lines);
            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

If you run the given application, the console should contain output like it's shown below.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the Files.lines() method

The Files class also provides the lines() method that allows you to read the content as a Stream. The advantage of this method is that the data is loaded on demand, step by step. Such a behavior may be useful if you have a large file.

But if you need to get all data into a single variable, you can use the forEach method. It will iterate over the lines. Then you can use the StringBuilder class to combine all lines together. Also, you may need to specify the line separator.

To see how it should be done, please review the following example.

Java 8

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";
            Path filePath = Path.of(contentFileName);
            StringBuilder contentBuilder = new StringBuilder();

            Stream<String> stream =
                Files.lines(filePath, StandardCharsets.UTF_8);
            stream.forEach(s -> contentBuilder.append(s).append("\n"));
            stream.close();

            String fileContent = contentBuilder.toString();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

Now, you can try that code to see if it works. If you run our sample, the console output may be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the BufferedReader and FileReader classes

The lines() method is also available in the BufferedReader class. If it's used in conjunction with the FileReader class, then the process of reading data is more efficient. This is sometimes critical in the application that performs a lot of input or output operations.

In addition, our code sample uses the joining() method of the Collectors class to combine all lines together. And the application uses the default line separator. Please see the full source code below.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.stream.Collectors;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            FileReader fileReader = new FileReader(contentFileName);
            BufferedReader contentReader = new BufferedReader(fileReader);
            String newLine = System.lineSeparator();

            String fileContent =
                contentReader.lines().collect(Collectors.joining(newLine));

            contentReader.close();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

The console output is given below. If you run the given code, you should see the content of the file in your terminal.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the BufferedReader class to read a file line by line

The BufferedReader class also provides the readLine() method. It may help you in various scenarios. For example, each line contains a specific data that needs to be parsed prior to getting data from other lines. However, in our code sample, we simply combine all lines together to get a single value with all data. Then, when data is ready, it is printed to the console.

Please see the full source code below. You may try to use it in your application.

import java.io.BufferedReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            Path contentPath = Paths.get(contentFileName);

            BufferedReader contentReader =
                Files.newBufferedReader(contentPath);

            String fileContent = "";
            String singleLine = "";

            while ((singleLine = contentReader.readLine()) != null) {
                fileContent += singleLine;
                fileContent += System.lineSeparator();
            }

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

The console output is similar to the output from previous sections. There should be content taken from the file.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the StringBuffer and BufferedReader classes

You may also consider using the StringBuffer class to hold the data. There are some benefits if you decide to use this method. This class allows us to perform thread safe operations. As a result, you can make a code that works in complex applications.

The following sample also uses the FileInputStream class to read content from the disk. Then, when data is ready, each line is appended to the buffer.

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            StringBuffer contentBuffer = new StringBuffer();
            FileInputStream contentStream =
                new FileInputStream(contentFileName);
            BufferedReader contentReader =
                new BufferedReader(new InputStreamReader(contentStream));
            String singleLine = "";

            while ((singleLine = contentReader.readLine()) != null) {
                contentBuffer.append(singleLine + System.lineSeparator());
            }

            contentReader.close();

            System.out.println(contentBuffer.toString());
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

If you run the given code sample, the console output may be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the BufferedReader, FileReader and StringBuilder classes

To build a more efficient code, you may consider using the StringBuilder class. It may work faster in some conditions. However, the downside is that this class is not thread safe. So you need to be careful when integrating the following code into your application.

Also, our simple application uses the FileReader class. It was created especially for reading a sequence of characters. Now, you can see how the code looks.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            StringBuilder contentBuilder = new StringBuilder();
            FileReader fileReader = new FileReader(contentFileName);

            BufferedReader contentReader = new BufferedReader(fileReader);
            String fileContent = "";
            String singleLine = "";

            while ((singleLine = contentReader.readLine()) != null) {
                contentBuilder.append(singleLine);
                contentBuilder.append(System.lineSeparator());
            }

            fileContent = contentBuilder.toString();

            contentReader.close();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

You may try to run our application. The console output should contain the file content like it's shown below.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the FileReader.read() method

It is worth noting that the FileReader class has a special version of the read() method. If there are no arguments passed into that method, then it will return a single character.

Such a behavior may be useful in some cases, like you need to process and validate each element of the content. But on the other hand, this method may be very slow on large amounts of data. You should use the following code only in special circumstances when the speed of reading is not critical.

Now, you can see how the code is implemented. We create an instance of the FileReader class with the name of the file to read. Then, each character is taken from the file and added to the variable that holds the data.

import java.io.FileReader;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            FileReader contentReader = new FileReader(contentFileName);
            String fileContent = "";
            int character = 0;

            while ((character = contentReader.read()) != -1) {
                fileContent += (char) character;
            }

            contentReader.close();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

If you try to run the given application in the console, the output should be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the FileInputStream.read() method

The FileInputStream class also provides the read() method. There are several options available that you can use, but we will describe the option that allows you to read data into an array. However, before calling that method, we have to create the array. Then, we need to create instances of the FileInputStream and StringBuilder classes. They will help us to get data and combine the results together. Please see the following code to see how this method works.

import java.io.FileInputStream;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            byte[] dataHolder = new byte[512];

            FileInputStream contentStream =
                new FileInputStream(contentFileName);

            StringBuilder contentBuilder =
                new StringBuilder();

            while (contentStream.read(dataHolder) != -1) {
                contentBuilder.append(new String(dataHolder));
            }

            contentStream.close();

            String fileContent = contentBuilder.toString();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

Our code should produce results like it is shown below.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the DataInputStream.readFully() method

The DataInputStream class contains the readFully() method. That's another convenient method of getting content from a file. It allows you to read the whole file into a buffer. However, you have to know the size of the file if you want to read content in a single call to this method.

The solution is to get file size with help of the File class. Then, you can create a buffer long enough to hold the data. After that, the readFully() method may be called with a proper array.

Please see the following sample that shows how it can be correctly done.

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            DataInputStream contentStream =
                new DataInputStream(new FileInputStream(contentFileName));

            long fileLength = new File(contentFileName).length();

            byte[] contentBytes = new byte[(int) fileLength];

            contentStream.readFully(contentBytes);

            String fileContent =
                new String(contentBytes, StandardCharsets.UTF_8);

            contentStream.close();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

Now, if you run our code sample, the console output should be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the RandomAccessFile.readFully() method

The RandomAccessFile is a class that allows you to perform both operations, reading and writing the data. And it also contains the readFully() method. It is similar to the method described in the previous section of this tutorial. The same way, as it's shown there, you have to obtain the size of the file. Then, you should create a buffer that will hold the data.

When the initial configuration is done, you may call the readFully() method to get the content of the desired file. Our sample is given below, you can review it to learn how this method works.

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            RandomAccessFile fileAccess =
                new RandomAccessFile(contentFileName, "r");

            byte[] contentBytes = new byte[(int)fileAccess.length()];
            fileAccess.readFully(contentBytes);
            fileAccess.close();

            String fileContent = new String(contentBytes, StandardCharsets.UTF_8);

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

If you run the given application, the output may be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the Scanner class to read a file lines

Java has the Scanner class that can be used to read tokens from a file. The content should be separated by a specified delimiter. This method of reading file data is unusual and may not be applicable in all cases. However, we will show how it works just in case you decide to use it in your application.

The following sample shows how to read only the first and the second line of a file. Also, as you can see there, a new line character is used as a delimiter.

import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Scanner;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        final String contentFileName = "content.txt";

        try {
            Scanner contentScanner = new Scanner(
                Paths.get(contentFileName),
                StandardCharsets.UTF_8.name()
            );

            String firstLine = contentScanner.useDelimiter(
                System.lineSeparator()
            ).next();

            String secondLine = contentScanner.useDelimiter(
                System.lineSeparator()
            ).next();

            System.out.println(firstLine);
            System.out.println(secondLine);
            contentScanner.close();
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

Now, you can try to run our code. The terminal may contain the content like it's shown below.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the Scanner class to read a file line by line

The Scanner class also contains the nextLine() method that allows you to read the whole file line by line. In addition, there is also the hasNextLine() method that can be used to check if the next line is available. The full example of how to use these methods is shown below.

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            Scanner contentScanner = new Scanner(new File(contentFileName));

            String fileContent = "";

            while (contentScanner.hasNextLine()) {
                fileContent += contentScanner.nextLine();
                fileContent += System.lineSeparator();
            }

            contentScanner.close();

            System.out.println(fileContent);
        } catch (FileNotFoundException exception) {
            exception.printStackTrace();
        }
    }
}

If you try to get content from a file using our sample code, the console output may be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the StreamTokenizer class

The StreamTokenizer class also allows you to read tokens from the file on a disk. However, the usage is different. You have to use the nextToken() method to parse the next token. Then, if the token is a string, you can get it from the "sval" property of the StreamTokenizer class.

Please review the following code sample, it shows how the StreamTokenizer class can be used in a real application.

import java.io.FileReader;
import java.io.IOException;
import java.io.StreamTokenizer;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            FileReader contentReader =
                new FileReader(contentFileName);
            StreamTokenizer contentTokenizer =
                new StreamTokenizer(contentReader);

            contentTokenizer.nextToken();
            System.out.println(contentTokenizer.sval);

            contentTokenizer.nextToken();
            System.out.println(contentTokenizer.sval);

            contentTokenizer.nextToken();
            System.out.println(contentTokenizer.sval);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

After running the given code, you should see each word on a new line in the terminal. Example of the output is shown below.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This
is
sample

Using the SeekableByteChannel class

That's another method that you can use to read the content of a file. However, it's a bit complicated and may not be suitable in all cases. You should use the SeekableByteChannel class only if you know the Java API very well. The benefit of this class is that it maintains the current position. Also the data can be read and written. Please review our code sample, it shows how to read data from a text file.

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            Path filePath = Path.of(contentFileName);

            SeekableByteChannel byteChannel = Files.newByteChannel(filePath);

            long fileLength = new File(contentFileName).length();
            ByteBuffer contentBuffer = ByteBuffer.allocate((int) fileLength);
            String fileContent = "";

            while (byteChannel.read(contentBuffer) > 0) {
                contentBuffer.flip();

                String charsetName = StandardCharsets.UTF_8.toString();
                Charset contentCharset = Charset.forName(charsetName);
                fileContent += contentCharset.decode(contentBuffer);

                contentBuffer.clear();
            }

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

The same as in the previous example, the console output should contain data taken from a file.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using the FileChannel class

If you prefer to use channels for reading data then you may also consider using the FileChannel class. There is additional functionality, like thread safety, data mapping and so on. It is worth noting that this class implements the SeekableByteChannel interface.

But prior to using that class, you have to create a buffer that can hold the data. As a result, we use the ByteBuffer.allocate() method to allocate a required space for the buffer. The details are provided below, please see the full code sample.

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

class sample {
    public static void main(String args[]) {
        try {
            final String contentFileName = "content.txt";

            RandomAccessFile contentReader =
                new RandomAccessFile(contentFileName, "r");
            FileChannel contentChannel = contentReader.getChannel();

            int contentBufferSize = (int) contentChannel.size();

            ByteBuffer contentBuffer = ByteBuffer.allocate(contentBufferSize);

            contentChannel.read(contentBuffer);

            String fileContent = new String(contentBuffer.array());
            contentChannel.close();
            contentReader.close();

            System.out.println(fileContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

Finally, you can try to run this simple application. The output should be like it's shown below.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Reading a file from the URL

In the previous sections of this tutorial, we've described how to get the content of a file on disk. However, you may also want to read a file from some URL. That is also possible in the Java language. The URL class provides the openStream() method that you can use to obtain a stream. After that, the stream is passed into the InputStreamReader class. And then, the instance of the InputStreamReader class is given to the BufferedReader class.

After the initial setup is done, we can use the lines() method of the BufferedReader class to get a stream of lines. Then, the collect() method is also called to combine the data together.

The full code sample is given below.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.io.IOException;

class sample {
    public static void main(String args[]) {
        try {
            URL contentUrl = new URL("https://example.com/content.txt");

            InputStreamReader streamReader =
                new InputStreamReader(contentUrl.openStream());
            BufferedReader contentReader =
                new BufferedReader(streamReader);

            String newLine = System.lineSeparator();

            String remoteContent =
                contentReader.lines().collect(Collectors.joining(newLine));

            contentReader.close();

            System.out.println(remoteContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

It's time to try our code. If you run the given demo, the console output may be like the following.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Using URLConnection class to get the remote content

There is also an alternative method to get content of the remote file. The URL class contains the openConnection() method. It can be used to get connection to the specific remote resource. Then, we can use the getInputStream() method on that connection to get a stream to the data. Then, you can get data from that stream with help of the InputStreamReader and BufferedReader classes.

Now, you may review the following code. You can see there how this method works. Please pay attention that we use the readLine() method of the BufferedReader class to get each line from the remote file.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

class sample {
    public static void main(String args[]) {
        try {
            URL contentUrl = new URL("https://example.com/content.txt");

            URLConnection connection = contentUrl.openConnection();
            InputStream inputStream = connection.getInputStream();

            StringBuilder resultStringBuilder = new StringBuilder();

            BufferedReader contentReader
                = new BufferedReader(new InputStreamReader(inputStream));

            String contentLine = "";

            while ((contentLine = contentReader.readLine()) != null) {
                resultStringBuilder.append(contentLine);
                resultStringBuilder.append(System.lineSeparator());
            }

            String remoteContent = resultStringBuilder.toString();

            System.out.println(remoteContent);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

If you run the given code, you should see the content of the file in your terminal.

developer@developer-pc:~/samples/java$ javac ./sample.java && java sample
This is
sample text

Conclusion

As you see, there are many different methods that allow you to get the content of the file. Java language has a rich API. Each solution is unique and may work a bit different then the other methods. As a result, we recommend studying the official Java guides to learn more about each method. You may want to choose a solution that works best in your specific conditions.

Related Articles

Defocused lights

How to sort arrays in Java

Random numbers

How to generate a random number in Java

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *