1614

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();
    }
}
Naman
  • 23,555
  • 22
  • 173
  • 290
OscarRyz
  • 184,433
  • 106
  • 369
  • 548
  • 7
    Can anyone explain me in a very simple way what's with the NIO? Each time I read about itI get lost in the nth mention of channel :( – OscarRyz Nov 28 '08 at 18:33
  • 7
    do remember that it's not guaranteed that the line separator in the file isn't necessary the same as the system's line separator. – Henrik Paul Nov 28 '08 at 18:35
  • 6
    Code above has a bug of adding extra new line char at the last line. It should be something like following if(line = reader.readLine() ) != null){ stringBuilder.append( line ); } while (line = reader.readLine() ) != null) { stringBuilder.append( ls ); stringBuilder.append( line ); } – Deep Aug 12 '11 at 10:29
  • 28
    Java 7 introduces `byte[] Files.readAllBytes(file);` To those, who suggest the 'one-line' Scanner solution: Don't yo need to close it? – Val Jan 17 '12 at 15:20
  • @OscarRyz The biggest change for me is that NIO allows you to listen to many ports without allocating a thread for each. Not a problem unless you want to send a packet to every machine in a class B network address space (65k addresses) to see what exists, Windows runs out of threads at around 20k (Found this out solving exactly this problem--discovery of a class A/B network, before NIO it was tough). – Bill K Mar 17 '15 at 16:40
  • If you see the Files.readAllBytes() implementation, you will notice it is using a channel which is closeable. So no need to close it explicitly. – Rajesh Goel Jun 05 '17 at 23:41
  • With the advent of Groovy, you can read the file thus: return new File( file).text() – Piko Aug 02 '17 at 19:12
  • Linking another StackOverflow link, which find is well explained: https://stackoverflow.com/questions/14169661/read-complete-file-without-using-loop-in-java – Love Bisaria Nov 14 '17 at 01:26
  • @Deep The last line in a text file is usually line-terminated, so what you describe as a bug isn't one, and your code has the bug of removing *all* the line terminators. – user207421 Feb 07 '19 at 23:37

32 Answers32

1665

Read all text from a file

Java 11 added the readString() method to read small files as a String, preserving line terminators:

String content = Files.readString(path, StandardCharsets.US_ASCII);

For versions between Java 7 and 11, here's a compact, robust idiom, wrapped up in a utility method:

static String readFile(String path, Charset encoding)
  throws IOException
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

Read lines of text from a file

Java 7 added a convenience method to read a file as lines of text, represented as a List<String>. This approach is "lossy" because the line separators are stripped from the end of each line.

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java 8 added the Files.lines() method to produce a Stream<String>. Again, this method is lossy because line separators are stripped. If an IOException is encountered while reading the file, it is wrapped in an UncheckedIOException, since Stream doesn't accept lambdas that throw checked exceptions.

try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

This Stream does need a close() call; this is poorly documented on the API, and I suspect many people don't even notice Stream has a close() method. Be sure to use an ARM-block as shown.

If you are working with a source other than a file, you can use the lines() method in BufferedReader instead.

Memory utilization

The first method, that preserves line breaks, can temporarily require memory several times the size of the file, because for a short time the raw file contents (a byte array), and the decoded characters (each of which is 16 bits even if encoded as 8 bits in the file) reside in memory at once. It is safest to apply to files that you know to be small relative to the available memory.

The second method, reading lines, is usually more memory efficient, because the input byte buffer for decoding doesn't need to contain the entire file. However, it's still not suitable for files that are very large relative to available memory.

For reading large files, you need a different design for your program, one that reads a chunk of text from a stream, processes it, and then moves on to the next, reusing the same fixed-sized memory block. Here, "large" depends on the computer specs. Nowadays, this threshold might be many gigabytes of RAM. The third method, using a Stream<String> is one way to do this, if your input "records" happen to be individual lines. (Using the readLine() method of BufferedReader is the procedural equivalent to this approach.)

Character encoding

One thing that is missing from the sample in the original post is the character encoding. There are some special cases where the platform default is what you want, but they are rare, and you should be able justify your choice.

