Java: Sự khác biệt giữa PrintStream và PrintWriter


125

Sự khác biệt giữa PrintStreamvà là PrintWritergì? Chúng có nhiều phương thức chung do tôi thường trộn hai lớp này lên. Hơn nữa, tôi nghĩ rằng chúng ta có thể sử dụng chúng cho chính xác những điều tương tự. Nhưng phải có một sự khác biệt, nếu không, sẽ chỉ có một lớp.

Tôi đã tìm kiếm tài liệu lưu trữ, nhưng không thể tìm thấy câu hỏi này.


1
+1 Câu hỏi hay, tôi cũng trộn lẫn hai lớp này và tài liệu API cũng không giúp được gì nhiều.
helpermethod

Một sự khác biệt nữa là cách autoflush hoạt động. Đối với người viết, sự hiện diện của ký tự \ n trong đầu ra kích hoạt flush (). Nhưng trong một luồng byte (PrintStream) chỉ có byte. autoflush sau đó hoạt động như được mô tả trong Javadoc, dựa trên: "khái niệm riêng của nền tảng phân tách dòng hơn là ký tự dòng mới".
phút

Câu trả lời:


129

Điều này có thể nghe có vẻ thiếu sót, nhưng PrintStreamin ra OutputStreamPrintWriterin thành a Writer. Ok, tôi nghi ngờ tôi sẽ nhận được bất kỳ điểm nào cho thấy rõ ràng. Nhưng còn nhiều hơn thế.

Vậy, sự khác biệt giữa an OutputStreamvà a là Writergì? Cả hai đều là luồng, với sự khác biệt chính là a OutputStreamlà luồng byte trong khi a Writerlà luồng ký tự.

Nếu một OutputStreamgiao dịch với byte, thì PrintStream.print(String)sao? Nó chuyển đổi ký tự thành byte bằng cách sử dụng mã hóa nền tảng mặc định. Sử dụng mã hóa mặc định nói chung là một điều tồi tệ vì nó có thể dẫn đến lỗi khi chuyển từ nền tảng này sang nền tảng khác, đặc biệt nếu bạn đang tạo tệp trên một nền tảng và tiêu thụ nó trên nền tảng khác.

Với a Writer, bạn thường chỉ định mã hóa để sử dụng, tránh mọi phụ thuộc nền tảng.

Tại sao phải có một PrintStreamJDK, vì mục đích chính là viết các ký tự chứ không phải byte? PrintStreamcó trước JDK 1.1 khi các luồng ký tự Reader / Writer được giới thiệu. Tôi tưởng tượng Sun sẽ không dùng nữa PrintStreamnếu chỉ vì nó được sử dụng rộng rãi như vậy. (Rốt cuộc, bạn sẽ không muốn mỗi cuộc gọi System.outtạo cảnh báo API không dùng nữa! Ngoài ra, việc thay đổi loại từ PrintStreamsang PrintWriterluồng đầu ra tiêu chuẩn sẽ phá vỡ các ứng dụng hiện có.)


3
Đây là những gì tôi nghĩ là tốt - nhưng nó không đúng. Ngay cả PrintStream vẫn duy trì một Nhà văn dưới mui xe - nếu bạn vượt qua nó là một OutputStream, nó sẽ bọc nó.
Jon Skeet

3
@Jon - bên trong, có một Trình ghi, nhưng nó ghi vào OutputStream, do đó, hiệu ứng ròng là PrintStream ghi vào OutputStream - chuyển đổi từ char sang byte xảy ra và sử dụng mã hóa nền tảng mặc định. Không có yêu cầu như vậy đối với chuyển đổi char-> byte trong PrintWriter, bạn có thể giữ nguyên các ký tự.
mdma

"Bộ ký tự mặc định được xác định trong quá trình khởi động máy ảo và thường phụ thuộc vào ngôn ngữ và bộ ký tự của hệ điều hành cơ bản.", Locale cũng thay đổi bộ ký tự mặc định trên một số nền tảng.
Pindatjuh

7
Kể từ Java 1.5, PrintStreamđã không bị giới hạn trong việc sử dụng mã hóa mặc định của nền tảng; có những nhà xây dựng chấp nhận một tên bộ ký tự. Do đó, sự khác biệt giữa PrintStreamPrintWriterPrintWriterkhông thể ghi các byte thô và hai lớp bao bọc các loại đích khác nhau.
Ted Hopp

