What is the most efficient/elegant way to dump a StringBuilder to a text file?
You can do:
outputStream.write(stringBuilder.toString().getBytes());
Benchmarks for most answers here + improved implementation: https://www.genuitec.com/dump-a-stringbuilder-to-file/
The final implementation is along the lines of
try {
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(file, append), charset), BUFFER_SIZE);
try {
final int length = sb.length();
final char[] chars = new char[BUFFER_SIZE];
int idxEnd;
for ( int idxStart=0; idxStart<length; idxStart=idxEnd ) {
idxEnd = Math.min(idxStart + BUFFER_SIZE, length);
sb.getChars(idxStart, idxEnd, chars, 0);
bw.write(chars, 0, idxEnd - idxStart);
}
bw.flush();
} finally {
bw.close();
}
} catch ( IOException ex ) {
ex.printStackTrace();
}
You could use the Apache Commons IO library, which gives you FileUtils:
FileUtils.writeStringToFile(file, stringBuilder.toString(), Charset.forName("UTF-8"))
As pointed out by others, use a Writer, and use a BufferedWriter, but then don't call writer.write(stringBuilder.toString());
instead just writer.append(stringBuilder);
.
EDIT: But, I see that you accepted a different answer because it was a one-liner. But that solution has two problems:
it doesn't accept a java.nio.Charset
. BAD. You should always specify a Charset explicitly.
it's still making you suffer a stringBuilder.toString()
. If the simplicity is really what you're after, try the following from the Guava project:
Files.write(stringBuilder, file, Charsets.UTF_8)
You should use a BufferedWriter to optimize the writes (always write character data using a Writer instead of an OutputStream). If you weren't writing character data, you would use a BufferedOutputStream.
File file = new File("path/to/file.txt");
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(stringBuilder.toString());
} finally {
if (writer != null) writer.close();
}
or, using try-with-resources (Java 7 and up)
File file = new File("path/to/file.txt");
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(stringBuilder.toString());
}
Since you're ultimately writing to a file, a better approach would be to write to the BufferedWriter more often instead of creating a huge StringBuilder in-memory and writing everything at the end (depending on your use-case, you might even be able to eliminate the StringBuilder entirely). Writing incrementally during processing will save memory and will make better use of your limited I/O bandwidth, unless another thread is trying to read a lot of data from the disk at the same time you're writing.
Since java 8 you only need to do this:
Files.write(Paths.get("/path/to/file/file_name.extension"), stringBuilder.toString().getBytes());
You don't need any third party libraries to do that.
Well, if the string is huge, toString().getBytes()
will create duplicate bytes (2 or 3 times). The size of the string.
To avoid this, you can extract chunk of the string and write it in separate parts.
Here is how it may looks:
final StringBuilder aSB = ...;
final int aLength = aSB.length();
final int aChunk = 1024;
final char[] aChars = new char[aChunk];
for(int aPosStart = 0; aPosStart < aLength; aPosStart += aChunk) {
final int aPosEnd = Math.min(aPosStart + aChunk, aLength);
aSB.getChars(aPosStart, aPosEnd, aChars, 0); // Create no new buffer
final CharArrayReader aCARead = new CharArrayReader(aChars); // Create no new buffer
// This may be slow but it will not create any more buffer (for bytes)
int aByte;
while((aByte = aCARead.read()) != -1)
outputStream.write(aByte);
}
Hope this helps.