The StandardCharsets class defines some constants for the encodings required of all Java runtimes:

String content = readFile("test.txt", StandardCharsets.UTF_8);

The platform default is available from the Charset class itself:

String content = readFile("test.txt", Charset.defaultCharset());

Note: This answer largely replaces my Java 6 version. The utility of Java 7 safely simplifies the code, and the old answer, which used a mapped byte buffer, prevented the file that was read from being deleted until the mapped buffer was garbage collected. You can view the old version via the "edited" link on this answer.

erickson
  • 249,448
  • 50
  • 371
  • 469
  • Quite interesting. What does the channel means. I know that is to avoid block the "thread?" They can be bidirectional ( or that's what I understood ) But, in more simple word, what are they? Can you elaborate further? – OscarRyz Nov 28 '08 at 19:07
  • In many ways, a ReadableByteChannel is like an InputStream, and WritableByteChannel is like an OutputStream. Many concrete Channels implement both of these interfaces, so one object is bi-directional. Some channels (SocketChannel) support non-blocking IO, but this isn't true of all channels. – erickson Nov 28 '08 at 19:11
  • Do you know the time- and memory-efficiencies of this idiom, or can at least estimate? It's a beautiful idiom! – Humphrey Bogart Jun 17 '09 at 20:00
  • 3
    Technically speaking, it's O(n) in time and space. Qualitatively, due the immutability requirement of Strings, it's pretty hard on memory; temporarily there are two copies of the char data in memory, plus the room for the encoded bytes. Assuming some single-byte encoding, it will (temporarily) require 5 bytes of memory for each character in the file. Since the question asks specifically for a String, that's what I show, but if you can work with the CharBuffer returned by "decode", the memory requirement is much less. Time-wise, I don't think you'll find anything faster in the core Java libs. – erickson Jun 17 '09 at 20:16
  • 5
    Possible typo? NIO has a Charset (not CharSet) class called java.nio.charset.Charset. Is this what CharSet should have been? – Jonathan Wright Dec 20 '09 at 22:43
  • 34
    Note : after exercising a bit that code, I found out that you can't reliably delete the file right after reading it with this method, which may be a non issue in some case, but not mine. May it be in relation with this issue : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 ? I finally went with the proposition of Jon Skeet which doesn't suffer from this bug. Anyways, I just wanted to give the info, for other people, just in case... – Sébastien Nussbaumer Aug 19 '10 at 15:47
  • 5
    @Sébastien Nussbaumer: I also bumped on this problem. Amazing that the bug has been marked "Will Not Fix". This essentially means that `FileChannel#map` is, in general, unusable. – Joonas Pulakka Nov 09 '10 at 07:45
  • 4
    @Sébastien Nussbaumer: The bug has been deleted from the Oracle / Sun Bug Database: "This bug is not available." Google cached the site at http://webcache.googleusercontent.com/search?q=cache:bugs.sun.com/bugdatabase/view_bug.do%3Fbug_id%3D4715154 – bobndrew Aug 01 '11 at 12:06
  • I tried reading an exe file using this method with default charset, append some data in it and again make it an exe, But it corrupted the exe, Any thoughts ? – foobar Sep 13 '13 at 07:21
  • 1
    @smilepleeeaz What you describe makes no sense. EXE files are not text. And they have a well-defined structure. First you are destroying the content of the file by decoding it as text, then you are destroying the structure by appending text to it. How could this fail to corrupt the EXE? – erickson Sep 13 '13 at 15:20
  • I don't really care about encoding, could I just use `Charset.defaultCharset()` instead of having an argument accepting it? – corazza Jan 11 '14 at 21:22
  • 1
    @yannbane If you are sure that the file will always be encoded with the platform's default character set, yes, you could do that. If there's a mismatch, then you'll care about encoding. – erickson Jan 11 '14 at 23:25
  • 1
    As of Java 8, the charset can be omitted to default to using UTF-8. Thus reading all lines becomes `Files.readAllLines(Paths.get("/your/path/to/file"));` – Matthew Madson Mar 27 '14 at 02:19
  • What is the benefit of this: encoding.decode(ByteBuffer.wrap(encoded)).toString(); versus this: new String(encoded, encoding); – Trejkaz Apr 11 '14 at 23:33
  • @Trejkaz There isn't one! I think that was just carried over from the original code which used a mapped buffer. Thanks for pointing it out. – erickson Apr 12 '14 at 00:33
  • magnifico, java 8 solution as well – JohnMerlino Jun 04 '14 at 20:21
  • In my case, I was doing this from a static method so it looked like this: `URL url = NarrationDataProvider.class.getResource(filePath); byte[] encoded = Files.readAllBytes(Paths.get(url.toURI())); return new String(encoded, StandardCharsets.US_ASCII);` – Philippe Jul 30 '14 at 16:51
  • Does any of this apply to compilers? – CMCDragonkai Apr 19 '15 at 08:20
  • 1
    I tried using the readFile method of this answer but I can't find where the `Files` class is located. I'm using JDK 1.7.0_79 – Jpaji Rajnish Jun 30 '15 at 00:24
  • 1
    @JpajiRajnish [`java.nio.file.Files`](http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html) – erickson Jun 30 '15 at 00:25
  • Unfortunately this code snippet isn't working in Android. – Miral Sarwar Aug 24 '15 at 10:17
  • @MiralSarwar "isn't working" isn't a clear problem description. What happens? Which of the four code snippets are you talking about? – erickson Aug 24 '15 at 16:01
  • java.nio.file.Files or java.nio.file.Paths is not supported in Android. – Miral Sarwar Aug 25 '15 at 04:02
  • @MiralSarwar Well, this question is about Java, not Android, but the Java 6 version (viewable in the edit history) will work on Android. – erickson Aug 25 '15 at 16:04
  • The "Character encoding" section needs to go now that you've removed all other references to Apache Commons IO. – Powerlord Feb 04 '16 at 15:22
  • @Powerlord That section has nothing to do with Apache Commons IO. It's completely relevant to core Java NIO. – erickson Feb 04 '16 at 16:37
  • @erickson In the paragraph starting with "Technically speaking,", When you said, "Time-wise, I don't think you'll find anything faster in the core Java libs.", you meant that the idiom using readAllBytes() is the fastest? – Sam Apr 08 '21 at 00:47
  • 1
    @Sam that comment was from 2009; it does not consider APIs that were created at a later time. Nowadays, there is no reason not to use the newer `Files.readString`. It’s the fastest *and* least memory consuming method. In the reference implementation, it uses tricks that other libraries could not use and avoids the redundant-copies problem. In the best case, there is only one copy of the character data in memory at any time (for iso-latin-1 or all-ascii strings, the I/O buffer will be the resulting string’s backing array without any copy operation). – Holger May 21 '21 at 13:05
  • @Holger is it still the fastest if you want a list of lines, to use ```Files.readString().split("\n")```? The docs say that 2GB is too big for this method; what would be the most efficient for files larger than 2GB when you need it all as a string or StringBuffer (assuming a string can't hold that much), or a list of strings, assuming it is too much for a StringBuffer? – Sam May 21 '21 at 14:09
  • 2
    @Sam A `StringBuffer` can’t hold that much either. The limitation is that the size is stored as an `int`. I think the most efficient alternative for that size would be `Files.readAllLines()`. I haven’t benchmarked it though. – erickson May 21 '21 at 14:16
  • 1
    @Sam don’t use A when you want B. The fact that `Files.readString` is the most efficient way to read a file *into a single string* doesn’t imply that using it when you actually want something entirely different, like a *list of lines*, was a good idea. As erickson said, there’s `Files.readAllLines​` doing the job. – Holger May 21 '21 at 16:05
  • 3
    @Sam If reading lines works for you, you should consider the final state you want for those strings. The use cases that come to my mind for multi-gigabyte files in memory are caches; these are likely to need some sort of index, and it seems less likely that you'll have a direct use for `List`. So instead of loading the list, and then converting each string to another object, and then adding each of those to some other data structure, you should read one line, convert it to the necessary type, and add it to the structure. Then do the next. Use stream-wise processing. – erickson May 21 '21 at 16:21
  • @erickson in my case, the objects are windowed every 4 lines, seperated by a blank line in the text file. I did not see any methods for the ```Stream``` class that would help. I am not sure if you intended for the literal use of the ```Stream``` class, or to process the files chunk by chunk. I am not sure how to do the latter ideomatically/in a memory efficient manner. – Sam May 23 '21 at 20:37
  • 1
    @Sam If your input is one line per record, an actual `Stream` would work, but I was talking more generally. In your case, I think the most idiomatic approach would be to create a `BufferedReader`, and, in a loop, read the five lines representing each record/object in each iteration. If you can do all the necessary processing for that item inside the loop, you won't need to keep a reference, and memory usage will be constant. If you need to keep *all* the objects together after reading the file, you can add them to a suitable collection in the loop. – erickson May 24 '21 at 15:42
  • Good idea! Thank you! – Sam May 24 '21 at 21:04
370

If you're willing to use an external library, check out Apache Commons IO (200KB JAR). It contains an org.apache.commons.io.FileUtils.readFileToString() method that allows you to read an entire File into a String with one line of code.

Example:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}
MultiplyByZer0
  • 4,341
  • 3
  • 27
  • 46
Willi aus Rohr
  • 4,520
  • 1
  • 14
  • 7
  • I don't find that method in the URL you provide. – OscarRyz Nov 28 '08 at 18:52
  • 2
    It's in the class org.apache.commons.io.FileUtils – Cyrille Ka Nov 28 '08 at 19:04
  • 2
    I'm using FileUtils too, but I'm wondering what is better betwwen using FileUtils or the accepted nio answer? – Guillaume Feb 09 '10 at 16:31
  • 4
    @Guillaume: The biggest question is whether you're comfortable having a dependency on a 3rd party library. If you do have Commons IO or [Guava](http://stackoverflow.com/a/2224519/56285) in your project, then use that (just for code simplicity; otherwise there likely won't be a noticeable difference). – Jonik Dec 29 '13 at 13:04
