How do I create a Java string from the contents of a file?


13 Answers

Commons FileUtils.readFileToString:

public static String readFileToString(File file)
                       throws IOException

Reads the contents of a file into a String using the default encoding for the VM. The file is always closed.

Parameters:

  • file - the file to read, must not be null

Returns: the file contents, never null

Throws: - IOException - in case of an I/O error

Since: Commons IO 1.3.1

The code used (indirectly) by that class is:

IOUtils.java under Apache Licence 2.0.

public static long copyLarge(InputStream input, OutputStream output)
       throws IOException {
   byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
   long count = 0;
   int n = 0;
   while (-1 != (n = input.read(buffer))) {
       output.write(buffer, 0, n);
       count += n;
   }
   return count;
}

It is very similar to the one used by Ritche_W.

Question

I've been using the idiom below for some time now. And it seems to be the most wide-spread, at least on the sites I've visited.

Is there a better/different way to read a file into a string in Java?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}



import java.nio.file.Files;

.......

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }



Using this library, it is one line:

String data = IO.from(new File("data.txt")).toString();



To read a File as binary and convert at the end

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}



I cannot comment other entries yet, so I'll just leave it here.

One of best answers here (https://.com/a/326448/1521167):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

still has one flaw. It always puts new line char in the end of string, which may cause some weirds bugs. My suggestion is to change it to:

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}



in java 8 , there are a new Class

java.util.stream.Stream

A stream represents a sequence of elements and supports different kind of operations to perform computations upon those elements

to Read more about it :

Oracle Documentation

Here an Example :

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public Class ReadFile{
  public  static String readFile(String filePath) {
 StringBuilder  stringBuilder = new StringBuilder();
    String ls = System.getProperty("line.separator");
        try {

            try (Stream<String> lines = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)) {
                for (String line : (Iterable<String>) lines::iterator) {


                      stringBuilder.append(line);
                      stringBuilder.append(ls);


                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

      return stringBuilder.toString(); 


}

}



You can try Scanner and File class, a few lines solution

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}



Be aware when using fileInputStream.available() the returned integer does not have to represent the actual file size, but rather the guessed amount of bytes the system should be able to read from the stream without blocking IO. A safe and simple way could look like this

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}

It should be considered that this approach is not suitable for multi-byte character encodings like UTF-8.




That code will normalize line breaks, which may or may not be what you really want to do.

Here's an alternative which doesn't do that, and which is (IMO) simpler to understand than the NIO code (although it still uses java.nio.charset.Charset):

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}



If it's a text file why not use apache commons-io?

It has the following method

public static String readFileToString(File file) throws IOException

If you want the lines as a list use

public static List<String> readLines(File file) throws IOException



If you do not have access to Files, you do the next:

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}



There is a variation on the same theme that uses a for loop, instead of a while loop, to limit the scope of the line variable. Whether it's "better" is a matter of personal taste.

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}



import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
/**
 * A simple example program that reads a text file into a String using Files.lines and stream.
 */
public class ReadTextFileExample {
    public static void main(String[] args) throws IOException {
        String contents = Files.lines(Paths.get("c:\\temp\\testfile.txt")).collect(Collectors.joining("\n"));
        System.out.println(contents);
    }
}



If you're looking for an alternative that doesn't involve a third-party library (e.g. Commons I/O), you can use the Scanner class:

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());
    Scanner scanner = new Scanner(file);
    String lineSeparator = System.getProperty("line.separator");

    try {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + lineSeparator);
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}



Related