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<String>
). 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.
-
\$\begingroup\$ You can refer to this Stack Overflow question. \$\endgroup\$Tunaki– Tunaki2016年01月23日 23:43:11 +00:00Commented Jan 23, 2016 at 23:43
1 Answer 1
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.
-
\$\begingroup\$ Yup, that was obvious! And yes, the files are smallish anyway, so I'm not too concerned about storing everything in-memory inefficiently in this case. \$\endgroup\$Edd– Edd2016年01月24日 11:26:32 +00:00Commented Jan 24, 2016 at 11:26