186

A very lean solution based on Scanner:

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Or, if you want to set the charset:

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Or, with a try-with-resources block, which will call scanner.close() for you:

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

Remember that the Scanner constructor can throw an IOException. And don't forget to import java.io and java.util.

Source: Pat Niemeyer's blog

MultiplyByZer0
  • 4,341
  • 3
  • 27
  • 46
Pablo Grisafi
  • 4,915
  • 1
  • 17
  • 28
  • 4
    \\A works because there is no "other beginning of file", so you are in fact read the last token...which is also the first. Never tried with \\Z. Also note you can read anything that is Readable , like Files, InputStreams, channels...I sometimes use this code to read from the display window of eclipse, when I'm not sure if I'm reading one file or another...yes, classpath confuses me. – Pablo Grisafi Sep 16 '11 at 20:16
  • 1
    As the poster, I can say I really don't know if and when the file is properly close...I never write this one in production code, I use it only for tests or debug. – Pablo Grisafi Jun 04 '12 at 17:26
  • 2
    It has a limit of 1024 chars I think – Whimusical Jul 04 '12 at 14:32
  • 21
    Scanner implements Closeable (it invokes close on the source) - so while elegant it shouldn't really be a one-liner. The default size of the buffer is 1024, but Scanner will increase the size as necessary (see Scanner#makeSpace()) – earcam Nov 23 '12 at 09:43
  • 8
    This one fails for empty files with a `java.util.NoSuchElementException`. – SpaceTrucker Aug 02 '13 at 09:16
  • 1
    This solution allows to read files from streams, so you are able to read e.g classpath resources. The widely suggested `Files.readAllBytes(Paths.get(path))` solution doesn't work e.g in JEE environment. – Vladimir Sosnin Sep 25 '15 at 19:20
  • Also, don't forget to call `trim()` on the resulting String, unless you want the `\r\n` appended to the end. – shieldgenerator7 Feb 02 '16 at 17:16
  • 2
    @SpaceTrucker this can be fixed by using `sc.findWithinHorizon("(?s).*", 0)` instead of `.useDelimiter("\\A").next()`. Then, it will match the entire (possibly empty) file instead of searching for a separator. – Holger Sep 13 '19 at 08:53
  • 1
    @VladimirSosnin it dependents on the type of the classpath resource and available file system implementations. For files and module storage, `Files.readAllBytes(Paths.get(url.toURI()))` works out-of-the-box, whereas for jar entries, you’ll have to create the `ZipFileSystem` once manually at the beginning of your application. For other, special constructs, your container would have to provide the necessary file system, which is indeed not guaranteed. But since Java 9, you can call `readAllBytes()` directly on the `InputStream`. – Holger Sep 13 '19 at 08:57
