Frage

Was ist der effizienteste/eleganteste Weg, um einen StringBuilder in eine Textdatei zu werfen?

Du kannst tun:

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

Aber ist das für eine sehr lange Datei effizient?

Gibt es einen besseren Weg?

War es hilfreich?

Lösung

Verwenden Sie einen Schriftsteller und verwenden writer.write(stringBuilder.toString()); Stattdessen gerecht writer.append(stringBuilder);.

Bearbeiten: Aber ich sehe, dass Sie eine andere Antwort angenommen haben, weil es ein Einzeiler war. Diese Lösung hat jedoch zwei Probleme:

  1. es akzeptiert keine java.nio.Charset. SCHLECHT. Sie sollten immer einen Zeichensatz explizit angeben.

  2. Es bringt dich immer noch dazu, a zu leiden stringBuilder.toString(). Wenn die Einfachheit wirklich das ist, wonach Sie suchen, probieren Sie Folgendes aus der Guave Projekt:

Dateien.Write (StringBuilder, Datei, charsets.utf_8)

Andere Tipps

Sie sollten einen gepufferten Writer verwenden, um die Schreibvorgänge zu optimieren (schreiben Sie immer Charakterdaten mit einem Autor anstelle eines Ausgangsstreams). Wenn Sie keine Charakterdaten schreiben würden, würden Sie einen pufferedOutputStream verwenden.

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

Oder mit Try-with-Resources (Java 7 und Up)

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

Da Sie letztendlich in eine Datei schreiben, besteht ein besserer Ansatz darin, häufiger an den Bufferterwriter zu schreiben, anstatt ein riesiges StringBuilder-In-Memory zu erstellen und am Ende alles zu schreiben (abhängig von Ihrem Anwendungsfall können Sie sogar in der Lage sein Um den StringBuilder vollständig zu beseitigen). Inkrementell während der Verarbeitung speichert das Speicher und nutzt Ihre begrenzte E/A -Bandbreite besser, es sei denn, ein anderer Thread versucht, viele Daten von der Festplatte zu lesen, während Sie gleichzeitig schreiben.

Nun, wenn die Saite riesig ist, toString().getBytes() Erstellt doppelte Bytes (2 oder dreimal). Die Größe der Zeichenfolge.

Um dies zu vermeiden, können Sie ein Stück der Zeichenfolge extrahieren und in getrennte Teile schreiben.

So kann es aussehen:

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);                 // Erstellen Sie keinen neuen Puffer
    final CharArrayReader aCARead = new CharArrayReader(aChars); // Erstellen Sie keinen neuen Puffer

    // Dies mag langsam sein, aber es erzeugt keinen Puffer mehr (für Bytes)
    int aByte;
    while((aByte = aCARead.read()) != -1)
        outputStream.write(aByte);
}

Hoffe das hilft.

Sie könnten die verwenden Apache Commons io Bibliothek, die Ihnen gibt FileUtils:

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

Für Zeichendaten besser verwenden Reader/Writer. Verwenden Sie in Ihrem Fall a BufferedWriter. Wenn möglich, verwenden Sie BufferedWriter von Anfang an anstelle von StringBuilder Speicher speichern.

Beachten Sie, dass Ihre Art, das Nicht-ARG anzurufen getBytes() Die Methode würde die Plattform -Standardzeichenkodierung verwenden, um die Zeichen zu dekodieren. Dies kann fehlschlagen, wenn die Plattform -Standardkodierung beispielsweise ist ISO-8859-1 Während Ihre String -Daten Zeichen außerhalb der enthält ISO-8859-1 Charset. Verwenden Sie das getBytes(charset) Wohin können Sie das Zeichen selbst angeben, z. UTF-8.

Wenn die Zeichenfolge selbst lang ist, sollten Sie auf jeden Fall toString () vermeiden, was eine andere Kopie der Zeichenfolge erstellt. Der effizienteste Weg zum Stream sollte so etwas sein.

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

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

Seit Java 8 müssen Sie dies nur tun:

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

Sie brauchen für das tun, was Dritter für Bibliotheken tun.

Bezogen auf https://stackoverflow.com/a/1677317/980442

Ich erstelle diese Funktion, die verwendet wird OutputStreamWriter und die write(), Dies ist auch Speicher optimiert, besser als nur zu verwenden 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);
        }
    }
}

Benchmarks für die meisten Antworten hier + Verbesserte Implementierung: https://www.genuitec.com/dump-astringbuilder-to-file/

Die endgültige Implementierung liegt im Sinne von

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();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top