769 votes

Comment ajouter du texte à un fichier existant en Java ?

J'ai besoin d'ajouter du texte de façon répétée à un fichier existant en Java. Comment faire ?

915voto

Kip Points 37013

Faites-vous cela à des fins de journalisation ? Si c'est le cas, il existe plusieurs bibliothèques pour cela . Deux des plus populaires sont Log4j y Retour à la case départ .

Java 7+

Pour une tâche ponctuelle, le Classe de fichiers facilite les choses :

try {
    Files.write(Paths.get("myfile.txt"), "the text".getBytes(), StandardOpenOption.APPEND);
}catch (IOException e) {
    //exception handling left as an exercise for the reader
}

Attention : L'approche ci-dessus génère un NoSuchFileException si le fichier n'existe pas encore. Il n'ajoute pas non plus de nouvelle ligne automatiquement (ce que vous souhaitez souvent lors de l'ajout d'un fichier texte). Une autre approche consiste à passer les deux commandes CREATE y APPEND qui crée d'abord le fichier s'il n'existe pas déjà :

private void write(final String s) throws IOException {
    Files.writeString(
        Path.of(System.getProperty("java.io.tmpdir"), "filename.txt"),
        s + System.lineSeparator(),
        CREATE, APPEND
    );
}

Toutefois, si vous écrivez plusieurs fois dans le même fichier, les extraits ci-dessus doivent ouvrir et fermer le fichier sur le disque plusieurs fois, ce qui est une opération lente. Dans ce cas, un BufferedWriter est plus rapide :

try(FileWriter fw = new FileWriter("myfile.txt", true);
    BufferedWriter bw = new BufferedWriter(fw);
    PrintWriter out = new PrintWriter(bw))
{
    out.println("the text");
    //more code
    out.println("more text");
    //more code
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}

Notes :

  • Le deuxième paramètre de la fonction FileWriter lui indiquera d'ajouter au fichier, plutôt que d'écrire un nouveau fichier. (Si le fichier n'existe pas, il sera créé).
  • L'utilisation d'un BufferedWriter est recommandé pour un écrivain coûteux (tel que FileWriter ).
  • L'utilisation d'un PrintWriter vous donne accès à println que vous avez probablement l'habitude d'utiliser dans le cadre du programme System.out .
  • Mais le BufferedWriter y PrintWriter ne sont pas strictement nécessaires.

Ancienne Java

try {
    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("myfile.txt", true)));
    out.println("the text");
    out.close();
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}

Traitement des exceptions

Si vous avez besoin d'une gestion robuste des exceptions pour les anciennes versions de Java, cela devient très verbeux :

FileWriter fw = null;
BufferedWriter bw = null;
PrintWriter out = null;
try {
    fw = new FileWriter("myfile.txt", true);
    bw = new BufferedWriter(fw);
    out = new PrintWriter(bw);
    out.println("the text");
    out.close();
} catch (IOException e) {
    //exception handling left as an exercise for the reader
}
finally {
    try {
        if(out != null)
            out.close();
    } catch (IOException e) {
        //exception handling left as an exercise for the reader
    }
    try {
        if(bw != null)
            bw.close();
    } catch (IOException e) {
        //exception handling left as an exercise for the reader
    }
    try {
        if(fw != null)
            fw.close();
    } catch (IOException e) {
        //exception handling left as an exercise for the reader
    }
}

35 votes

Vous devez soit utiliser le try-with-resources de Java7, soit placer le close() dans un bloc finally, afin de vous assurer que le fichier est fermé en cas d'exception.

3 votes

Imaginons que new BufferedWriter(...) lève une exception ; l'option FileWriter être fermé ? Je pense qu'il ne sera pas fermé, parce que les close() (dans des conditions normales) sera invoquée sur la méthode out qui, dans ce cas, ne sera pas initialisé - donc, en fait, l'objet close() ne sera pas invoquée -> le fichier sera ouvert, mais ne sera pas fermé. Ainsi, l'IMHO try devrait ressembler à ceci try(FileWriter fw = new FileWriter("myFile.txt")){ Print writer = new ....//code goes here } Et il devrait flush() l'auteur avant de quitter le try bloc !!!

7 votes

Attention, l'exemple "Older java" ne fermera pas correctement le flux si une exception est levée dans le bloc try.

201voto

northpole Points 5793

Vous pouvez utiliser fileWriter avec un drapeau fixé à true pour l'annexer.

try
{
    String filename= "MyFile.txt";
    FileWriter fw = new FileWriter(filename,true); //the true will append the new data
    fw.write("add a line\n");//appends the string to the file
    fw.close();
}
catch(IOException ioe)
{
    System.err.println("IOException: " + ioe.getMessage());
}

10 votes

close devrait être placé dans finally comme indiqué dans le bloc Réponse de @etech au cas où une exception serait levée entre la création du FileWriter et l'invocation de la fermeture.

5 votes

Bonne réponse, bien qu'il soit préférable d'utiliser System.getProperty( "line.separator" ) pour une nouvelle ligne plutôt que ". \n ".

0 votes

@Decoded J'ai annulé votre modification sur cette réponse, car elle ne compile pas.

75voto

etech Points 503

Toutes les réponses ici avec des blocs try/catch ne devraient-elles pas contenir les éléments .close() dans un bloc finally ?

Exemple de réponse corrigée :

PrintWriter out = null;
try {
    out = new PrintWriter(new BufferedWriter(new FileWriter("writePath", true)));
    out.println("the text");
} catch (IOException e) {
    System.err.println(e);
} finally {
    if (out != null) {
        out.close();
    }
} 

En outre, depuis Java 7, vous pouvez utiliser un fichier Déclaration sur l'utilisation des ressources . Aucun bloc final n'est nécessaire pour fermer la (les) ressource(s) déclarée(s), car cette opération est gérée automatiquement et est également moins verbeuse :

try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("writePath", true)))) {
    out.println("the text");
} catch (IOException e) {
    System.err.println(e);
}

