Java: différence entre PrintStream et PrintWriter

125

Quelle est la différence entre PrintStreamet PrintWriter? Ils ont de nombreuses méthodes en commun grâce auxquelles je mélange souvent ces deux classes. De plus, je pense que nous pouvons les utiliser pour exactement les mêmes choses. Mais il doit y avoir une différence, sinon, il n'y aurait eu qu'une seule classe.

J'ai fouillé les archives, mais je n'ai pas trouvé cette question.

Martijn Courteaux
la source
1
+1 Bonne question, je mélange aussi ces deux classes, et le document API n'aide pas beaucoup non plus.
helpermethod
Une autre différence est le fonctionnement de l'autoflush. Pour un écrivain, la présence d'un caractère \ n dans la sortie déclenche flush (). Mais dans un flux d'octets (PrintStream), il n'y a que des octets. autoflush fonctionne alors comme décrit dans Javadoc, basé sur: "la propre notion de la plate-forme de séparateur de ligne plutôt que le caractère de nouvelle ligne".
min

Réponses:

129

Cela peut sembler désinvolte, mais PrintStreams'imprime sur un OutputStreamet PrintWriterimprime sur un fichier Writer. Ok, je doute que j'obtienne des points pour énoncer l'évidence. Mais il y a plus.

Alors, quelle est la différence entre un OutputStreamet un Writer? Les deux sont des flux, la principale différence étant que a OutputStreamest un flux d'octets tandis que a Writerest un flux de caractères.

Si un OutputStreamtraite des octets, qu'en est-il PrintStream.print(String)? Il convertit les caractères en octets en utilisant le codage de plate-forme par défaut. L'utilisation de l'encodage par défaut est généralement une mauvaise chose car cela peut entraîner des bogues lors du passage d'une plateforme à une autre, surtout si vous générez le fichier sur une plateforme et le consommez sur une autre.

Avec un Writer , vous spécifiez généralement le codage à utiliser, en évitant toute dépendance de plate-forme.

Pourquoi se donner la peine d'avoir un PrintStreamdans le JDK, puisque l'intention principale est d'écrire des caractères et non des octets? PrintStreamest antérieur à JDK 1.1 lorsque les flux de caractères Reader / Writer ont été introduits. J'imagine que Sun aurait été obsolète PrintStreamne serait- ce que pour le fait qu'il est si largement utilisé. (Après tout, vous ne voudriez pas que chaque appel à System.outgénère un avertissement d'API obsolète! De plus, changer le type de PrintStreamà PrintWritersur les flux de sortie standard aurait interrompu les applications existantes.)

mdma
la source
3
C'est ce que je pensais aussi - mais ce n'est pas vrai. Même PrintStream maintient un Writer sous le capot - si vous lui passez un OutputStream, il l'enveloppe.
Jon Skeet
3
@Jon - en interne, il y a un Writer, mais il écrit dans un OutputStream, donc l'effet net est qu'un PrintStream écrit dans un OutputStream - une conversion de caractères en octets se produit et utilise le codage de plate-forme par défaut. Il n'y a pas une telle exigence pour la conversion char-> octet dans un PrintWriter, vous pouvez rester avec des caractères jusqu'au bout.
mdma
"Le jeu de caractères par défaut est déterminé lors du démarrage de la machine virtuelle et dépend généralement des paramètres régionaux et du jeu de caractères du système d'exploitation sous-jacent.", Également Locale modifie le jeu de caractères par défaut sur certaines plates-formes.
Pindatjuh
7
Depuis Java 1.5, PrintStreamn'a pas été limité à l'utilisation de l'encodage par défaut de la plate-forme; il existe des constructeurs qui acceptent un nom de jeu de caractères. Ainsi, les distinctions entre PrintStreamet PrintWritersont que a PrintWriterne peut pas écrire d'octets bruts et les deux classes englobent différents types de destinations.
Ted Hopp
1
Cela vaut peut-être la peine de noter également une différence significative dans leur comportement, alors qu'ils partagent effectivement PrintStreamles print()méthodes d' une interface sont des fonctions pratiques qui appellent write(), en tant que telles, elles déclenchent l'autoflush si elles sont activées. PrintWriterd'autre part, ne sera pas autoflush après un appel à print(). J'ai fait la démonstration de Java débutants aujourd'hui et cela a surpris certains étudiants qui n'étaient pas familiers avec la nécessité de vider manuellement. Sinon, votre réponse est excellente.
Robadob
61

Avec le, PrintStreamvous êtes bloqué sur l'encodage par défaut de la plateforme.

PrintStream stream = new PrintStream(output);

Avec le PrintWritervous pouvez cependant passer un OutputStreamWriteravec un encodage spécifique.

PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));

L'avantage est que vous pouvez contrôler le codage des caractères dans lequel les caractères doivent être écrits de sorte qu'ils ne finissent pas par devenir des mojibake .

BalusC
la source
12
Depuis la 1.4, il y a un nouveau constructeur pour PrintStream qui prend l'encodagePrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol
19

Depuis JDK 1.4, il est possible de spécifier le codage des caractères pour un PrintStream. Ainsi, les différences entre PrintStream et PrintWriter concernent uniquement le comportement de vidage automatique et qu'un PrintStream ne peut pas encapsuler un Writer.

Renan Mozone
la source
3

Les écrivains comme PrintWriter sont destinés à la sortie de texte, les flux sont à la sortie binaire. Les rédacteurs gèrent les jeux de caractères pour vous. Les flux ne le font pas car il est supposé que vous ne voulez pas de ce type de conversion, ce qui gâcherait vos données binaires et que vous utiliseriez un écrivain si vous le faisiez.

sblundy
la source
1
Sauf PrintStream, car celui-ci prend un encodage donc il peut gérer un peu plus qu'un OutputStream standard.
Simon Groenewolt
Cela semble étrange que System.out, dont le seul objectif est d'imprimer des chaînes, soit en fait un PrintStream.
min
"Les écrivains gèrent les jeux de caractères pour vous" - seuls les écrivains qui s'occupent de la conversion des caractères en octets. Tous les écrivains ne le font pas.
Aivar
2

Vous pouvez écrire des octets bruts dans un Stream et non dans un Writer. Le javadoc PrintWriter répertorie les autres différences (surtout, être capable de définir un encodage sur un flux afin qu'il puisse interpréter les octets bruts, je dirais).

Simon Groenewolt
la source
Avec PrintStream, on peut également spécifier l'encodage
Aivar
1

depuis le noyau java par Horstmann

Les vétérans de Java pourraient se demander ce qui est arrivé à la classe PrintStream et à System.out. Dans Java 1.0, la classe PrintStream a simplement tronqué tous les caractères Unicode en caractères ASCII en supprimant l'octet supérieur. (À l'époque, Unicode était encore un encodage 16 bits.) De toute évidence, ce n'était pas une approche propre ou portable, et cela a été corrigé avec l'introduction de lecteurs et d'écrivains dans Java 1.1. Pour la compatibilité avec le code existant, System.in, System.out et System.err sont toujours des flux d'entrée / sortie, pas des lecteurs et des écrivains. Mais maintenant, la classe PrintStream convertit en interne les caractères Unicode en encodage hôte par défaut de la même manière que PrintWriter. Les objets de type PrintStream agissent exactement comme les rédacteurs d'impression lorsque vous utilisez les méthodes print et println,

Nichijou
la source
-3

Printwriter est une amélioration du flux d'impression.

Flux d'impression IE dans un but précis.

Spoo
la source