270

I am trying to read a simple text file into a String. Of course there is the usual way of getting the input stream and iterating with readLine() and reading contents into String.

Having done this hundreds of times in past, I just wondered how can I do this in minimum lines of code? Isn't there something in java like String fileContents = XXX.readFile(myFile/*File*/) .. rather anything that looks as simple as this?

I know there are libraries like Apache Commons IO which provide such simplifications or even I can write a simple Util class to do this. But all that I wonder is - this is a so frequent operation that everyone needs then why doesn't Java provide such simple function? Isn't there really a single method somewhere to read a file into string with some default or specified encoding?

tshepang
  • 10,772
  • 21
  • 84
  • 127
Gopi
  • 9,585
  • 4
  • 26
  • 43

9 Answers9

362

Yes, you can do this in one line (though for robust IOException handling you wouldn't want to).

String content = new Scanner(new File("filename")).useDelimiter("\\Z").next();
System.out.println(content);

This uses a java.util.Scanner, telling it to delimit the input with \Z, which is the end of the string anchor. This ultimately makes the input have one actual token, which is the entire file, so it can be read with one call to next().

There is a constructor that takes a File and a String charSetName (among many other overloads). These two constructor may throw FileNotFoundException, but like all Scanner methods, no IOException can be thrown beyond these constructors.

You can query the Scanner itself through the ioException() method if an IOException occurred or not. You may also want to explicitly close() the Scanner after you read the content, so perhaps storing the Scanner reference in a local variable is best.

See also

Related questions


Third-party library options

For completeness, these are some really good options if you have these very reputable and highly useful third party libraries:

Guava

com.google.common.io.Files contains many useful methods. The pertinent ones here are:

Apache Commons/IO

org.apache.commons.io.IOUtils also offer similar functionality:

  • String toString(InputStream, String encoding)
    • Using the specified character encoding, gets the contents of an InputStream as a String
  • List readLines(InputStream, String encoding)
    • ... as a (raw) List of String, one entry per line

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 348,637
  • 121
  • 546
  • 611
  • Alright! Though may not be robust as you mentioned, no doubt this does it in minimum lines of code ! – Gopi Aug 05 '10 at 04:38
  • 2
    Please also see solution below for Java 7 mechanism that's essentially one line with the default API, as with many things Java has moved on slightly since this question. – Jim Jun 13 '13 at 13:45
  • 7
    Unfortunately, the Scanner solution fails with empty files (NoSuchElementException) – Daniel Alder May 15 '14 at 22:21
  • 1
    In addition to failing on empty files, it also omits the newline at the end of the file, if it exists. – SigmaX Jun 09 '14 at 23:33
  • 2
    I have used this for some time, but it turns out it doesn't always work! Sometimes `\\Z` will actually occur in the file and will cause this to fail. – wvdz Aug 20 '14 at 11:29
  • 7
    return new Scanner(new URL(url).openStream(), "UTF-8").useDelimiter("\\A").next(); is better as it does not fail on empty files. – Guy Jan 04 '15 at 17:40
  • I don't know why but it fails on Windows 7, that I met NoSuchElementException. But the same code works fine on OS X. Reading the same files, which are not empty. – Evan JIANG Dec 09 '16 at 03:39
  • 2
    Avoid this, if you are using text files that are bigger than 1024 bytes. The scanner will (at least on Android) cuts the resulting string to 1024 bytes. – Udo Klimaschewski Feb 10 '17 at 10:51
  • With the advent of Groovy, you can read a file thus: String content = new File( filename ).text() – Piko Aug 02 '17 at 19:08
  • I have to downvote this: it trims the trailing newline, which is inacceptable and cost me half an hour of debugging right now, thank you very much. – mirabilos Mar 21 '19 at 17:26
217

From Java 7 (API Description) onwards you can do:

new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);

Where filePath is a String representing the file you want to load.

leventov
  • 12,780
  • 10
  • 60
  • 91
Jim
  • 3,173
  • 1
  • 16
  • 26
  • 2
    I believe this will only work if the file was in the platform's default char set. – Paul Jun 24 '13 at 10:01
  • 6
    @Paul that would be okay as a default I think. You can always specify a charset when constructing the new String – Mike Braun Jun 30 '13 at 19:20
  • 2
    This solution has the disadvantage of not working with classpath resources (obtained via `Class.getResource()` or similar methods), while the `Scanner` solution does work in this case. – LordOfThePigs Oct 06 '14 at 19:29
  • This approach works fine with classpath resources: String IAmAString = new String(Files.readAllBytes(Paths.get(((new ClassPathResource("IAmAFile")).getFile()).getAbsolutePath()))); – Rondo Jan 17 '15 at 01:10
  • 2
    a pure java version of my last comment: String iAmAString = new String(Files.readAllBytes(new File(Thread.currentThread().getContextClassLoader().getResource("iAmAFile").toURI()).toPath())); – Rondo Jan 17 '15 at 01:50
  • 1
    @Rondo Not all classpath resources correspond to a `File` (think about a resource inside a jar for example), so no, it can't be used for that in general. – ddekany Feb 23 '17 at 06:08
  • @ddekany you have a misplaced 'no' :) I wasn't trying to make it general. The question pretty much requires a non-general answer since the only general solutions necessitate building the file contents a bit a a time: like this: try{ URL in = ClassLoader.getSystemResource("filename"); System.out.println(in); InputStream is = ClassLoader.getSystemResourceAsStream("filename"); int c; StringBuilder sb = new StringBuilder(); while ((c = is.read()) != -1) { sb.append((char) c); } String iAmAString = sb.toString();; } catch (IOException io) {} – Rondo Feb 24 '17 at 06:46
  • @Jim inputStream is not closed in Api Files.readAllBytes(). – Pruthvi Chitrala Feb 27 '17 at 08:55
  • @PruthviChitrala from the JavaDoc for readAllBytes: Reads all the bytes from a file. The method ensures that the file is closed when all bytes have been read or an I/O error, or other runtime exception, is thrown. The inputStream is not the concern of the caller of Files.readAllBytes. https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#readAllBytes(java.nio.file.Path) – Jim Mar 25 '17 at 08:20
  • 1
    Use of String constructors without charset parameter is not the best practice from the internationalization point of view. I would suggest `new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);` assuming the file is in UTF-8 encoding, which is true in most cases in these days. – Kuro Kurosaka Jan 09 '18 at 21:23
  • 1
    Since Java 11: `String s = Files.readString(Paths.get(filePath))` – Mikolasan Nov 17 '20 at 09:52