1 votes

Quand out sort de son champ d'application, il est automatiquement fermé lorsqu'il est ramassé, n'est-ce pas ? Dans votre exemple avec le finally je pense que vous avez en fait besoin d'un autre try/catch imbriqué autour de out.close() si je me souviens bien. La solution Java 7 est plutôt bien pensée ! (Je n'ai pas fait de développement Java depuis Java 6, donc je ne connaissais pas ce changement).

2 votes

@Kip Non, sortir du champ d'application ne fait rien en Java. Le fichier sera fermé à un moment aléatoire dans le futur. (probablement à la fermeture du programme)

0 votes

@etech La deuxième approche nécessitera-t-elle la flush méthode ?

53voto

ripper234 Points 39314

Utilisation d'Apache Commons 2.1 :

import org.apache.logging.log4j.core.util.FileUtils;

FileUtils.writeStringToFile(file, "String to append", true);

7 votes

Oh, merci. J'ai été amusé par la complexité de toutes les autres réponses. Je ne comprends vraiment pas pourquoi les gens aiment se compliquer la vie (de développeur).

8 votes

Le problème de cette approche est qu'elle ouvre et ferme le flux de sortie à chaque fois. En fonction de ce que vous écrivez dans votre fichier et de la fréquence à laquelle vous le faites, cela peut entraîner un surcoût ridicule.

1 votes

@Buffalo a raison. Mais vous pouvez toujours utiliser StringBuilder pour construire de gros morceaux (qui valent la peine d'être écrits) avant de les écrire dans un fichier.

23voto

Emily L. Points 696

Veillez à ce que le flux soit correctement fermé dans tous les cas de figure.

Il est un peu alarmant de constater le nombre de réponses qui laissent la poignée du fichier ouverte en cas d'erreur. La réponse https://stackoverflow.com/a/15053443/2498188 est dans le mille, mais seulement parce que BufferedWriter() ne peut pas lancer. Si c'était le cas, une exception quitterait le FileWriter objet ouvert.

Une façon plus générale de procéder qui ne se préoccupe pas de savoir si BufferedWriter() peut lancer :

  PrintWriter out = null;
  BufferedWriter bw = null;
  FileWriter fw = null;
  try{
     fw = new FileWriter("outfilename", true);
     bw = new BufferedWriter(fw);
     out = new PrintWriter(bw);
     out.println("the text");
  }
  catch( IOException e ){
     // File writing/opening failed at some stage.
  }
  finally{
     try{
        if( out != null ){
           out.close(); // Will close bw and fw too
        }
        else if( bw != null ){
           bw.close(); // Will close fw too
        }
        else if( fw != null ){
           fw.close();
        }
        else{
           // Oh boy did it fail hard! :3
        }
     }
     catch( IOException e ){
        // Closing the file writers failed for some obscure reason
     }
  }

Edita:

Depuis Java 7, il est recommandé d'utiliser "try with resources" et de laisser la JVM s'en charger :

  try(    FileWriter fw = new FileWriter("outfilename", true);
          BufferedWriter bw = new BufferedWriter(fw);
          PrintWriter out = new PrintWriter(bw)){
     out.println("the text");
  }  
  catch( IOException e ){
      // File writing/opening failed at some stage.
  }

0 votes

+1 pour l'ARM correct avec Java 7. Voici une bonne question sur ce thème délicat : stackoverflow.com/questions/12552863/ .

1 votes

Hmm, pour une raison ou une autre PrintWriter.close() n'est pas déclaré comme throws IOException en les docs . En examinant ses source , le close() ne peut en effet pas lancer de IOException parce qu'il l'attrape dans le flux sous-jacent et met un drapeau. Ainsi, si vous travaillez sur le code de la prochaine navette spatiale ou sur un système de mesure de la dose de rayons X, vous devriez utiliser PrintWriter.checkError() après avoir tenté de out.close() . Cela aurait vraiment dû être documenté.

0 votes

Si nous voulons être super paranoïaques en ce qui concerne la fermeture, chacune de ces XX.close() devrait être dans son propre try/catch, n'est-ce pas ? Par exemple, out.close() pourrait lever une exception, auquel cas bw.close() y fw.close() ne serait jamais appelé, et fw est celui qui est le plus important à clôturer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X