将 Java StringBuilder 转储到文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1677194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 21:17:29  来源:igfitidea点击:

Dumping a Java StringBuilder to File

javafilestringbuilder

提问by Patrick

What is the most efficient/elegant way to dump a StringBuilder to a text file?

将 StringBuilder 转储到文本文件的最有效/最优雅的方法是什么?

You can do:

你可以做:

outputStream.write(stringBuilder.toString().getBytes());

But is this efficient for a very long file?

但是这对于一个很长的文件有效吗?

Is there a better way?

有没有更好的办法?

采纳答案by Kevin Bourrillion

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

正如其他人所指出的,使用 Writer 并使用 BufferedWriter,但不要writer.write(stringBuilder.toString());只调用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:

编辑:但是,我看到您接受了不同的答案,因为它是单行的。但该解决方案有两个问题:

  1. it doesn't accept a java.nio.Charset. BAD. You should always specify a Charset explicitly.

  2. it's still making you suffer a stringBuilder.toString(). If the simplicity is really what you're after, try the following from the Guavaproject:

  1. 它不接受java.nio.Charset. 坏的。您应该始终明确指定一个字符集。

  2. 它仍然让你痛苦stringBuilder.toString()。如果您真正追求的是简单性,请尝试从Guava项目中执行以下操作:

Files.write(stringBuilder, file, Charsets.UTF_8)

Files.write(stringBuilder, 文件, Charsets.UTF_8)

回答by rob

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.

您应该使用 BufferedWriter 来优化写入(始终使用 Writer 而不是 OutputStream 写入字符数据)。如果您不编写字符数据,则可以使用 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)

或者,使用 try-with-resources(Java 7 及更高版本)

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.

由于您最终要写入文件,因此更好的方法是更频繁地写入 BufferedWriter,而不是在内存中创建一个巨大的 StringBuilder 并在最后写入所有内容(取决于您的用例,您甚至可以完全消除 StringBuilder)。在处理期间增量写入将节省内存并更好地利用您有限的 I/O 带宽,除非另一个线程试图在您写入的同时从磁盘读取大量数据。

回答by Mike Sickler

You could use the Apache Commons IOlibrary, which gives you FileUtils:

您可以使用Apache Commons IO库,它为您提供FileUtils

FileUtils.writeStringToFile(file, stringBuilder.toString(), Charset.forName("UTF-8"))

回答by BalusC

For character data better use Reader/Writer. In your case, use a BufferedWriter. If possible, use BufferedWriterfrom the beginning on instead of StringBuilderto save memory.

对于字符数据更好地使用Reader/Writer. 在您的情况下,请使用BufferedWriter. 如果可能,BufferedWriter从一开始就使用而不是StringBuilder为了节省内存。

Note that your way of calling the non-arg getBytes()method would use the platform default character encoding to decode the characters. This may fail if the platform default encoding is for example ISO-8859-1while your String data contains characters outside the ISO-8859-1charset. Better use the getBytes(charset)where in you can specify the charset yourself, such as UTF-8.

请注意,您调用非 arggetBytes()方法的方式将使用平台默认字符编码来解码字符。例如ISO-8859-1,如果平台默认编码是您的字符串数据包含字符ISO-8859-1集之外的字符,则这可能会失败。更好地使用getBytes(charset)您可以自己指定字符集的位置,例如UTF-8.

回答by NawaMan

Well, if the string is huge, toString().getBytes()will create duplicate bytes (2 or 3 times). The size of the string.

好吧,如果字符串很大,toString().getBytes()将创建重复的字节(2 或 3 次)。字符串的大小。

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.

希望这可以帮助。

回答by ZZ Coder

If the string itself is long, you definitely should avoid toString(), which makes another copy of the string. The most efficient way to write to stream should be something like this,

如果字符串本身很长,您绝对应该避免使用 toString(),它会生成字符串的另一个副本。写入流的最有效方法应该是这样的,

OutputStreamWriter writer = new OutputStreamWriter(
        new BufferedOutputStream(outputStream), "utf-8");

for (int i = 0; i < sb.length(); i++) {
    writer.write(sb.charAt(i));
}

回答by Daniel De León

Based on https://stackoverflow.com/a/1677317/980442

基于https://stackoverflow.com/a/1677317/980442

I create this function that use OutputStreamWriterand the write(), this is memory optimized too, better than just use StringBuilder.toString().

我创建了这个使用OutputStreamWriter和 的函数write(),这也是内存优化的,比仅仅使用更好StringBuilder.toString()

public static void stringBuilderToOutputStream(
        StringBuilder sb, OutputStream out, String charsetName, int buffer)
        throws IOException {
    char[] chars = new char[buffer];
    try (OutputStreamWriter writer = new OutputStreamWriter(out, charsetName)) {
        for (int aPosStart = 0; aPosStart < sb.length(); aPosStart += buffer) {
            buffer = Math.min(buffer, sb.length() - aPosStart);
            sb.getChars(aPosStart, aPosStart + buffer, chars, 0);
            writer.write(chars, 0, buffer);
        }
    }
}

回答by dotwin

Benchmarks for most answers here + improved implementation: https://www.genuitec.com/dump-a-stringbuilder-to-file/

此处大多数答案的基准 + 改进的实施: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();
}

回答by John Alexander Betts

Since java 8 you only need to do this:

从 Java 8 开始,您只需要执行以下操作:

Files.write(Paths.get("/path/to/file/file_name.extension"), stringBuilder.toString().getBytes());

Files.write(Paths.get("/path/to/file/file_name.extension"), stringBuilder.toString().getBytes());

You don't need any third party libraries to do that.

你不需要任何第三方库来做到这一点。