Java: разница между PrintStream и PrintWriter

125

В чем разница между PrintStreamи PrintWriter? У них много общих методов, из-за чего я часто смешиваю эти два класса. Более того, я думаю, что мы можем использовать их для тех же целей. Но разница должна быть, иначе класс был бы только один.

Я просмотрел архивы, но не смог найти этот вопрос.

Мартин Курто
источник
1
+1 Хороший вопрос, я тоже смешиваю эти два класса, и документация по API тоже не очень помогает.
helpermethod
Еще одно отличие заключается в том, как работает автозапуск. Для писателя наличие символа \ n в выводе запускает flush (). Но в байтовом потоке (PrintStream) есть только байты. Затем autoflush работает, как описано в Javadoc, на основе: «собственного представления платформы о разделителе строк, а не о символе новой строки».
минут

Ответы:

129

Это может показаться легкомысленным, но PrintStreamпечать в файл OutputStreamи PrintWriterпечать в файл Writer. Хорошо, я сомневаюсь, что получу какие-то очки за утверждение очевидного. Но это еще не все.

Итак, в чем разница между an OutputStreamи a Writer? Оба являются потоками, с основным отличием в том, что a OutputStream- это поток байтов, а a Writer- это поток символов.

А если имеет OutputStreamдело с байтами, что насчет PrintStream.print(String)? Он преобразует символы в байты, используя кодировку платформы по умолчанию. Использование кодировки по умолчанию, как правило, плохо, поскольку это может привести к ошибкам при переходе с одной платформы на другую, особенно если вы создаете файл на одной платформе и используете его на другой.

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

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

МДМА
источник
3
Я тоже так думал - но это неправда. Даже PrintStream поддерживает Writer под капотом - если вы передадите ему OutputStream, он обернет его.
Джон Скит,
3
@Jon - внутри есть Writer, но он записывает в OutputStream, поэтому чистый эффект заключается в том, что PrintStream записывает в OutputStream - происходит преобразование char в байты и используется кодировка платформы по умолчанию. В PrintWriter нет такого требования для преобразования char-> byte, вы можете полностью использовать символы.
mdma
«Кодировка по умолчанию определяется во время запуска виртуальной машины и обычно зависит от языкового стандарта и кодировки базовой операционной системы.», Также Locale изменяет кодировку по умолчанию на некоторых платформах.
Pindatjuh
7
Начиная с Java 1.5, PrintStreamиспользование кодировки по умолчанию для платформы не ограничивается; есть конструкторы, которые принимают имя набора символов. Таким образом, различия между PrintStreamи PrintWriterзаключаются в том, что a PrintWriterне может записывать необработанные байты и эти два класса переносят разные типы адресатов.
Тед Хопп
1
Возможно, вам стоит также отметить значительную разницу в их поведении, хотя они эффективно используют методы интерфейса PrintStream, print()которые вызывают удобные функции write(), поэтому они запускают автозапуск, если он включен. PrintWriterс другой стороны, не будет автоматически запускаться после вызова print(). Сегодня я демонстрировал некоторым новичкам Java, и это привлекло внимание некоторых студентов, которые не были знакомы с необходимостью ручной промывки. В противном случае ваш ответ отличный.
Robadob
61

С помощью PrintStreamвы застряли в кодировке платформы по умолчанию.

PrintStream stream = new PrintStream(output);

Однако с помощью PrintWriterвы можете передать OutputStreamWriterс определенной кодировкой.

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

Преимущество состоит в том, что вы можете управлять кодировкой символов, в которой должны быть написаны символы, чтобы они в конечном итоге не превратились в моджибаке .

BalusC
источник
12
Начиная с версии 1.4, для PrintStream появился новый конструктор, который принимает кодировкуPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol
19

Начиная с JDK 1.4, можно указать кодировку символов для PrintStream. Таким образом, различия между PrintStream и PrintWriter связаны только с автоматическим сбросом и тем, что PrintStream не может обернуть Writer.

Ренан Мозоне
источник
3

Такие писатели, как PrintWriter, предназначены для вывода текста, потоки - для двоичного вывода. Сценаристы сделают за вас набор символов. Потоки этого не делают, потому что предполагается, что вы не хотите такого рода преобразования, которое могло бы испортить ваши двоичные данные, и в этом случае вы бы использовали писатель.

sblundy
источник
1
За исключением PrintStream, потому что он принимает кодировку, поэтому он может обрабатывать немного больше, чем стандартный OutputStream.
Саймон Гроенвольт,
Звучит странно, что System.out, единственной целью которого является печать строк, на самом деле является PrintStream.
минут
«Сценаристы обрабатывают набор символов за вас» - только писатели, которые занимаются преобразованием символов в байты. Не все писатели это делают.
Айвар
2

Вы можете записывать необработанные байты в Stream, а не в Writer. В PrintWriter списки Javadoc другие различия ( что самое главное, будучи в состоянии установить кодировку на поток , поэтому он может интерпретировать необработанные байты , я бы сказал).

Саймон Гроенвольт
источник
С помощью PrintStream можно также указать кодировку
Айвар
1

из ядра java от Хорстманна

Ветераны 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,

Nichijou
источник
-3

Printwriter - это усовершенствование printstream.

IE printstream для определенной цели.

Spoo
источник