Java: differenza tra PrintStream e PrintWriter


125

Qual'è la differenza tra PrintStreame PrintWriter? Hanno molti metodi in comune grazie ai quali spesso mischio queste due classi. Inoltre, penso che possiamo usarli esattamente per le stesse cose. Ma ci deve essere una differenza, altrimenti ci sarebbe stata solo una classe.

Ho cercato negli archivi, ma non sono riuscito a trovare questa domanda.


1
+1 Bella domanda, confondo anche queste due classi e neanche il documento API è di grande aiuto.
helpermethod

Un'altra differenza è come funziona l'autoflush. Per uno scrittore, la presenza di un carattere \ n nell'output attiva flush (). Ma in un flusso di byte (PrintStream) ci sono solo byte. autoflush quindi funziona come descritto in Javadoc, sulla base di: "la nozione di separatore di riga della piattaforma piuttosto che il carattere di nuova riga".
min.

Risposte:


129

Potrebbe sembrare impertinente, ma PrintStreamstampa su an OutputStreame PrintWriterstampa su a Writer. Ok, dubito che otterrò punti per aver affermato l'ovvio. Ma c'è di più.

Allora, qual è la differenza tra an OutputStreame a Writer? Entrambi sono flussi, con la differenza principale che OutputStreamè un flusso di byte mentre a Writerè un flusso di caratteri.

Se un si OutputStreamoccupa di byte, che dire PrintStream.print(String)? Converte i caratteri in byte utilizzando la codifica della piattaforma predefinita. L'utilizzo della codifica predefinita è generalmente una cosa negativa poiché può portare a bug quando ci si sposta da una piattaforma all'altra, soprattutto se si genera il file su una piattaforma e lo si consuma su un'altra.

Con a Writer, in genere si specifica la codifica da utilizzare, evitando qualsiasi dipendenza dalla piattaforma.

Perché preoccuparsi di avere un PrintStreamnel JDK, dato che l'intento principale è scrivere caratteri e non byte? PrintStreamprecede JDK 1.1 quando sono stati introdotti i flussi di caratteri Reader / Writer. Immagino che Sun avrebbe disapprovato PrintStreamse solo per il fatto che è così ampiamente utilizzato. (Dopo tutto, non vorresti che ogni chiamata System.outgenerasse un avviso API deprecato! Inoltre, la modifica del tipo da PrintStreama PrintWritersui flussi di output standard avrebbe interrotto le applicazioni esistenti.)


3
Questo è quello che pensavo anch'io, ma non è vero. Anche PrintStream mantiene un writer sotto il cofano: se gli passi un OutputStream, lo avvolge.
Jon Skeet

3
@Jon - internamente c'è un writer, ma scrive su un OutputStream, quindi l'effetto finale è che un PrintStream scrive su un OutputStream - avviene la conversione da caratteri a byte e utilizza la codifica della piattaforma predefinita. Non esiste tale requisito per la conversione di caratteri> byte in un PrintWriter, puoi rimanere con i caratteri fino in fondo.
mdma

"Il set di caratteri predefinito viene determinato durante l'avvio della macchina virtuale e in genere dipende dalla lingua e dal set di caratteri del sistema operativo sottostante.", Inoltre Locale cambia il set di caratteri predefinito su alcune piattaforme.
Pindatjuh

7
A partire da Java 1.5, PrintStreamnon si è limitato a utilizzare la codifica predefinita della piattaforma; ci sono costruttori che accettano un nome di charset. Quindi la distinzione tra PrintStreame PrintWriterè che a PrintWriternon può scrivere byte grezzi e le due classi racchiudono diversi tipi di destinazioni.
Ted Hopp

1
Potrebbe valere la pena notare anche una differenza significativa nel loro comportamento, mentre condividono effettivamente PrintStreami print()metodi di un'interfaccia che sono funzioni utili che chiamano write(), in quanto tali attivano l'autoflush se abilitato. PrintWriterd'altra parte non si autoflush dopo una chiamata a print(). Oggi ho dimostrato alcuni principianti di Java e questo ha catturato alcuni studenti che non avevano familiarità con la necessità di scaricare manualmente. Altrimenti la tua risposta è ottima.
Robadob

61

Con il PrintStreamsei bloccato alla codifica predefinita della piattaforma.

PrintStream stream = new PrintStream(output);

Con il PrintWritersi può comunque passare un OutputStreamWritercon una codifica specifica.

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

Il vantaggio è, beh, che puoi controllare il carattere che codifica i caratteri dovrebbero essere scritti in modo tale che alla fine non finiscano come mojibake .


12
Dalla 1.4, c'è un nuovo costruttore per PrintStream che prende la codificaPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol

19

A partire da JDK 1.4 è possibile specificare la codifica dei caratteri per un PrintStream. Pertanto, le differenze tra PrintStream e PrintWriter riguardano solo il comportamento dello scaricamento automatico e che un PrintStream non può eseguire il wrapping di un writer.


3

Writer come PrintWriter sono per l'output di testo, i flussi sono per l'output binario. Gli scrittori gestiscono le cose del set di caratteri per te. Gli stream non lo fanno perché si presume che tu non voglia quel tipo di conversione, che rovinerebbe i tuoi dati binari e, se lo facessi, utilizzerebbe un writer.


1
Tranne PrintStream, perché quello prende una codifica in modo da poter gestire un po 'più di un OutputStream standard.
Simon Groenewolt

Sembra strano che System.out, il cui unico obiettivo è stampare le stringhe, sia in realtà un PrintStream.
min.

"Gli scrittori gestiscono le cose dei set di caratteri per te" - solo gli scrittori che si occupano della conversione dei caratteri in byte. Non tutti gli scrittori lo fanno.
Aivar

2

È possibile scrivere byte non elaborati in un flusso e non in un writer. Il javadoc di PrintWriter elenca le altre differenze (cosa più importante, essere in grado di impostare una codifica su un flusso in modo che possa interpretare i byte grezzi che direi).


Con PrintStream si può anche specificare la codifica
Aivar

1

dal core java di Horstmann

I veterani di Java potrebbero chiedersi cosa sia successo alla classe PrintStream e a System.out. In Java 1.0, la classe PrintStream ha semplicemente troncato tutti i caratteri Unicode in caratteri ASCII rilasciando il byte superiore. (A quel tempo, Unicode era ancora una codifica a 16 bit.) Chiaramente, questo non era un approccio pulito o portabile, ed è stato risolto con l'introduzione di lettori e scrittori in Java 1.1. Per compatibilità con il codice esistente, System.in, System.out e System.err sono ancora flussi di input / output, non lettori e writer. Ma ora la classe PrintStream converte internamente i caratteri Unicode nella codifica host predefinita nello stesso modo in cui fa PrintWriter. Gli oggetti di tipo PrintStream agiscono esattamente come i writer di stampa quando si utilizzano i metodi print e println,


-3

Printwriter è un miglioramento di printstream.

IE printstream per uno scopo specifico.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.