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"));

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


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.
— Саймон Гроенвольт,

Звучит странно, что 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,


-3

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.