Java: ความแตกต่างระหว่าง PrintStream และ PrintWriter


125

อะไรคือความแตกต่างระหว่างPrintStreamและPrintWriter? พวกเขามีหลายวิธีที่เหมือนกันเนื่องจากฉันมักจะผสมสองคลาสนี้เข้าด้วยกัน นอกจากนี้ฉันคิดว่าเราสามารถใช้มันเพื่อสิ่งเดียวกัน แต่จะต้องมีความแตกต่างมิฉะนั้นจะมีเพียงคลาสเดียว

ฉันได้ค้นหาเอกสารสำคัญแล้ว แต่ไม่พบคำถามนี้


1
+1 คำถามที่ดีฉันยังผสมผสานสองคลาสนี้เข้าด้วยกันและเอกสาร API ก็ไม่ได้ช่วยอะไรมากเช่นกัน
วิธีช่วยเหลือ

ความแตกต่างอีกประการหนึ่งคือวิธีการทำงานของฟลัชอัตโนมัติ สำหรับผู้เขียนการมีอยู่ของอักขระ \ n ในเอาต์พุตจะทริกเกอร์ flush () แต่ในไบต์สตรีม (PrintStream) มีไบต์เท่านั้น จากนั้น autoflush จะทำงานตามที่อธิบายไว้ใน Javadoc โดยอ้างอิงจาก: "แนวคิดของตัวคั่นบรรทัดของแพลตฟอร์มแทนที่จะเป็นอักขระขึ้นบรรทัดใหม่"
นาที

คำตอบ:


129

สิ่งนี้อาจฟังดูดี แต่PrintStreamพิมพ์ไปที่OutputStreamและPrintWriterพิมพ์ไปยังไฟล์Writer. โอเคฉันสงสัยว่าฉันจะได้รับคะแนนสำหรับการระบุความชัดเจน แต่มีมากกว่านั้น

ดังนั้นอะไรคือความแตกต่างระหว่าง an OutputStreamและ a Writer? ทั้งสองเป็นสตรีมโดยความแตกต่างหลักOutputStreamคือ a คือสตรีมไบต์ในขณะที่ a Writerเป็นสตรีมของอักขระ

ถ้าOutputStreamข้อตกลงกับไบต์PrintStream.print(String)ล่ะ? จะแปลงอักขระเป็นไบต์โดยใช้การเข้ารหัสแพลตฟอร์มเริ่มต้น โดยทั่วไปการใช้การเข้ารหัสเริ่มต้นเป็นสิ่งที่ไม่ดีเนื่องจากอาจทำให้เกิดข้อบกพร่องเมื่อย้ายจากแพลตฟอร์มหนึ่งไปยังอีกแพลตฟอร์มหนึ่งโดยเฉพาะอย่างยิ่งหากคุณกำลังสร้างไฟล์บนแพลตฟอร์มหนึ่งและใช้งานบนอีกแพลตฟอร์มหนึ่ง

ด้วยWriterคุณมักจะระบุการเข้ารหัสเพื่อใช้หลีกเลี่ยงการพึ่งพาแพลตฟอร์มใด ๆ

ทำไมต้องกังวลPrintStreamใน JDK เนื่องจากเจตนาหลักคือการเขียนอักขระไม่ใช่ไบต์ PrintStreamเกิดก่อน JDK 1.1 เมื่อมีการนำสตรีมอักขระ Reader / Writer ฉันคิดว่าซันคงจะเลิกใช้PrintStreamถ้าเพียงเพราะมันถูกใช้กันอย่างแพร่หลาย ( System.outท้ายที่สุดคุณคงไม่ต้องการให้การเรียกแต่ละครั้งสร้างคำเตือน API ที่เลิกใช้แล้ว! นอกจากนี้การเปลี่ยนประเภทจากPrintStreamเป็นPrintWriterบนสตรีมเอาต์พุตมาตรฐานอาจทำให้แอปพลิเคชันที่มีอยู่เสียหาย)


3
นี่คือสิ่งที่ฉันคิดเช่นกัน - แต่มันไม่เป็นความจริง แม้แต่ PrintStream ยังดูแล Writer ภายใต้ประทุน - ถ้าคุณส่ง OutputStream มันก็จะห่อมัน
Jon Skeet

3
@ จอน - ภายในมี Writer แต่เขียนไปยัง OutputStream ดังนั้นเอฟเฟกต์สุทธิคือ PrintStream เขียนไปยัง OutputStream - การแปลงถ่านเป็นไบต์จะเกิดขึ้นและใช้การเข้ารหัสแพลตฟอร์มเริ่มต้น ไม่มีข้อกำหนดดังกล่าวสำหรับการแปลง char-> byte ใน PrintWriter คุณสามารถใช้อักขระได้ตลอดทาง
mdma

"ชุดอักขระเริ่มต้นจะถูกกำหนดระหว่างการเริ่มต้นเครื่องเสมือนและโดยทั่วไปจะขึ้นอยู่กับสถานที่และชุดอักขระของระบบปฏิบัติการที่ใช้งานอยู่" นอกจากนี้ Locale ยังเปลี่ยนชุดอักขระเริ่มต้นในบางแพลตฟอร์ม
Pindatjuh

