Java: Perbedaan antara PrintStream dan PrintWriter

125

Apa perbedaan antara PrintStreamdan PrintWriter? Mereka memiliki banyak metode yang sama karena saya sering mencampur dua kelas ini. Selain itu, saya pikir kita bisa menggunakannya untuk hal yang persis sama. Tetapi harus ada perbedaan, jika tidak, hanya akan ada satu kelas.

Saya telah mencari arsip, tetapi tidak dapat menemukan pertanyaan ini.

Martijn Courteaux
sumber
1
+1 Pertanyaan bagus, saya juga mencampur dua kelas ini, dan dokumen API juga tidak banyak membantu.
helpermethod
Perbedaan lainnya adalah cara kerja autoflush. Bagi seorang penulis, kehadiran karakter \ n dalam output memicu flush (). Tetapi dalam aliran byte (PrintStream) hanya ada byte. autoflush kemudian berfungsi seperti yang dijelaskan di Javadoc, berdasarkan: "gagasan platform tentang pemisah baris, bukan karakter baris baru".
menit

Jawaban:

129

Ini mungkin terdengar kurang ajar, tetapi PrintStreammencetak ke OutputStream, dan PrintWritermencetak ke Writer. Oke, saya ragu saya akan mendapatkan poin untuk menyatakan yang sudah jelas. Tapi masih ada lagi.

Jadi, apa perbedaan antara an OutputStreamdan a Writer? Keduanya adalah aliran, dengan perbedaan utama menjadi OutputStreamaliran byte sedangkan a Writeradalah aliran karakter.

Jika OutputStreamberurusan dengan byte, bagaimana dengan PrintStream.print(String)? Itu mengubah karakter menjadi byte menggunakan pengkodean platform default. Menggunakan pengkodean default umumnya merupakan hal yang buruk karena dapat menyebabkan bug saat berpindah dari satu platform ke platform lain, terutama jika Anda membuat file di satu platform dan menggunakannya di platform lain.

Dengan Writer , Anda biasanya menentukan encoding yang akan digunakan, menghindari dependensi platform apa pun.

Mengapa repot-repot memiliki PrintStreamdi JDK, karena maksud utamanya adalah untuk menulis karakter, dan bukan byte? PrintStreammendahului JDK 1.1 ketika aliran karakter Pembaca / Penulis diperkenalkan. Saya membayangkan Sun akan usang PrintStreamjika hanya karena fakta itu digunakan secara luas. (Lagi pula, Anda tidak ingin setiap panggilan System.outmenghasilkan peringatan API yang tidak berlaku lagi! Selain itu, mengubah jenis dari PrintStreammenjadi PrintWriterpada aliran keluaran standar akan merusak aplikasi yang ada.)

mdma
sumber
3
Ini juga yang saya pikirkan - tapi itu tidak benar. Bahkan PrintStream mempertahankan Writer di bawah tenda - jika Anda memberikannya OutputStream, itu akan membungkusnya.
Jon Skeet
3
@Jon - secara internal, ada Writer, tetapi menulis ke OutputStream, sehingga efek bersihnya adalah PrintStream menulis ke OutputStream - konversi char ke byte terjadi, dan menggunakan pengkodean platform default. Tidak ada persyaratan untuk konversi karakter-> byte di PrintWriter, Anda dapat tetap menggunakan karakter sepanjang jalan.
mdma
"Charset default ditentukan selama startup mesin virtual dan biasanya bergantung pada lokal dan charset dari sistem operasi yang mendasarinya.", Lokal juga mengubah charset default pada beberapa platform.
Pindatjuh
7
Sejak Java 1.5, PrintStreamtidak terbatas pada penggunaan pengkodean default platform; ada konstruktor yang menerima nama charset. Jadi, perbedaan antara PrintStreamdan PrintWriterare bahwa a PrintWritertidak dapat menulis byte mentah dan dua kelas membungkus berbagai jenis tujuan.
Ted Hopp
1
Mungkin layak Anda juga mencatat perbedaan yang signifikan dalam perilaku mereka, sementara mereka secara efektif berbagi antarmuka PrintStream's print()metode adalah fungsi kenyamanan yang panggilan write(), dengan demikian mereka memicu autoflush jika diaktifkan. PrintWriterdi sisi lain tidak akan autoflush setelah panggilan ke print(). Saya telah mendemonstrasikan beberapa pemula Java hari ini dan ini menarik perhatian beberapa siswa yang tidak terbiasa dengan kebutuhan untuk menyiram secara manual. Jika tidak, jawaban Anda bagus.
Robadob
61