141
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

since java 7 you can do it this way.

J J
  • 4,698
  • 5
  • 30
  • 48
80

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

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}
Dónal
  • 176,670
  • 166
  • 541
  • 787
  • 2
    I think this is the best way. Check out http://java.sun.com/docs/books/tutorial/essential/io/scanning.html – Tarski Nov 28 '08 at 19:19
  • 3
    The Scanner constructor that accepts a String doesn't treat the string as the name of a file to read, but as the text to be scanned. I make that mistake all the time. :-/ – Alan Moore Nov 29 '08 at 09:10
  • @Alan, good catch. I edited Don's answer slightly to fix that (I hope). – Jonik Apr 17 '10 at 10:12
  • 3
    fileContents.append(scanner.nextLine()).append(lineSeparator); – ban-geoengineering May 24 '13 at 10:53
  • 1
    Change the initialization statement to `Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));`. Otherwise you may only capture part of the file. – Wei Yang Oct 22 '13 at 17:40
  • This method will add an extra separator at the end of the file, when there isn't one in the actual file (for an a file that ends with no newline). – forumulator Aug 10 '18 at 03:35
  • @WeiYang Why is that? – golimar Oct 24 '18 at 14:42
72

Guava has a method similar to the one from Commons IOUtils that Willi aus Rohr mentioned:

import com.google.common.base.Charsets;
import com.google.common.io.Files;

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

EDIT by PiggyPiglet
Files#toString is deprecated, and due for removal Octobor 2019. Instead use Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

EDIT by Oscar Reyes

This is the (simplified) underlying code on the cited library:

InputStream in = new FileInputStream(file);
byte[] b  = new byte[file.length()];
int len = b.length;
int total = 0;

while (total < len) {
  int result = in.read(b, total, len - total);
  if (result == -1) {
    break;
  }
  total += result;
}

return new String( b , Charsets.UTF_8 );

Edit (by Jonik): The above doesn't match the source code of recent Guava versions. For the current source, see the classes Files, CharStreams, ByteSource and CharSource in com.google.common.io package.

PiggyPiglet
  • 156
  • 2
  • 14
finnw
  • 45,253
  • 22
  • 134
  • 212
  • This code has casting from long to int which could pop up some crazy behaviour with big files. Has extra spaces and where do you close the inputstream? – Mohamed Taher Alrefaie Apr 22 '13 at 15:42
  • @M-T-A: The stream *is* closed, note the use of `Closer` in [CharSource](http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/io/CharSource.java). The code in the answer isn't the actual, current Guava source. – Jonik Dec 29 '13 at 13:19
56
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 "";
    }
user590444
  • 3,968
  • 7
  • 32
  • 42
  • 6
    Or even more simple: `new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));` –  Aug 06 '12 at 21:54
  • 13
    or `new String(Files.readAllBytes(Paths.get(filename)));` :-) – assafmo Apr 06 '13 at 12:09
  • 1
    Well played, and to save the next guy the Googling, [`Paths` is apparently 1.7+](http://docs.oracle.com/javase/7/docs/api/java/nio/file/Paths.html) as is [`FileSystems`](http://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystems.html). (Dang it!) – ruffin Apr 09 '13 at 19:51
  • 4
    It;s a shame this answer doesn't have more votes. I was looking for the quickest and simplest way to get a text file into a String. This is it and if I didn't scroll down and down and down, I would have missed it. The OP should consider accepting this answer to move it to the top. – Thorn Apr 16 '13 at 04:40
  • 1
    @Thorn This answer has horrible error handling. Don't use this method in production code, or better: never. – xehpuk Feb 20 '15 at 23:35
52

If you need a string processing (parallel processing) Java 8 has the great Stream API.

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines

More examples are available in JDK samples sample/lambda/BulkDataOperations that can be downloaded from Oracle Java SE 8 download page

Another one liner example

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));
Andrei N
  • 4,316
  • 4
  • 27
  • 29