1
Có thể bạn cũng nên chú ý đến một sự khác biệt đáng kể trong hành vi của họ, trong khi họ chia sẻ một cách hiệu quả PrintStreamcác print()phương thức của giao diện là các chức năng tiện lợi gọi write(), vì vậy chúng kích hoạt tự động điền nếu được bật. PrintWritermặt khác sẽ không tự động điền sau khi gọi đến print(). Tôi đã trình diễn một số người mới bắt đầu Java ngày hôm nay và điều này đã thu hút một số sinh viên không quen với nhu cầu tuôn ra thủ công. Nếu không, câu trả lời của bạn là tuyệt vời.
Robadob

61

Với việc PrintStreambạn bị mắc kẹt với mã hóa mặc định của nền tảng.

PrintStream stream = new PrintStream(output);

PrintWriterTuy nhiên, với bạn có thể vượt qua OutputStreamWritervới một mã hóa cụ thể.

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

Ưu điểm là, bạn có thể điều khiển ký tự mã hóa các ký tự nên được viết sao cho cuối cùng chúng sẽ không trở thành mojibake .


12
Kể từ ngày 1.4, có một hàm tạo mới cho PrintStream, mã hóaPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol

19

Vì JDK 1.4, có thể chỉ định mã hóa ký tự cho PrintStream. Do đó, sự khác biệt giữa PrintStream và PrintWriter chỉ là về hành vi tự động xả và PrintStream không thể bao bọc một Nhà văn.


3

Các nhà văn như PrintWriter dành cho đầu ra văn bản, các luồng dành cho đầu ra nhị phân. Các nhà văn xử lý các công cụ thiết lập nhân vật cho bạn. Các luồng không phải vì nó giả định rằng bạn không muốn loại chuyển đổi đó sẽ làm xáo trộn dữ liệu nhị phân của bạn và sẽ sử dụng một nhà văn nếu bạn đã làm.


1
Ngoại trừ PrintStream, vì cái đó lấy một mã hóa để nó có thể xử lý nhiều hơn một chút so với OutputStream tiêu chuẩn.
Simon Groenewolt

Nghe có vẻ lạ khi System.out, mục tiêu duy nhất là in chuỗi, thực sự là PrintStream.
phút

"Các nhà văn xử lý các công cụ thiết lập ký tự cho bạn" - chỉ các Nhà văn liên quan đến việc chuyển đổi các ký tự thành byte. Không phải tất cả các nhà văn làm.
Aivar

2

Bạn có thể ghi byte thô vào Luồng và không cho Nhà văn. Các PrintWriter danh sách javadoc sự khác biệt khác (quan trọng nhất, có khả năng thiết lập một mã hóa trên một dòng để nó có thể giải thích các byte liệu tôi muốn nói).


Với PrintStream, người ta cũng có thể chỉ định mã hóa
Aivar

1

từ lõi java của Horstmann

Các cựu chiến binh Java có thể tự hỏi bất cứ điều gì đã xảy ra với lớp PrintStream và System.out. Trong Java 1.0, lớp PrintStream chỉ cần cắt ngắn tất cả các ký tự Unicode thành các ký tự ASCII bằng cách bỏ byte trên cùng. (Vào thời điểm đó, Unicode vẫn là mã hóa 16 bit.) Rõ ràng, đó không phải là một cách tiếp cận rõ ràng hoặc di động và nó đã được sửa với sự giới thiệu của người đọc và người viết trong Java 1.1. Để tương thích với mã hiện có, System.in, System.out và System.err vẫn là các luồng đầu vào / đầu ra, không phải cho người đọc và người viết. Nhưng bây giờ, lớp PrintStream chuyển đổi bên trong các ký tự Unicode thành mã hóa máy chủ mặc định giống như cách PrintWriter thực hiện. Các đối tượng của loại PrintStream hoạt động chính xác như các nhà văn in khi bạn sử dụng các phương thức in và println,


-3

Printwriter là một sự tăng cường của dòng in.

Dòng in IE cho một mục đích cụ thể.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.