代码之家  ›  专栏  ›  技术社区  ›  Patrick

将Java StrugBu建器倾倒到文件中

  •  34
  • Patrick  · 技术社区  · 15 年前

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

    你可以做到:

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

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

    有更好的方法吗?

    9 回复  |  直到 5 年前
        1
  •  39
  •   Manos Nikolaidis    8 年前

    正如其他人所指出的,使用一个编写器,并使用缓冲编写器,但不要调用 writer.write(stringBuilder.toString()); 相反,只是 writer.append(stringBuilder); .

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

    1. 它不接受 java.nio.Charset . 坏的。您应该总是显式地指定一个字符集。

    2. 它仍然让你痛苦 stringBuilder.toString() . 如果您真正追求的是简单性,请尝试 Guava 项目:

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

        2
  •  23
  •   rob    8 年前

    您应该使用BufferedWriter来优化写入(始终使用写入程序而不是输出流写入字符数据)。如果不编写字符数据,则将使用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();
    }
    

    或者,尝试使用资源(Java 7和UP)

    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带宽,除非另一个线程在您写入的同时试图从磁盘读取大量数据。

        3
  •  15
  •   NawaMan    15 年前

    如果绳子很大, 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);
    }
    

    希望这有帮助。

        4
  •  14
  •   JeanValjean    7 年前

    你可以用 Apache Commons IO 图书馆,给你 FileUtils :

    FileUtils.writeStringToFile(file, stringBuilder.toString(), Charset.forName("UTF-8"))
    
        5
  •  3
  •   BalusC    15 年前

    更好地使用字符数据 Reader/Writer . 在您的情况下,使用 BufferedWriter . 如果可能,使用 业余作家 从一开始,而不是 StringBuilder 保存内存。

    请注意,您调用非参数的方式 getBytes() 方法将使用平台默认字符编码来解码字符。例如,如果平台默认编码为 ISO-8859-1 当字符串数据包含 ISO-859-1 字符集。最好使用 getBytes(charset) 在中,您可以自己指定字符集,例如 UTF-8 .

        6
  •  1
  •   Madhawa Priyashantha Artur    9 年前

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

    OutputStreamWriter writer = new OutputStreamWriter(
            new BufferedOutputStream(outputStream), "utf-8");
    
    for (int i = 0; i < sb.length(); i++) {
        writer.write(sb.charAt(i));
    }
    
        7
  •  0
  •   Community Egal    7 年前

    基于 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);
            }
        }
    }
    
        8
  •  0
  •   dotwin    6 年前

    大多数答案的基准+改进的实施: 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();
    }
    
        9
  •  0
  •   John Alexander Betts    5 年前

    由于Java 8,您只需要这样做:

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

    你不需要任何第三方图书馆来做这件事。