51

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();
    }        
}
J J
  • 4,698
  • 5
  • 30
  • 48
Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
29

Gathered all the possible ways to read the File as String from Disk or Network.

  • Guava: Google using classes Resources, Files

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }
    

  • APACHE - COMMONS IO using classes IOUtils, FileUtils

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }
    

  • Java 8 BufferReader using Stream API

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }
    

  • Scanner Class with regex \A. which matches the beginning of input.

    static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
    public static String streamURL_Scanner( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    public static String streamFile_Scanner( File file ) throws IOException {
        Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    

  • Java 7 (java.nio.file.Files.readAllBytes)

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }
    

  • BufferedReader using InputStreamReader.

    public static String getDiskFile_Lines( File file ) throws IOException {
        StringBuffer text = new StringBuffer();
        FileInputStream fileStream = new FileInputStream( file );
        BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }
    

Example with main method to access the above methods.

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@see

Yash
  • 7,342
  • 2
  • 55
  • 63
26

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
J J
  • 4,698
  • 5
  • 30
  • 48
Home in Time
  • 261
  • 3
  • 2
25

Since JDK 11:

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8
leventov
  • 12,780
  • 10
  • 60
  • 91
  • Why, oh why, introduce new methods that rely on the default charset in 2018 ? – mryan Sep 24 '18 at 07:49
  • 2
    @mryan this method doesn't rely on the default system charset. It defaults to UTF-8, that is fine. – leventov Sep 24 '18 at 11:39
  • @leventov you're right ! so does Files.readAllLines ! that makes the files API not very consistent with older methods but it's for the better :) – mryan Sep 25 '18 at 13:34
17

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();
    }
}
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
16

Java attempts to be extremely general and flexible in all it does. As a result, something which is relatively simple in a scripting language (your code would be replaced with "open(file).read()" in python) is a lot more complicated. There doesn't seem to be any shorter way of doing it, except using an external library (like Willi aus Rohr mentioned). Your options:

  • Use an external library.
  • Copy this code into all your projects.
  • Create your own mini-library which contains functions you use often.

Your best bet is probably the 2nd one, as it has the least dependencies.

Community
  • 1
  • 1
Claudiu
  • 206,738
  • 150
  • 445
  • 651
  • 4
    Yeap. It makes the "high" level language take a different meaning. Java is high level compared with C but low compared with Python or Ruby – OscarRyz Nov 28 '08 at 19:36
  • 3
    Agree that Java is long on high-level abstractions but short on convenience methods – Dónal May 11 '11 at 16:44
  • 3
    True, Java has an insane number of ways of dealing with Files and many of them seem complicated. But this is fairly close to what we have in higher level languages: `byte[] bytes = Files.readAllBytes(someFile.toPath());` – Thorn Apr 16 '13 at 20:45
16

With Java 7, this is my preferred option to read a UTF-8 file:

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");

Since Java 7, the JDK has the new java.nio.file API, which provides many shortcuts, so 3rd party libraries are not always required for simple file operations.

Moritz Petersen
  • 11,897
  • 2
  • 35
  • 42
11

Using JDK 8 or above:

no external libraries used

You can create a new String object from the file content (Using classes from java.nio.file package):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}
leventov
  • 12,780
  • 10
  • 60
  • 91
Saikat
  • 8,190
  • 12
  • 69
  • 94
7

If you do not have access to the Files class, you can use a native solution.

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);
}
Ilya Gazman
  • 27,805
  • 19
  • 119
  • 190
