Java: Diferença entre PrintStream e PrintWriter

125

Qual é a diferença entre PrintStreame PrintWriter? Eles têm muitos métodos em comum, devido aos quais eu costumo misturar essas duas classes. Além disso, acho que podemos usá-los exatamente para as mesmas coisas. Mas tem que haver uma diferença, caso contrário, haveria apenas uma classe.

Pesquisei nos arquivos, mas não consegui encontrar esta pergunta.

Martijn Courteaux
fonte
1
+1 Boa pergunta, eu também misturo essas duas classes, e o documento da API também não ajuda muito.
Helpermethod
Outra diferença é como o autoflush funciona. Para um escritor, a presença de um caractere \ n na saída aciona flush (). Mas em um fluxo de bytes (PrintStream), existem apenas bytes. autoflush funciona como descrito em Javadoc, com base em: "própria noção de separador de linha da plataforma, em vez do caractere de nova linha".
mins

Respostas:

129

Isso pode parecer irreverente, mas PrintStreamimprime em um OutputStreame PrintWriterimprime em um Writer. Ok, duvido que receba algum argumento por afirmar o óbvio. Mas tem mais.

Então, qual é a diferença entre an OutputStreame a Writer? Ambos são fluxos, sendo a principal diferença a OutputStreamum fluxo de bytes, enquanto a Writeré um fluxo de caracteres.

Se um OutputStreamlida com bytes, o que dizer PrintStream.print(String)? Ele converte caracteres em bytes usando a codificação da plataforma padrão. Usar a codificação padrão geralmente é uma coisa ruim, pois pode levar a erros ao passar de uma plataforma para outra, especialmente se você estiver gerando o arquivo em uma plataforma e consumindo-o em outra.

Com a Writer, você normalmente especifica a codificação a ser usada, evitando dependências da plataforma.

Por que se preocupar em ter um PrintStreamno JDK, já que a intenção principal é escrever caracteres, e não bytes? PrintStreamé anterior ao JDK 1.1 quando os fluxos de caracteres do Reader / Writer foram introduzidos. Eu imagino que a Sun teria se tornado obsoleta PrintStreamse fosse tão amplamente usada. (Afinal, você não deseja que cada chamada System.outgere um aviso de API descontinuado! Além disso, alterar o tipo de PrintStreampara PrintWriternos fluxos de saída padrão teria quebrado os aplicativos existentes.)

mdma
fonte
3
Foi o que pensei também - mas não é verdade. Até o PrintStream mantém um gravador sob o capô - se você passar um OutputStream, ele o envolverá.
Jon Skeet
3
@ Jon - internamente, existe um Writer, mas ele grava em um OutputStream, portanto o efeito líquido é que um PrintStream grava em um OutputStream - a conversão de char para byte acontece e usa a codificação da plataforma padrão. Não existe esse requisito para a conversão de caracteres em um PrintWriter; você pode ficar com os caracteres o tempo todo.
Mdma
"O conjunto de caracteres padrão é determinado durante a inicialização da máquina virtual e normalmente depende do código de idioma e conjunto de caracteres do sistema operacional subjacente.", Também Locale altera o conjunto de caracteres padrão em algumas plataformas.
Pindatjuh
7
Desde o Java 1.5, PrintStreamnão se limita ao uso da codificação padrão da plataforma; existem construtores que aceitam um nome de conjunto de caracteres. Assim, as distinções entre PrintStreame PrintWritersão que a PrintWriternão pode escrever bytes brutos e as duas classes agrupam tipos diferentes de destinos.
Ted Hopp
1
Também pode valer a pena notar uma diferença significativa no comportamento deles, enquanto eles compartilham efetivamente os métodos de uma interface PrintStream. print()São funções de conveniência que chamam write(); portanto, elas acionam o autoflush se ativado. PrintWriterpor outro lado, não será liberado automaticamente após uma chamada para print(). Eu tenho demonstrado alguns iniciantes em Java hoje e isso chamou a atenção de alguns estudantes que não estavam familiarizados com a necessidade de liberar manualmente. Caso contrário, sua resposta é ótima.
Robadob
61

Com o que PrintStreamvocê está preso à codificação padrão da plataforma.

PrintStream stream = new PrintStream(output);

Com o PrintWritervocê pode, no entanto, passar um OutputStreamWritercom uma codificação específica.

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

A vantagem é que você pode controlar o código que os caracteres devem ser escritos, para que não acabem como mojibake .

BalusC
fonte
12
Desde 1.4, há um novo construtor para PrintStream que leva a codificaçãoPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol
19

Desde o JDK 1.4, é possível especificar a codificação de caracteres para um PrintStream. Portanto, as diferenças entre PrintStream e PrintWriter são apenas sobre o comportamento de liberação automática e que um PrintStream não pode quebrar um Writer.

Renan Mozone
fonte
3

Escritores como PrintWriter são para saída de texto, fluxos são para saída binária. Os escritores lidam com coisas do conjunto de caracteres para você. Os fluxos não o fazem porque se supõe que você não deseja esse tipo de conversão, o que prejudicaria seus dados binários e, se você preferir, usaria um gravador.

esplêndido
fonte
1
Exceto PrintStream, porque esse leva uma codificação para que possa lidar com um pouco mais do que um OutputStream padrão.
Simon Groenewolt
Parece estranho que o System.out, cujo único objetivo seja imprimir strings, seja realmente um PrintStream.
minutos
"Os gravadores manipulam coisas do conjunto de caracteres para você" - apenas os gravadores que lidam com a conversão de caracteres em bytes. Nem todos os escritores fazem.
Aivar
2

Você pode gravar bytes não processados ​​em um fluxo e não em um gravador. O javadoc PrintWriter lista as outras diferenças (o mais importante é poder definir uma codificação em um fluxo para que ele possa interpretar os bytes brutos que eu diria).

Simon Groenewolt
fonte
Com PrintStream Pode-se especificar codificação bem
Aivar
1

do núcleo java por Horstmann

Os veteranos de Java podem se perguntar o que aconteceu com a classe PrintStream e com o System.out. No Java 1.0, a classe PrintStream simplesmente truncou todos os caracteres Unicode para caracteres ASCII, descartando o byte superior. (Na época, o Unicode ainda era uma codificação de 16 bits.) Claramente, essa não era uma abordagem limpa ou portátil, e foi corrigida com a introdução de leitores e gravadores no Java 1.1. Para compatibilidade com o código existente, System.in, System.out e System.err ainda são fluxos de entrada / saída, não leitores e gravadores. Mas agora a classe PrintStream converte internamente caracteres Unicode na codificação de host padrão da mesma maneira que o PrintWriter. Objetos do tipo PrintStream agem exatamente como gravadores de impressão quando você usa os métodos print e println,

nichijou
fonte
-3

O Printwriter é um aprimoramento do fluxo de impressão.

IE imprime o fluxo para uma finalidade específica.

Spoo
fonte