Question

Quelle est la manière la plus efficace / élégante pour vider un StringBuilder dans un fichier texte?

Vous pouvez faire:

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

Mais est-ce efficace pour un fichier très long?

Y at-il une meilleure façon?

Était-ce utile?

La solution

Comme l'ont souligné d'autres, utiliser un écrivain, et utiliser un BufferedWriter, mais ne pas appeler writer.write(stringBuilder.toString()); plutôt juste writer.append(stringBuilder);.

EDIT: Mais, je vois que vous avez accepté une réponse différente parce qu'il était en une ligne. Mais cette solution a deux problèmes:

  1. il n'accepte pas java.nio.Charset. MAUVAIS. Vous devez toujours spécifier explicitement un jeu de caractères.

  2. il est de vous faire souffrir encore un stringBuilder.toString(). Si la simplicité est vraiment ce que vous êtes après, essayez ce qui suit du projet Goyave :

Files.write (stringbuilder, fichier, Charsets.UTF_8)

Autres conseils

Vous devez utiliser un BufferedWriter pour optimiser les écritures (écrire toujours des données de caractère à l'aide d'un écrivain au lieu d'un OutputStream). Si vous n'êtes pas en train d'écrire des données de caractères, vous devez utiliser un 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();
}

ou, en utilisant try-with-ressources (Java 7 et plus)

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

Puisque vous écrivez en fin de compte à un fichier, une meilleure approche serait d'écrire à la BufferedWriter plus souvent au lieu de créer un énorme StringBuilder en mémoire et d'écriture tout à la fin (en fonction de votre cas d'utilisation, vous pourriez même être en mesure d'éliminer le StringBuilder entièrement). L'écriture progressivement au cours du traitement permettra d'économiser la mémoire et une meilleure utilisation de la bande passante d'E / S limitée, à moins qu'un autre thread tente de lire un grand nombre de données à partir du disque en même temps que vous écrivez.

Eh bien, si la chaîne est énorme, toString().getBytes() va créer octets en double (2 ou 3 fois). La taille de la chaîne.

Pour éviter cela, vous pouvez extraire partie de la chaîne et l'écrire dans des parties séparées.

Voici comment il peut les regards:

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.

Vous pouvez utiliser le Apache Commons IO bibliothèque de qui vous donne FileUtils :

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

Pour les données de caractère mieux utiliser Reader/Writer. Dans votre cas, utilisez un BufferedWriter. Si possible, utilisez BufferedWriter depuis le début à la place de StringBuilder pour économiser la mémoire.

Notez que votre façon d'appeler la méthode getBytes() non-arg utiliserait le caractère par défaut pour la plate-forme de codage décoder les caractères. Cela peut échouer si l'encodage par défaut de la plate-forme est par exemple ISO-8859-1 alors que vos données de chaîne contient des caractères en dehors du jeu de caractères ISO-8859-1. Mieux utiliser le getBytes(charset) où en vous pouvez spécifier le charset vous, comme UTF-8.

Si la chaîne elle-même est longue, vous devez absolument éviter toString (), ce qui en fait une autre copie de la chaîne. La façon la plus efficace d'écrire à flux doit être quelque chose comme ça,

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

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

Depuis java 8 il vous suffit de faire ceci:

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

Vous ne avez pas besoin de bibliothèques tierces pour le faire.

Basé sur https://stackoverflow.com/a/1677317/980442

Je crée cette fonction qui utilisent OutputStreamWriter et write(), ce mémoire est optimisé aussi, mieux que simplement utiliser 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);
        }
    }
}

Repères pour la plupart des réponses ici + une meilleure mise en œuvre: https: // www .genuitec.com / dump-a-à-stringbuilder fichier /

La mise en œuvre finale est le long des lignes de

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top