1
votes

Conception de programme lors de l'utilisation de BufferedWriter, dois-je ouvrir et fermer le fichier à plusieurs reprises?

J'ai un programme qui fait beaucoup de traitement avec des boucles et écrit des chaînes dans un fichier à de nombreux points différents. Je ne suis pas sûr de la conception générale de la meilleure façon de procéder. Je n'aurai pas besoin de lire le fichier à aucun moment pendant l'exécution, mais je souhaiterai le voir par la suite.

Premièrement, un BufferedWriter avec FileWriter est-il un moyen raisonnable de le faire?

Deuxièmement, probablement je ne veux pas ouvrir et fermer ceci chaque fois que je veux écrire quelque chose (plusieurs fois par seconde).

Mais si j'utilise essayer avec des ressources, je devrais mettre pratiquement tout programme à l'intérieur de cet essai, est-ce normal?

Pour le moment, le squelette ressemble à:

try (FileWriter writer = new FileWriter("filename.txt");
     BufferedWriter bw = new BufferedWriter(writer)) {

} catch (IOException e) {
    //catch IO error
}

for (//main loop){
    bw.write(string);
    for (//several sub loops){
        bw.write(//more strings);
    }
    for (//several sub loops){
        bw.write(//more strings);
    }
}

bw.write(//final string);

try {
    bw.close();
} catch (IOException ex) {
    //catch IO error
}

Est-ce que cela semble raisonnable ou y a-t-il un meilleur moyen? Merci beaucoup d'avance pour l'aide.

Modifier - merci à vous tous pour l'aide, a totalement répondu à mes questions.


3 commentaires

Comment ce code se compile-t-il même? bw n'est pas dans la portée après le bloc try-with-resources. Avez-vous un autre bw défini ailleurs?


Il ne compile pas, c'est juste un croquis. C'est l'un de mes problèmes, aurais-je besoin de mettre l'ensemble de mon code dans les boucles for dans un essai avec des ressources?


@John Il y a des façons dont vous n'avez pas, une façon est de produire la String à écrire avant le bloc try-with-resources, puis de l'écrire dans son ensemble. Mais comme cela est décrit dans ma réponse, ce n'est pas une mémoire compatible avec les gros fichiers. Mais tant que vous n'écrivez pas pendant des heures avec de longues pauses, n'hésitez pas à garder le fichier ouvert et à enrouler le bloc autour de lui. Améliorez la lisibilité en produisant le contenu dans des méthodes uniques afin que le bloc try ne soit pas trop gonflé et mauvais à lire.


4 Réponses :


0
votes

Mais si j'utilise essayer avec des ressources, je devrais mettre pratiquement programme entier à l'intérieur de cet essai, est-ce normal?

C'est comme ça que fonctionne try-catch-with-resources - il ferme les ressources en quittant le bloc try . Si cela vous dérange, n'utilisez pas cette construction et vous gérez vous-même writer .

Le squelette ci-dessus ne fonctionnera pas car le premier essai ouvrira et fermera vos rédacteurs;


0 commentaires

1
votes

Premièrement, un BufferedWriter avec FileWriter est-il un moyen raisonnable de faire cela?

Oui, cela devrait être le moyen le plus pratique de le faire.

Deuxièmement, je ne veux probablement pas ouvrir et fermer ceci chaque fois que je veux écrire quelque chose (plusieurs fois par seconde).

Vous ne devriez vraiment pas. Mais vous écraseriez votre progression de cette façon chaque fois que vous ouvrez le fichier de toute façon. C'est parce que vous n'avez pas dit à FileWriter d'ajouter à un fichier existant (via new FileWriter ("filename.txt", true); .

Mais si j'utilise try avec des ressources, je devrais mettre pratiquement tout le programme dans cet essai, est-ce normal?

Je ne vois pas de problème avec cela. Vous pouvez (et devriez) toujours déplacer votre logique dans vos propres méthodes ou classes, qui peuvent renvoyer les String s à écrire. De cette façon, vous séparez la logique métier réelle de la logique d'écriture du fichier technique et structurez votre code, ce qui le rend plus facile à comprendre.

Vous pouvez également simplement écrire dans une grosse chaîne , puis écrire cette chaîne dans le bloc try-with-resources . Mais cela a ses limites avec de très gros fichiers et peut parfois ne pas être le meilleur choix.


0 commentaires

0
votes

Il est tout à fait correct de mettre tout le code dans une routine try-catch. Chaque fois que vous avez des problèmes à écrire dans le fichier, il le détecte et ne vous donne pas d'erreur. Cependant, je vous recommande d'essayer cette structure avec une seule routine try-catch.

try  { (FileWriter writer = new FileWriter("filename.txt");
 BufferedWriter bw = new BufferedWriter(writer)) 

for (/*main loop*/){
   bw.write(string);
   for (/*several sub loops*/){
    bw.write(/*more strings*/);
    }
for (/*several sub loops*/){
    bw.write(/*more strings*/);
    }
   }

bw.write(/*final string*/);


bw.close(); 


} catch (IOException e) {
   System.out.println("error");
}

PS: Si vous commentez quelque chose entre du code, utilisez ceci: / * comment * / au lieu de ceci: // car il mettra en commentaire toute la ligne.


3 commentaires

Vous avez la syntaxe d'ouverture du try-with-resources incorrecte. De plus, vous n'avez plus besoin de fermer BufferedWriter car le bloc try géré le fait pour vous.


Vous êtes dans le bloc TOWER, pas besoin de fermer explicitement


@Zhedar, comment la syntaxe est-elle erronée? Bon point de fermeture inutile.



0
votes

Voici une alternative qui permet une gestion plus fine des exceptions. Dans de nombreux cas, c'est préférable. Avoir un bloc catch qui gère trop d'exceptions devient très déroutant: le flux de contrôle est obscurci, et le diagnostic des erreurs peut être beaucoup plus difficile.

Avoir un fichier ouvert pendant tout le temps d'exécution d'un programme est très courant. C'est souvent le cas pour les fichiers journaux. Si vous savez que votre programme fonctionnera pendant une longue période et si vous pensez qu’il y aura de longs délais entre la sortie vers un seul fichier, vous pouvez ouvrir et fermer le fichier pour chaque lot d'opérations rapprochées. Mais vous devez avoir une idée claire du modèle d'activité pour ce faire, car vous voudrez faire correspondre l'heure d'ouverture du fichier avec les lots d'écritures à court terme attendus. Vous devez absolument éviter les opérations d'ouverture et de fermeture à haute fréquence. Cela entraîne toutes sortes de frais supplémentaires indésirables.

package my.tests;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.function.Consumer;

public class WriterTest {
    public static final String TARGET_NAME = "filename.txt";

    public void performMainLoop() {
        performWrites( this::mainLoop, TARGET_NAME );
    }

    public void performWrites( Consumer<Writer> writeActor, String targetName ) {
        FileWriter fileWriter;
        try {
            fileWriter = new FileWriter(targetName);
        } catch ( IOException e ) {
            System.out.println("Open failure: " + e.getMessage());
            e.printStackTrace();
            return;
        }

        BufferedWriter bufferedWriter = null;
        try {
            bufferedWriter = new BufferedWriter(fileWriter);
            writeActor.accept(bufferedWriter);

        } finally {
            if ( bufferedWriter != null ) {
                try {
                    bufferedWriter.close();
                } catch ( IOException e ) {
                    System.out.println("Unexpected close failure: " + e.getMessage());
                    e.printStackTrace();
                }
            } else {
                try {
                    fileWriter.close();
                } catch ( IOException e ) {
                    System.out.println("Unexpected close failure: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    }

    public void mainLoop(Writer writer) {
        for ( int loopNo = 0; loopNo < 10; loopNo++ ) {
            try {
                writer.write("Loop [ " + Integer.toString(loopNo) + " ]\n");

            } catch ( IOException e ) {
                System.out.println("Unexpected write failure: " + e.getMessage());
                e.printStackTrace();
                return;
            }
        }
    }
}


1 commentaires

Beaucoup de code standard, pas de try-catch-with-resources, fermer les deux écrivains tout en fermant l'écrivain tamponné ferait l'affaire.