2009-05-25 9 views
34

Dans un programme Java (Java 1.5), j'ai un BufferedWriter qui enveloppe un FileWriter, et j'appelle write() beaucoup de fois ... Le fichier résultant est assez grand ...Quand rincer un BufferedWriter

Parmi les lignes de ce fichier, certaines d'entre elles sont incomplètes ...

Dois-je appeler flush à chaque fois que j'écris quelque chose (mais je suppose que ce serait inefficace) ou utiliser une autre méthode de BufferedWriter ou utiliser une autre classe ...?

(Puisque j'ai une ligne de zillion à écrire, je veux avoir quelque chose de très efficace.) Quel serait le moment idéal pour "flush"? (Quand je tends la capacité du BufferedWriter) ...

Init:

try { 
    analysisOutput = new BufferedWriter(new FileWriter(
     "analysisResults", true)); 
    analysisOutput.newLine(); 
    analysisOutput.write("Processing File " + fileName + "\n"); 
} 
catch (FileNotFoundException ex) { 
    ex.printStackTrace(); 
} 
catch (IOException ex) { 
    ex.printStackTrace(); 
} 

Rédaction:

private void printAfterInfo(String toBeMoved,HashMap<String, Boolean> afterMap, Location location) 
    throws IOException { 
    if(afterMap != null) { 
     for (Map.Entry<String, Boolean> map : afterMap.entrySet()) { 
     if (toBeMoved == "Condition") { 
      if (1 <= DEBUG) 
      System.out.println("###" + toBeMoved + " " + location + " " 
       + conditionalDefs.get(conditionalDefs.size() - 1) 
       + " After " + map.getKey() + " " 
       + map.getValue() + "\n"); 

      analysisOutput.write("###" + toBeMoved + " " + location + " " 
       + conditionalDefs.get(conditionalDefs.size() - 1) 
       + " After " + map.getKey() + " " + map.getValue() 
       + "\n"); 
     } else { 
      if (1 <= DEBUG) 
      System.out.println("###" + toBeMoved + " " + location + " " 
       + map.getKey() + " After " 
       + map.getValue() + "\n"); 
      if (conditionalDefs.size() > 0) 
      analysisOutput.write("###" + toBeMoved + " " + location + " " 
       + conditionalDefs.get(conditionalDefs.size() - 1) + " " 
       + map.getKey() + " After " + map.getValue() 
       + "\n"); 
      else 
      analysisOutput.write("###" + toBeMoved + " " + location + " " + map.getKey() + " After " + map.getValue() + "\n"); 


     } 
     } 
    } 

Je viens compris que les lignes qui sont incomplètes sont celles qui viennent avant "Processing file" ... donc cela se produit quand je passe d'un fichier que j'analyse à un autre ...

Clôture:

dispatch(unit); 

try { 
    if (analysisOutput != null) { 
    printFileInfo(); 
    analysisOutput.close(); 
    } 
} 
catch (IOException ex) { 
    ex.printStackTrace(); 
} 

Parfois, les informations imprimées par printFileInfo ne figure pas dans le fichier de résultats ...

+0

sont incomplets, avez-vous plusieurs threads à écrire? IIRC un BufferedWriter n'est pas thread-safe, donc cela pourrait être une explication, mais il ne doit pas être "rincé manuellement" pour faire plus de place, il prend soin de lui-même. –

+0

Si vous n'êtes pas sûr que votre question est claire, fournissez peut-être un échantillon de code ou un échantillon de sortie qui clarifie. –

+0

Il est réellement thread-safe (bien que les décorateurs de Writer ont des problèmes d'accord sur quel objet verrouiller). –

Répondre

74

Le BufferedWriter sera déjà vidé lorsqu'il remplit son tampon. A partir de la documentation de BufferedWriter.write:

Ordinairement cette méthode stocke les caractères du tableau donné dans le tampon de ce courant, rinçage du tampon au flux sous-jacent au besoin.

(moi qui souligne.)

Le point de BufferedWriter est essentiellement de consolider beaucoup de petites écritures dans beaucoup moins grandes écritures, car c'est généralement plus efficace (mais plus d'une douleur au code). Vous ne devriez pas avoir besoin de faire quoi que ce soit de spécial pour le faire fonctionner correctement, sinon de vous assurer de le vider quand vous avez fini avec lui - et appeler close() le fera et vider/fermer l'écrivain sous-jacent de toute façon. En d'autres termes, relaxez - écrivez, écrivez, fermez et fermez :) La seule fois où vous devez normalement appeler flush manuellement, c'est si vous avez réellement besoin des données sur le disque. (Par exemple, si vous avez un enregistreur perpétuel, vous voudrez peut-être le vider de temps en temps pour que celui qui lit les journaux n'ait pas besoin d'attendre que le tampon soit plein avant de pouvoir voir de nouvelles entrées!)

+0

Testé et approuvé. Écrit 10Mb de chiffres ligne par ligne: rinçage après écrire chaque ligne - prend 7 secondes, sans rinçage - 4 secondes. –

8

Le moment de rinçage idéal est quand vous avez besoin d'un autre programme de lecture du fichier pour voir les données qui a été écrit, avant que le fichier est fermé. Dans de nombreux cas, ce n'est jamais.

+0

même si le BufferedWriter est grand ... je n'ai pas à le faire à un stade intermédiaire? – LB40

+0

Si le tampon se remplit, il écrira son contenu sur le disque. L'API BufferedWriter est conçue pour être un remplacement direct d'un FileWriter, à l'exception de la consommation de données avant la fermeture du fichier. – Dave

Questions connexes