7

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);
}
Dan Dyer
  • 51,823
  • 16
  • 125
  • 165
  • 3
    This will change the newlines to the default newline choise. This may be desirable, or unintended. – Peter Lawrey Apr 18 '10 at 07:23
  • Rolled back the edit to this answer because the point was to narrow the scope of the `line` variable. The edit declared it twice, which would be a compile error. – Dan Dyer Aug 01 '13 at 20:16
4

A flexible solution using IOUtils from Apache commons-io in combination with StringWriter:

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();

It works with any reader or input stream (not just with files), for example when reading from a URL.

tuckerpm
  • 141
  • 1
  • 10
wau
  • 810
  • 7
  • 19
3

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.

Henry
  • 39
  • 2
  • 1
    This code may give unpredictable results. According to the [documentation](http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available%28%29) of the `available()` method, there is no guarantee that the end of file is reached in the event that the method returns 0. In that case you might end up with an incomplete file. What's worse, the number of bytes actually read can be smaller than the value returned by `available()`, in which case you get corrupted output. – wau Mar 15 '13 at 13:32
3
public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}
Scott S. McCoy
  • 1,067
  • 11
  • 11
  • I think this has the inconvenience os using the platform default encoding. +1 anyway :) – OscarRyz Feb 09 '10 at 15:53
  • 7
    I seems to me that the finally block does not know variables defined in the try block. javac 1.6.0_21 throws the error `cannot find symbol`. – ceving Jun 25 '12 at 16:11
  • Have you even tried your own code? You've defined reader in try/catch block, so it won't be accessible in finally block. – mauron85 Oct 31 '18 at 09:48
3

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!");
}
jamesjara
  • 534
  • 5
  • 14
3

Based on @erickson`s answer, you can use:

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}
Muskovets
  • 423
  • 8
  • 13
3

User java.nio.Files to read all lines of file.

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}
Nitin
  • 1,882
  • 1
  • 14
  • 42
3

This one uses the method RandomAccessFile.readFully, it seems to be available from JDK 1.0 !

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}
barjak
  • 9,744
  • 3
  • 30
  • 46
2

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

One of best answers here (https://stackoverflow.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();
    }
}
Community
  • 1
  • 1
Ajk
  • 491
  • 1
  • 5
  • 13
  • In the first case you might be adding an extra newline at the end. in the second case you might be omitting one. So both are equally wrong. See [this article](https://www.linkedin.com/pulse/overcoming-javas-readline-limitation-patrick-parker/) – Patrick Parker Mar 28 '18 at 13:46
2

After Ctrl+F'ing after Scanner, I think that the Scanner solution should be listed too. In the easiest to read fashion it goes like this:

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}

If you use Java 7 or newer (and you really should) consider using try-with-resources to make the code easier to read. No more dot-close stuff littering everything. But that's mostly a stylistic choice methinks.

I'm posting this mostly for completionism, since if you need to do this a lot, there should be things in java.nio.file.Files that should do the job better.

My suggestion would be to use Files#readAllBytes(Path) to grab all the bytes, and feed it to new String(byte[] Charset) to get a String out of it that you can trust. Charsets will be mean to you during your lifetime, so beware of this stuff now.

Others have given code and stuff, and I don't want to steal their glory. ;)

Haakon Løtveit
  • 770
  • 7
  • 18
2

Using this library, it is one line:

String data = IO.from(new File("data.txt")).toString();
satnam
  • 8,425
  • 4
  • 25
  • 39
2

Also if your file happens to be inside a jar, you can also use this:

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\\A").next();
    }
}

The path should start with / for instance if your jar is

my.jar/com/some/thing/a.txt

Then you want to invoke it like this:

String myTxt = fromFileInJar("/com/com/thing/a.txt");
OscarRyz
  • 184,433
  • 106
  • 369
  • 548
2

In one line (Java 8), assuming you have a Reader:

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));
Malcolm Boekhoff
  • 862
  • 10
  • 7
0

Use code:

File file = new File("input.txt");
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
                file));
byte[] buffer = new byte[(int) file.length()];
bin.read(buffer);
String fileStr = new String(buffer);

fileStr contains output in String.

Devram Kandhare
  • 666
  • 1
  • 8
  • 20
-2

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


}

}