47

You can use apache commons IO..

FileInputStream fisTargetFile = new FileInputStream(new File("test.txt"));

String targetFileStr = IOUtils.toString(fisTargetFile, "UTF-8");
Rakesh Goyal
  • 2,947
  • 6
  • 33
  • 65
  • 15
    What is it with Java programmers and always trying to use third party libraries when Java has built in facilities that work just fine. – Jay Feb 15 '14 at 00:57
  • 4
    Of course those facilities "work just fine", it's just that some of them are utterly over-complicated. I agree however that using another lib just for this is a bit overkill. – Andrea Lazzarotto Aug 18 '14 at 09:21
  • 4
    It is not overkill. It is an opportunity. The opportunity to start using the apache commons libraries and become productive. Or you can opt for guava. – Florian F Aug 29 '17 at 10:56
  • It's a three-liner - you'll need to cose the stream. – Pavel Vlasov Aug 05 '20 at 13:14
37

This should work for you:

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

public static void main(String[] args) throws IOException {
    String content = new String(Files.readAllBytes(Paths.get("abc.java")));
}
DDas
  • 405
  • 5
  • 10
  • Thanks! In contrast to the majority solution, this also doesn’t remove the trailing newline. One improvement: `new String(…, StandardCharsets.UTF_8)` – mirabilos Mar 21 '19 at 17:25
25

Using Apache Commons IO.

import org.apache.commons.io.FileUtils;

//...

String contents = FileUtils.readFileToString(new File("/path/to/the/file"), "UTF-8")

You can see de javadoc for the method for details.

cjungel
  • 3,365
  • 1
  • 21
  • 19
11

Don't write your own util class to do this - I would recommend using Guava, which is full of all kinds of goodness. In this case you'd want either the Files class (if you're really just reading a file) or CharStreams for more general purpose reading. It has methods to read the data into a list of strings (readLines) or totally (toString).

It has similar useful methods for binary data too. And then there's the rest of the library...

I agree it's annoying that there's nothing similar in the standard libraries. Heck, just being able to supply a CharSet to a FileReader would make life a little simpler...

ThisClark
  • 12,145
  • 9
  • 61
  • 89
Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • 1
    On Java 7, would you recommend Guava or `new String(Files.readAllBytes(Paths.get(filePath)))` ? – Manu Manjunath Jul 09 '14 at 07:24
  • 2
    @Manu: I'd *definitely* not use that - I'd at least specify a character encoding. But as Guava is generally useful anyway (even with Java 8) you might as well use `Files.toString` given how easy it is... – Jon Skeet Jul 09 '14 at 07:32
8

Another alternative approach is:

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

Other option is to use utilities provided open source libraries
http://commons.apache.org/io/api-1.4/index.html?org/apache/commons/io/IOUtils.html

Why java doesn't provide such a common util API ?
a) to keep the APIs generic so that encoding, buffering etc is handled by the programmer.
b) make programmers do some work and write/share opensource util libraries :D ;-)

Community
  • 1
  • 1
7

Sadly, no.

I agree that such frequent operation should have easier implementation than copying of input line by line in loop, but you'll have to either write helper method or use external library.

Nikita Rybak
  • 64,889
  • 22
  • 150
  • 172
1

I discovered that the accepted answer actually doesn't always work, because \\Z may occur in the file. Another problem is that if you don't have the correct charset a whole bunch of unexpected things may happen which may cause the scanner to read only a part of the file.

The solution is to use a delimiter which you are certain will never occur in the file. However, this is theoretically impossible. What we CAN do, is use a delimiter that has such a small chance to occur in the file that it is negligible: such a delimiter is a UUID, which is natively supported in Java.

String content = new Scanner(file, "UTF-8")
    .useDelimiter(UUID.randomUUID().toString()).next();
wvdz
  • 15,266
  • 3
  • 43
  • 82
  • What do you mean by "\\Z may occur in the file"? \Z (after unescaping) is one of the patterns of java.util.regex.Pattern, not the literal character sequence. The literal character sequence, a backslash followed by Z, in the file would not match with the pattern \Z. – Kuro Kurosaka Dec 20 '17 at 17:43
  • @KuroKurosaka I don't mean the literal sequence `\Z`, I mean the file may actually contain the 'End of string' character somewhere in the middle of the file. It happened to me, and was the reason the accepted answer did not work for me. – wvdz Jan 06 '18 at 11:12
  • I see. You are thinking of a situation where a piece of software or OS decided to use a control character other than CR or LF (or both, in case of Microsoft) for the EOL sequence. I'd write it something like "'\u001A', for example, if Control-Z is used to as the EOF character". – Kuro Kurosaka Jan 07 '18 at 19:15