Question

J'ai toujours été un peu confondu avec la quantité de différentes implémentations IO en Java, et maintenant que je suis complètement coincé dans le développement de mon projet, je prenais mon temps de lire sur son côté de choses utiles.

J'ai réalisé qu'il n'y a pas de comparaison de débutant convivial (à part brève explication à API pour la classe Writer ) entre les différentes sous-classes de la classe Writer. Donc, je pensais que je virerais loin la question, quelles sont les différentes sous-classes bon?

Par exemple, j'utilise habituellement un FileWriter enveloppé d'un BufferedWriter pour mes sorties vers des fichiers, mais je l'ai toujours été irrité par le fait qu'il n'y a pas println() comme méthode, et on doit utiliser newLine() chaque seconde ligne (pour faire la lisible par l'homme de sortie). PrintWriterhas la méthode println() mais aucun constructeur qui supports mais ... annexant

Je vous en serais reconnaissant si vous pouviez me donner votre grain de sel de votre expérience, ou un guide de Nice / comment-vous aurais peut-être trébuché sur.

EDIT: Merci pour les réponses tout le monde, j'apprécie vraiment l'info passé ici. Il est un peu regrettable que toute chose append() a fini par être mis au point, il voulait simplement dire comme un exemple. Ma question se référait surtout à la nécessité et l'utilisation de toutes les différentes implémentations, ce qui suppose que j'a été mentionné un peu dans quelques réponses.

Il est difficile de choisir une réponse acceptée, car il y a trois réponses vraiment solides, chacun a contribué à ma compréhension du problème. Je suis vais devoir aller avec Anon, cette fois comme il a le moins de représentant. les points (je suppose qu'il est nouveau sur SO). Il est 15 réponses dont certaines sont vraiment bien formulées, et 0 questions posées. Bonne contribution je dirais, et qui mérite d'être encouragée.

Cela étant dit, ColinD et Jay ont également fourni des réponses très bons, et ont fait des idées intéressantes. Surtout commentaire de Jay sur Java enroulant automatiquement BufferedWriter convient de noter. Merci encore les gars, vraiment apprécié!

Était-ce utile?

La solution

Les classes java.io suivent généralement le modèle décorateur. Ainsi, alors que PrintWriter n'a pas le constructeur spécifique, vous voudrez peut-être, il a un constructeur qui prend une autre Writer, de sorte que vous pouvez faire quelque chose comme ce qui suit:

FileOutputStream fos = null;
try
{
    fos = new FileOutputStream("foo.txt");
    PrintWriter out = new PrintWriter(
                          new BufferedWriter(
                              new OutputStreamWriter(fos, "UTF-8")));
    // do what you want to do
    out.flush();
    out.close();
}
finally
{
    // quietly close the FileOutputStream (see Jakarta Commons IOUtils)
}

Comme une note d'utilisation générale, vous voulez toujours envelopper un écrivain de bas niveau (par exemple FileWriter ou OutputStreamWriter) dans un BufferedWriter, pour réduire au minimum les opérations d'entrées-sorties réelles. Cependant, cela signifie que vous devez explicitement flush et fermer la Writer externe, afin d'assurer que tout le contenu est écrit.

Et alors vous devez fermer le bas niveau Writer dans un bloc de finally, pour vous assurer que vous ne fuyez pas les ressources.

Modifier :

Regarder MForster La réponse de 'm'a fait prendre un autre regard sur l'API pour FileWriter. Et je me suis aperçu qu'il ne prend pas un ensemble explicite de caractère, ce qui est une très mauvaise chose. Donc, j'ai édité mon extrait de code à utiliser un FileOutputStream enveloppé par un OutputStreamWriter qui prend un ensemble explicite de caractères.

Autres conseils

FileWriter est généralement pas une classe acceptable à utiliser. Il ne vous permet pas de spécifier le Charset à utiliser pour l'écriture, ce qui signifie que vous êtes coincé avec ce que le jeu de caractères par défaut de la plate-forme que vous utilisez sur se trouve être. Inutile de dire que cela rend impossible d'utiliser systématiquement la même charset pour lire et écrire des fichiers texte et peut conduire à des données corrompues.

Plutôt que d'utiliser FileWriter, vous devriez être envelopper un FileOutputStream dans un OutputStreamWriter. OutputStreamWriter ne vous permet de spécifier un charset:

File file = ...
OutputStream fileOut = new FileOutputStream(file);
Writer writer = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));

