将java stringbuilder转储到文件

d6kp6zgx  于 2021-06-30  发布在  Java
关注(0)|答案(9)|浏览(496)

将stringbuilder转储到文本文件的最有效/最优雅的方法是什么?
你可以做:

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

但是对于一个很长的文件来说这是有效的吗?
有更好的办法吗?

kdfy810k

kdfy810k1#

您应该使用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();
}

或者,使用try with resources(Java7及更高版本)

File file = new File("path/to/file.txt");
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
    writer.write(stringBuilder.toString());
}

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

pb3skfrl

pb3skfrl2#

正如其他人指出的,使用writer,然后使用bufferedwriter,但是不要调用 writer.write(stringBuilder.toString()); 相反只是 writer.append(stringBuilder); .
编辑:但是,我看到你接受了一个不同的答案,因为它是一行。但这种解决方案有两个问题:
它不接受 java.nio.Charset . 糟糕。应该始终显式指定字符集。
它仍然让你痛苦 stringBuilder.toString() . 如果您真正追求的是简单性,请尝试guava项目中的以下方法:
files.write(stringbuilder,文件,字符集.utf\u 8)

wwodge7n

wwodge7n3#

如果字符串本身很长,您肯定应该避免tostring(),因为它会生成字符串的另一个副本。最有效的写入流的方法应该是这样的,

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

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

vmpqdwk34#

为了更好地使用字符数据 Reader/Writer . 在你的情况下,使用 BufferedWriter . 如果可能,使用 BufferedWriter 从一开始 StringBuilder 以节省内存。
请注意,您调用非arg的方式 getBytes() 方法将使用平台默认字符编码来解码字符。例如,如果平台默认编码为 ISO-8859-1 而字符串数据包含 ISO-8859-1 查塞特。最好使用 getBytes(charset) 在中,您可以自己指定字符集,例如 UTF-8 .

hec6srdp

hec6srdp5#

如果绳子很大, toString().getBytes() 将创建重复字节(2或3次)。字符串的大小。
为了避免这种情况,您可以提取字符串的块并将其写在不同的部分中。
下面是它的样子:

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

希望这有帮助。

qybjjes1

qybjjes16#

大多数答案的基准+改进的实施:https://www.genuitec.com/dump-a-stringbuilder-to-file/
最终的实现是按照

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

rqdpfwrv7#

基于https://stackoverflow.com/a/1677317/980442
我创建了这个函数 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);
        }
    }
}
b1zrtrql

b1zrtrql8#

您可以使用apache commons io库,它为您提供了fileutils:

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

ifsvaxew9#

由于java 8,您只需执行以下操作: Files.write(Paths.get("/path/to/file/file_name.extension"), stringBuilder.toString().getBytes()); 您不需要任何第三方库来实现这一点。

相关问题