7
ตั้งแต่ Java 1.5 PrintStreamไม่ได้ จำกัด เฉพาะการใช้การเข้ารหัสเริ่มต้นของแพลตฟอร์ม มีตัวสร้างที่ยอมรับชื่อชุดอักขระ ดังนั้นความแตกต่างระหว่างPrintStreamและPrintWriterคือการที่ a PrintWriterไม่สามารถเขียนไบต์ดิบและทั้งสองคลาสจะรวมจุดหมายปลายทางประเภทต่างๆ
Ted Hopp

1
มันอาจจะมีมูลค่าคุณก็สังเกตความแตกต่างอย่างมีนัยสำคัญในการทำงานของพวกเขาขณะที่พวกเขาได้อย่างมีประสิทธิภาพแบ่งปันอินเตอร์เฟซPrintStream's print()วิธีการฟังก์ชั่นอำนวยความสะดวกที่โทรwrite()เป็นเช่นที่พวกเขาเรียก autoflush ถ้าเปิดใช้งาน PrintWriterบนมืออื่น ๆ จะไม่ autoflush print()หลังจากที่โทรไป วันนี้ฉันได้สาธิต Java สำหรับผู้เริ่มต้นบางคนและสิ่งนี้ทำให้นักเรียนบางคนไม่คุ้นเคยกับความจำเป็นในการล้างด้วยตนเอง มิฉะนั้นคำตอบของคุณดีมาก
Robadob

61

เมื่อPrintStreamคุณติดอยู่กับการเข้ารหัสเริ่มต้นของแพลตฟอร์ม

PrintStream stream = new PrintStream(output);

กับPrintWriterคุณ แต่สามารถผ่านการOutputStreamWriterกับการเข้ารหัสที่เฉพาะเจาะจง

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

ข้อดีคือคุณสามารถควบคุมอักขระที่เข้ารหัสอักขระที่ควรเขียนในลักษณะที่จะไม่ลงเอยด้วยโมจิบาเกะในที่สุด


12
ตั้งแต่ 1.4 มีตัวสร้างใหม่สำหรับ PrintStream ซึ่งใช้การเข้ารหัสPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol

19

เนื่องจาก JDK 1.4 เป็นไปได้ที่จะระบุการเข้ารหัสอักขระสำหรับ PrintStream ดังนั้นความแตกต่างระหว่าง PrintStream และ PrintWriter จึงเป็นเพียงเกี่ยวกับพฤติกรรมการล้างอัตโนมัติและ PrintStream ไม่สามารถรวม Writer ได้


3

นักเขียนเช่น PrintWriter ใช้สำหรับเอาต์พุตข้อความสตรีมสำหรับเอาต์พุตไบนารี นักเขียนจัดการเรื่องชุดตัวละครให้คุณ สตรีมไม่ได้เป็นเพราะสมมติว่าคุณไม่ต้องการการแปลงแบบนั้นซึ่งจะทำให้ข้อมูลไบนารีของคุณยุ่งเหยิงและจะใช้ตัวเขียนหากคุณทำ


1
ยกเว้น PrintStream เนื่องจากใช้การเข้ารหัสดังนั้นจึงสามารถจัดการกับ OutputStream มาตรฐานได้มากกว่าเล็กน้อย
Simon Groenewolt

ฟังดูแปลกที่ System.out ซึ่งมีเป้าหมายเดียวคือการพิมพ์สตริงจริงๆแล้วคือ PrintStream
นาทีที่

"นักเขียนจัดการเรื่องชุดอักขระให้คุณ" - เฉพาะนักเขียนที่จัดการกับการแปลงอักขระเป็นไบต์ นักเขียนทุกคนไม่ได้ทำ
Aivar

2

คุณสามารถเขียนไบต์ดิบไปยังสตรีมไม่ใช่เขียนถึง Writer PrintWriter Javadoc รายการแตกต่างอื่น ๆ (ที่สำคัญที่สุดคือความสามารถในการตั้งค่าการเข้ารหัสบนกระแสเพื่อที่จะสามารถตีความไบต์ดิบผมว่า)


ด้วย PrintStream เราสามารถระบุการเข้ารหัสได้เช่นกัน
Aivar

1

จากcore javaโดย Horstmann

ทหารผ่านศึก Java อาจสงสัยว่าเกิดอะไรขึ้นกับคลาส PrintStream และ System.out ใน Java 1.0 คลาส PrintStream จะตัดทอนอักขระ Unicode ทั้งหมดให้เป็นอักขระ ASCII โดยทิ้งไบต์บนสุด (ในขณะนั้น Unicode ยังคงเป็นการเข้ารหัสแบบ 16 บิต) เห็นได้ชัดว่านั่นไม่ใช่วิธีการที่สะอาดหรือพกพาได้และได้รับการแก้ไขด้วยการแนะนำผู้อ่านและนักเขียนใน Java 1.1 สำหรับความเข้ากันได้กับรหัสที่มีอยู่ System.in, System.out และ System.err ยังคงเป็นสตรีมอินพุต / เอาต์พุตไม่ใช่ผู้อ่านและผู้เขียน แต่ตอนนี้คลาส PrintStream แปลงอักขระ Unicode ภายในเป็นการเข้ารหัสโฮสต์เริ่มต้นในลักษณะเดียวกับที่ PrintWriter ทำ ออบเจ็กต์ประเภท PrintStream ทำหน้าที่เหมือนกับตัวเขียนงานพิมพ์เมื่อคุณใช้วิธีการพิมพ์และวิธีการพิมพ์


-3

Printwriter เป็นการเพิ่มประสิทธิภาพของ printstream

IE printstream สำหรับวัตถุประสงค์เฉพาะ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.