Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Java StringBuilder转储到文件_Java_File_Stringbuilder - Fatal编程技术网

将Java StringBuilder转储到文件

将Java StringBuilder转储到文件,java,file,stringbuilder,Java,File,Stringbuilder,将StringBuilder转储到文本文件的最有效/最优雅的方法是什么 你可以做: outputStream.write(stringBuilder.toString().getBytes()); 但是,对于非常长的文件,这是否有效 有更好的方法吗?您应该使用BufferedWriter来优化写入(始终使用Writer而不是OutputStream来写入字符数据)。如果您没有写入字符数据,您将使用BufferedOutputStream File file = new File("path/t

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

你可以做:

outputStream.write(stringBuilder.toString().getBytes());
但是,对于非常长的文件,这是否有效


有更好的方法吗?

您应该使用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(Java 7及更高版本)

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

您可以使用该库,它为您提供:


对于字符数据,最好使用
读写器
。在您的情况下,请使用
BufferedWriter
。如果可能,从一开始就使用
BufferedWriter
,而不是
StringBuilder
,以节省内存


请注意,调用非arg
getBytes()
方法的方法将使用平台默认字符编码来解码字符。如果平台默认编码为例如
ISO-8859-1
,而字符串数据包含
ISO-8859-1
字符集之外的字符,则此操作可能失败。最好使用
getBytes(charset)
,您可以自己指定字符集,例如
UTF-8

如果字符串很大,
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);
}
final StringBuilder aSB=。。。;
最终整数长度=aSB.length();
最终int aChunk=1024;
最终字符[]aChars=新字符[aChunk];
对于(int aPosStart=0;aPosStart

希望这有帮助。

正如其他人所指出的,使用Writer和BufferedWriter,但不要调用
Writer.write(stringBuilder.toString())而只是
writer.append(stringBuilder)

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

  • 它不接受
    java.nio.Charset
    。糟糕。您应该始终显式指定字符集

  • 它仍然让您遭受
    stringBuilder.toString()
    的痛苦。如果您真正追求的是简单性,请尝试以下项目:


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

    OutputStreamWriter writer = new OutputStreamWriter(
            new BufferedOutputStream(outputStream), "utf-8");
    
    for (int i = 0; i < sb.length(); i++) {
        writer.write(sb.charAt(i));
    }
    
    OutputStreamWriter writer=新的OutputStreamWriter(
    新的BufferedOutputStream(outputStream),“utf-8”);
    for(int i=0;i
    基于

    我创建这个函数时使用了
    OutputStreamWriter
    write()
    ,这也是内存优化,比只使用
    StringBuilder.toString()
    要好

    公共静态无效stringBuilderToOutputStream(
    StringBuilder sb、OutputStream out、字符串字符集名称、int缓冲区)
    抛出IOException{
    char[]chars=新字符[缓冲区];
    try(OutputStreamWriter=newoutputstreamwriter(out,charsetName)){
    for(int aPosStart=0;aPosStart
    此处大多数答案的基准测试+改进的实施:

    最终的实现是按照

    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();
    }
    
    试试看{
    BufferedWriter bw=新的BufferedWriter(
    新的OutputStreamWriter(
    新的FileOutputStream(文件、追加)、字符集、缓冲区大小);
    试一试{
    最终整数长度=sb.length();
    最终字符[]字符=新字符[缓冲区大小];
    int-idxEnd;
    
    对于(int idxStart=0;idxStart,自java 8以来,您只需执行以下操作:

    Files.write(path.get(“/path/to/file/file_name.extension”)、stringBuilder.toString().getBytes());


    您不需要任何第三方库就可以做到这一点。

    您会说“很长”有多大是吗?在KB、MB或更大的数量级上?您的StringBuilder的大小是否会接近任何实际限制,比如分配给JVM的最大内存?可能只有几兆字节……没有StringBuilder我无法做到,这是我的API返回的结果。+1它不是很慢,只是用50MB的字符串进行了测试。但它确实节省了内存。(对于其他方法,大约2MB比130MB)@NawaMan“巨大”的性能差异来自底层的OutputStream。在许多情况下,写入(数组)方法调用在内部分解为一个while循环。很好的例子。这比.append解决方案的内存效率高吗?我想writer可能正在做类似的事情。@Thomas Ahle:据我所知(并尝试过),append即使不是最有效的,也是最有效的。另一个非常有效的方法(对于流)是
    write(byte)
    。Java是开放的
    OutputStreamWriter writer = new OutputStreamWriter(
            new BufferedOutputStream(outputStream), "utf-8");
    
    for (int i = 0; i < sb.length(); i++) {
        writer.write(sb.charAt(i));
    }
    
    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);
            }
        }
    }
    
    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();
    }