Java: різниця між PrintStream та PrintWriter


125

У чому різниця між PrintStreamі PrintWriter? У них є багато спільних методів, завдяки яким я часто поєдную ці два класи. Більше того, я думаю, ми можемо використовувати їх для абсолютно однакових речей. Але має бути різниця, інакше був би лише один клас.

Я шукав архіви, але не зміг знайти це питання.


1
+1 Добре запитання, я також змішую ці два класи, і API документа теж не дуже допомагає.
helpermethod

Ще одна відмінність полягає в тому, як працює автовідмивка. Для письменника наявність \ n символу у виході запускає flus (). Але в байтовому потоці (PrintStream) є лише байти. Тоді autoflush працює, як описано в Javadoc, базуючись на "власному розумінні платформи про роздільник рядків, а не на символі нового рядка".
хвилини

Відповіді:


129

Це може здатися легким, але PrintStreamдрукує до OutputStreamта PrintWriterдрукує до Writer. Гаразд, я сумніваюся, що я отримаю якісь бали за твердження очевидного. Але є більше.

Отже, яка різниця між a OutputStreamі a Writer? Обидва є потоками, головна відмінність яких OutputStream- це потік байтів, а a Writer- потік символів.

Якщо OutputStreamугоди з байтами, а що PrintStream.print(String)? Він перетворює символи в байти, використовуючи кодування платформи за замовчуванням. Використання кодування за замовчуванням, як правило, погано, оскільки це може призвести до помилок при переході з однієї платформи на іншу, особливо якщо ви генеруєте файл на одній платформі та використовуєте його на іншій.

За допомогою параметра a Writer, ви зазвичай вказуєте кодування, яке слід використовувати, уникаючи будь-яких залежностей платформи.

Навіщо турбуватися з тим, що маєте PrintStreamв JDK, оскільки основним завданням є написання символів, а не байтів? PrintStreamдо JDK 1.1, коли були введені потоки символів Reader / Writer. Я думаю, що Сонце було б застарілим, PrintStreamякби тільки той факт, що його так широко використовують. ( В кінці кінців, ви не хотіли б кожен виклик , System.outщоб згенерувати застарілий API попередження! Крім того , зміна типу від PrintStreamдо PrintWriterна стандартних вихідних потоків порвали б існуючі програми.)


3
Це я і думав, але це неправда. Навіть PrintStream підтримує програму Writer під кришкою - якщо ви передаєте їй OutputStream, він завершує її.
Джон Скіт

3
@Jon - внутрішньо є Writer, але він пише в OutputStream, тому чистий ефект полягає в тому, що PrintStream записує в OutputStream - char для перетворення байтів відбувається і використовує кодування платформи за замовчуванням. Немає такої вимоги для перетворення баз-> байтів у PrintWriter, ви можете весь час залишатися з символами.
mdma

"Набір шаблонів за замовчуванням визначається під час запуску віртуальної машини і, як правило, залежить від місцеположення та діаграми базової операційної системи.", Також Locale змінює схему за замовчуванням на деяких платформах.
Піндатхух

7
Оскільки Java 1.5 PrintStreamне обмежувався використанням кодування платформи за замовчуванням; є конструктори, які приймають ім'я шаблона. Таким чином, відмінності між PrintStreamі PrintWriterполягають у тому, що PrintWriterне можна писати необроблені байти, а два класи містять різні типи призначення.
Тед Хопп

1
Можливо, варто також відзначити істотну різницю у їхній поведінці, хоча ефективні методи спільного використання інтерфейсу PrintStream- print()це функції зручності, які викликають write(), як такі вони запускають автоматичне відмивання, якщо це увімкнено. PrintWriterз іншого боку, не вимикається після дзвінка на print(). Я демонстрував початківців Java сьогодні, і це виловлювало студентів, які не були знайомі з необхідністю ручного промивання. Інакше ваша відповідь чудова.
Робадоб

61

Завдяки PrintStreamкодуванню платформи за замовчуванням.

PrintStream stream = new PrintStream(output);

Однак PrintWriterви можете передавати OutputStreamWriterкодування з певним кодуванням.

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

Перевага полягає в тому, що ви можете керувати символами, що кодують символи, слід записати так, щоб вони в кінцевому підсумку не закінчилися як mojibake .


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.
хв

"Письменники обробляють набір символів для вас" - лише письменники, які займаються перетворенням символів у байти. Не всі письменники це роблять.
Айвар

2

Ви можете писати необроблені байти в Stream, а не в 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 діють точно так само, як і автори друку, коли ви використовуєте методи print та println,


-3

Printwriter - це розширення потоку друку.

IE printstream для конкретних цілей.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.