web-dev-qa-db-fra.com

BufferedWriter n'écrit pas tout dans son fichier de sortie

J'ai un programme Java qui lit du texte dans un fichier, ligne par ligne, et écrit le nouveau texte dans un fichier de sortie. Mais tout le texte que j'écris sur ma BufferedWriter ne figure pas dans le fichier de sortie une fois le programme terminé. Pourquoi donc?

Les détails: le programme prend un document texte CSV et le convertit en commandes SQL pour insérer les données dans une table. Le fichier texte contient plus de 10000 lignes qui ressemblent à ce qui suit:

2007,10,9,1,1,1006134,19423882

Le programme semble fonctionner correctement, sauf qu'il s'arrête dans le fichier de manière aléatoire au milieu de la création d'une nouvelle instruction SQL après l'avoir imprimée dans le fichier SQL. Cela ressemble à quelque chose comme:

insert into nyccrash values (2007, 1, 2, 1, 4, 1033092, 259916);
insert into nyccrash values (2007, 1, 1, 1, 1, 1020246, 197687);
insert into nyccrash values (2007, 10, 9, 1

Cela se produit après environ 10000 lignes, mais plusieurs centaines de lignes avant la fin du fichier. La rupture se produit entre 1 et ,. Cependant, les caractères ne semblent pas importants car si je change le 1 en un 42, la dernière chose écrite dans le nouveau fichier est 4, ce qui coupe le 2 de cet entier. Il semble donc que le lecteur ou l'écrivain doit être en train de mourir après avoir écrit/lu une certaine quantité.

Mon code Java est le suivant:

import Java.io.*;

public class InsertCrashData
{
    public static void main (String args[])
    {
        try
        {   
            //Open the input file.
            FileReader istream = new FileReader("nyccrash.txt");
            BufferedReader in = new BufferedReader(istream);
            //Open the output file.
            FileWriter ostream = new FileWriter("nyccrash.sql");
            BufferedWriter out = new BufferedWriter(ostream);
            String line, sqlstr;

            sqlstr = "CREATE TABLE nyccrash (crash_year integer, accident_type integer, collision_type integer, weather_condition integer, light_condition integer, x_coordinate integer, y_coordinate integer);\n\n"; 
            out.write(sqlstr);

            while((line = in.readLine())!= null)
            {
                String[] esa = line.split(",");
                sqlstr = "insert into nyccrash values ("+esa[0]+", "+esa[1]+", "+esa[2]+", "+esa[3]+", "+esa[4]+", "+esa[5]+", "+esa[6]+");\n";
                out.write(sqlstr);
            }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}
28
golmschenk

Vous devez fermer votre OutputStream qui effacera le reste de vos données:

out.close();

La taille de tampon par défaut pour BufferedWriter est 8192 caractères , suffisamment grande pour contenir facilement des centaines de lignes de données non écrites.

61
Reimeus

Vous devezclose() votre BufferedWriter. Vous devez close() votre BufferedWriter car il est -A Writer et implémente donc AutoCloseable , ce qui signifie

Une ressource qui doit être fermée lorsqu'elle n'est plus nécessaire.

Certaines personnes disent que vous devez d'abord appeler flush() pour votre BufferedWriter avant d'appeler close(). Ils ont tort. La documentation de BufferedWriter.close() indique qu'il "ferme le flux, le vide d'abord _" (caractères gras ajoutés).

La sémantique documentée du rinçage ( flush() ) est

Purge ce flux en écrivant toute sortie mise en mémoire tampon dans le flux sous-jacent

Donc, vous devez close, et close videra toute sortie mise en mémoire tampon.

Votre fichier de sortie n'inclut pas tout le texte que vous avez écrit sur votre BufferedWriter car il en a stocké une partie dans un tampon. La BufferedWriter n'a jamais vidé ce tampon, le transférant dans le fichier, car vous ne lui avez jamais dit de le faire.


Depuis Java 7, le meilleur moyen de s’assurer qu’une ressource AutoCloseable, telle qu’une BufferedWriter, est fermée quand il n’est plus nécessaire d’avoir recours est d’utiliser la gestion automatique des ressources (ARM), également appelée try-with-resources :

 try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) {
    // writes to out here
 } catch (IOException ex) {
    // handle ex
 }

Vous devez également close votre BufferedReader quand vous n'en avez plus besoin. Vous devez donc avoir des blocs imbriqués try-with-resources:

 try (BufferedReader in = new BufferedReader(new FileReader("nyccrash.txt")) {
    try (BufferedWriter out = new BufferedWriter(new FileWriter("nyccrash.sql"))) {
       // your reading and writing code here
    }
 } catch (IOException ex) {
    // handle ex
 }
9
Raedwald

Une ressource qui doit être fermée lorsqu'elle n'est plus nécessaire.

finally {
    out.close();//this would resolve the issue
    }

Quelques points à considérer: 

  • BufferedWriter.close()vide le tampon dans le flux sous-jacent, donc si vous oubliez de flush() et ne fermez pas, votre fichier risque de ne pas contenir tout le texte que vous avez écrit. 
  • BufferedWriter.close() ferme également le Writer enveloppé. Quand ceci est un FileWriter, ceci fermera finalement un FileOutputStream et dira au système d'exploitation que vous avez fini d'écrire dans le fichier. 
  • Le garbage collector appellera automatiquement close(), pas sur BufferedWriter ou FileWriter encapsulé, mais sur FileOuputStream. Donc, le système d'exploitation sera content, mais vous devez attendre le GC. 
  • Cependant, vous voulez toujours libérer les ressources du système d'exploitation dès que vous n'en avez plus besoin. Cela vaut pour les fichiers ouverts, les connexions à la base de données, les files d'attente d'impression, etc. Fais moi confiance pour ce coup là. 
  • BufferedWriter.close() efface le tampon de caractères interne, de sorte que la mémoire sera disponible pour le nettoyage de la mémoire, même si BufferedWriter lui-même reste dans la portée. 

Alors, fermez toujours vos ressources (pas seulement les fichiers) lorsque vous avez terminé.

Si vous voulez vraiment jeter un coup d'œil sous les couvertures, la plupart des sources de l'API Java sont disponibles. BufferedWriter est ici .

6
Jaimin Patel

Votre code ne semble pas fermer le rédacteur une fois que vous avez fini de l'écrire. Ajoutez une out.close() (de préférence dans un bloc finally) et cela devrait fonctionner correctement.

5
Ian Roberts

vous ne fermez pas votre BufferedWriter.close-le dans un bloc finally 

   finally {
    out.close();//this would resolve the issue
    }
5
PermGenError

vous ne fermez pas votre BufferedWriter.close-le dans un bloc finally

finally {
out.close();//this would resolve the issue
}

Cela marche. J'ai fait face au même problème et cela a fonctionné pour moi .. Bonne chance :)

1
Harini

Fermez toujours vos ressources (pas seulement les fichiers) lorsque vous en avez fini. 

 finally {
    out.close();//this would resolve the issue
    }

Il peut arriver que vous souhaitiez vider le tampon sans fermer le fichier. Dans ces situations, vous pouvez utiliser la méthode flush.

1
Harita M

Puisque vous utilisez BufferedWriter, vous pouvez également vider le tampon si nécessaire:

out.flush()

Cela écrira le reste de la mémoire tampon dans le fichier réel. La méthode Close vide également le tampon et ferme le fichier.

out.close()

Il peut arriver que vous souhaitiez vider le tampon sans fermer le fichier. Dans ces situations, vous pouvez utiliser la méthode flush.

Vous pouvez également utiliser la méthode newline de BuffredWriter au lieu d’ajouter\n à la fin de la ligne. La méthode Newline utilise un séparateur de ligne spécifique au système pour que votre code fonctionne sur différentes plates-formes.

out.newLine()
0
niklasgerdt