HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Reading entire contents of file at a given java.no.file.Path into a String

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
readingfilepathentireintocontentsjavastringgiven

Problem

What I'm wanting to do is create a String readFile(Path filePath, Charset encoding) method, that returns the entire contents of a given file.

I'm wanting the equivalent of Guava's Files.toString(file, encoding), but without calling the Path.getFile() method (as this method only works with the default filesystem provider, and in this particular case I'm wanting to write tests that use JimFS).

I've written the following, but I'm wondering if it can be improved:

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import java.nio.file.Files;
⋮
public String readFile(Path path, Charset encoding) throws IOException {
    Preconditions.checkState(Files.exists(path), "File does not exist: %s", path);
    Preconditions.checkState(Files.isRegularFile(path), "File is not regular file: %s", path);

    return Joiner.on(System.lineSeparator()).join(Files.readAllLines(path, encoding));
}


Is there a better way to read the file in (such as without using Files.readAllLines() which results in a slightly awkward List). I'd previously joined this result together by streaming the lines of the file, and then immediately collecting them with Collectors.joining(System.lineSeparator()), but since the project has a dependency on Guava for other purposes, it seems preferable to use the Joiner available.

I'm happy to restrict this to Java 8 and onwards if needed, and as previously mentioned I already have a dependency on Guava, but I'd rather not add too many dependencies if possible.

Solution

I believe you are missing a relatively obvious, although somewhat memory-inefficient Files.readAllBytes(...) .... Consider this:

public String readFile(Path path, Charset encoding) throws IOException {
    return new String(Files.readAllBytes(path), encoding);
}


In your code you also have two full copies of the file in-memory at one time, so the files can't be huge. The code I suggest also pulls all the data in to memory twice, once as a byte[] array, which gets converted to a String, and the byte[] array is discarded.

There would be a loopy way to solve it by using a StringBuilder and a smaller byte[] array, or ByteBuffer, but, if your files are smallish, I would not worry about the byte[] size.

Code Snippets

public String readFile(Path path, Charset encoding) throws IOException {
    return new String(Files.readAllBytes(path), encoding);
}

Context

StackExchange Code Review Q#117722, answer score: 5

Revisions (0)

No revisions yet.