Dengan PrintStreamAnda terjebak pada pengkodean default platform.

PrintStream stream = new PrintStream(output);

PrintWriterNamun dengan itu Anda dapat meneruskan OutputStreamWriterdengan pengkodean tertentu.

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

Keuntungannya adalah, Anda dapat mengontrol karakter yang mengkodekan karakter yang harus ditulis sedemikian rupa sehingga pada akhirnya tidak akan berakhir sebagai mojibake .

BalusC
sumber
12
Sejak 1.4, ada konstruktor baru untuk PrintStream yang mengambil pengkodeanPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol
19

Sejak JDK 1.4 dimungkinkan untuk menentukan pengkodean karakter untuk PrintStream. Jadi, perbedaan antara PrintStream dan PrintWriter hanya tentang perilaku pembilasan otomatis dan bahwa PrintStream tidak dapat membungkus Writer.

Renan Mozone
sumber
3

Penulis seperti PrintWriter untuk keluaran teks, aliran untuk keluaran biner. Penulis menangani item set karakter untuk Anda. Aliran tidak melakukannya karena diasumsikan bahwa Anda tidak menginginkan konversi semacam itu, yang akan mengacaukan data biner Anda, dan akan menggunakan penulis jika Anda melakukannya.

sblundy.dll
sumber
1
Kecuali PrintStream, karena yang satu itu membutuhkan encoding sehingga dapat menangani sedikit lebih dari OutputStream standar.
Simon Groenewolt
Kedengarannya aneh bahwa System.out, yang tujuan utamanya adalah mencetak string, sebenarnya adalah PrintStream.
menit
"Para penulis menangani hal-hal kumpulan karakter untuk Anda" - hanya Penulis yang berurusan dengan pengubahan karakter menjadi byte. Tidak semua Penulis melakukannya.
Aivar
2

Anda dapat menulis byte mentah ke Stream dan bukan ke Penulis. The PrintWriter daftar javadoc perbedaan lainnya (yang paling penting, mampu mengatur pengkodean pada sungai sehingga dapat menafsirkan byte baku aku akan mengatakan).

Simon Groenewolt
sumber
Dengan PrintStream seseorang dapat menentukan pengkodean juga
Aivar
1

dari inti java oleh Horstmann

Veteran Java mungkin bertanya-tanya apa yang terjadi dengan kelas PrintStream dan System.out. Di Java 1.0, kelas PrintStream hanya memotong semua karakter Unicode menjadi karakter ASCII dengan menghilangkan byte atas. (Pada saat itu, Unicode masih merupakan pengkodean 16-bit.) Jelas, itu bukan pendekatan yang bersih atau portabel, dan telah diperbaiki dengan pengenalan pembaca dan penulis di Java 1.1. Untuk kompatibilitas dengan kode yang ada, System.in, System.out, dan System.err masih merupakan aliran input / output, bukan pembaca dan penulis. Tapi sekarang kelas PrintStream secara internal mengubah karakter Unicode menjadi pengkodean host default dengan cara yang sama seperti yang dilakukan PrintWriter. Objek berjenis PrintStream bertindak persis seperti penulis cetak saat Anda menggunakan metode cetak dan println,

nichijou
sumber
-3

Printwriter adalah peningkatan dari printstream.

Arus cetak IE untuk tujuan tertentu.

Spoo
sumber