Pour utiliser PrintWriter avec ce qui précède, juste envelopper le BufferedWriter dans un PrintWriter:

PrintWriter printWriter = new PrintWriter(writer);

pourrait aussi utiliser le constructeur de PrintWriter qui prend File et le nom d'un charset:

PrintWriter printWriter = new PrintWriter(file, "UTF-8");

Cela fonctionne très bien pour votre situation particulière, et ne fait exactement la même chose que le code ci-dessus, mais il est bon de savoir comment le construire en enveloppant les différentes parties.

Les autres types de Writer sont la plupart du temps pour des utilisations spécialisées:

  • StringWriter est juste un Writer qui peut être utilisé pour créer un String. CharArrayWriter est la même pour char[].
  • PipedWriter pour la tuyauterie à un PipedReader.

Modifier

Je remarque que vous avez dit sur une autre réponse au sujet de la verbosité de la création d'un écrivain de cette façon. Notez qu'il existe des bibliothèques telles que Goyave qui aident à réduire la verbosité des opérations communes. Prenons, par exemple, écrire un String à un fichier dans un jeu de caractères spécifique. Avec goyave, vous pouvez simplement écrire:

Files.write(text, file, Charsets.UTF_8);

Vous pouvez également créer un BufferedWriter comme ceci:

BufferedWriter writer = Files.newWriter(file, Charsets.UTF_8);

PrintWriter ne dispose pas d'un constructeur qui prend un paramètre « append », mais FileWriter fait. Et il me semble logique que c'est là où il appartient. PrintWriter ne sait pas si vous écrivez à un fichier, une prise, la console, une chaîne, etc. Que signifie pour « append » sur une prise à écrit?

Alors la bonne façon de faire ce que vous voulez est simplement:

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter(myfile, append)));

note intéressante: Si vous enveloppez un OutputStream dans un PrintWriter, Java insère automatiquement une BufferedWriter au milieu. Mais si vous enveloppez un écrivain dans un PrintWriter, il ne fonctionne pas. Donc, on ne gagne rien en disant:

PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(myfile))));

Il suffit de laisser tomber le BufferedWriter et le OutputStreamWriter, vous les obtenez gratuitement de toute façon. Je ne sais pas s'il y a une bonne raison de l'incompatibilité.

Il est vrai que vous ne pouvez pas spécifier un codage de caractères dans un FileWriter que des notes ColinD. Je ne sais pas ce qui le rend « inacceptable ». Je suis presque toujours parfaitement heureux d'accepter l'encodage par défaut. Peut-être que si vous utilisez une langue autre que l'anglais cette question.

La nécessité d'envelopper des écrivains ou OutputStreams en couches a été source de confusion pour moi quand je commencé à utiliser Java. Mais une fois que vous obtenez le coup de lui, il n'y a pas une grosse affaire. Il vous suffit de plier votre esprit dans le cadre d'écriture. Chaque écrivain a une fonction. Pensez-y comme je veux imprimer un fichier, donc je dois envelopper un FileWriter dans un PrintWriter. Ou, je veux convertir un flux de sortie à un écrivain, donc je besoin d'un OutputStreamWriter. Etc.

Ou peut-être que vous venez de vous habituer à ceux que vous utilisez tout le temps. Figure dehors une fois et rappelez-vous comment vous l'avez fait.

Vous pouvez créer un PrintWriter annexant comme ceci:

OutputStream os = new FileOutputStream("/tmp/out", true);
PrintWriter writer = new PrintWriter(os);

Edit:. poste de Anon est juste à la fois à l'aide d'un BufferedWriter entre et en spécifiant le codage

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top