Как PrintWriter может записывать в поток байтов, но BufferedWriter не может?

#java #io #printwriter #bufferedwriter #writer

#java #io #printwriter #bufferedwriter #писатель

Вопрос:

Для начала я предоставлю фрагмент кода с комментариями:

 FileOutputStream fos = new FileOutputStream ("test.txt");
//fos IS-A OutputStream as FileOutputStream extends OutputStream

PrintWriter pw = new PrintWriter (fos); //compiles (can take OutputStream)

BufferedWriter bw = new BufferedWriter (fos); //doesn't compile (can't take OutputStream)
//Need to do this:
BufferedWriter bufferedWriter = new BufferedWriter (new OutputStreamWriter (fos)); //compiles
  

Я думал, что знаю потоки ввода-вывода, пока не наткнулся на эту ошибку. Может кто-нибудь объяснить, как PrintWriter можно записывать в поток байтов, в то время BufferedWriter как не может? Разве они не должны быть одинаковыми? Я всегда считал их равными (имеется в виду внутренняя реализация), но разница заключалась в методах, которыми они обладают.

Похоже, я ошибался 🙂 Я вижу это так: BufferedWriter невозможно записать в поток байтов, поскольку это поток символов, что означает, что кто-то должен преобразовать эти символы. Вот почему мы «даем» OutputStreamWriter в качестве моста от символьных к байтовым потокам. Итак, почему PrintWriter этот «мост» не нужен. Разве у них не может быть способа кодирования и облегчения нашей жизни? Или я виноват в том, что что-то упустил?

Комментарии:

1. Кажется, я понял, что-то треснуло у меня в голове 🙂 Я не могу этого сделать, поскольку BufferedWriter — это просто класс декоратора, верно? Мне нужен «конкретный класс», который действительно что-то делает. Итак, используя BufferedWriter, я мог бы даже обернуть PrintWriter, но мне всегда нужен класс, который «должен выполнять работу». Что-нибудь близкое к ответу?

2. Вы правы, a BufferedWriter может записывать только в Writer такой, как PrintWriter . Он добавляет буферизацию к любому Writer, но он не может (и не должен) самостоятельно выполнять преобразование текста в байт.

3. PrintWriter использует это как «удобную функцию», но, возможно, даже не стоит ее предоставлять вообще. BufferedWriter не беспокоит — это работает так, как задумано, что вы можете / должны использовать OutputStreamWriter мост.

4. Правильно, a Writer принимает (необработанный) поток. Затем оберните Writer в BufferedWriter . Это двухэтапный процесс, а иногда и болезненный, но ясность и контроль того стоят, imo.

Ответ №1:

Итак, почему PrintWriter не нужен этот «мост».

В <a rel="noreferrer noopener nofollow" href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/PrintWriter.html#(java.io.OutputStream)» rel=»nofollow noreferrer»>javadocs для PrintWriter(OutputStream, ...) конструкторов указано, что они являются удобными конструкторами. Короче говоря, они предоставляют быстрый способ сделать что-то, что вы можете сделать другим способом.

Разве у них не может быть способа кодирования и облегчения нашей жизни?

Теперь вы имеете в виду BufferedWriter, не имеющий удобного конструктора, который принимает OutputStream аргумент.

Как правило, удобные конструкторы и методы предоставляются для вариантов использования, которые считаются достаточно распространенными, чтобы гарантировать это.

В этом случае им потенциально потребуется предоставить множество удобных конструкторов:

  • BufferedWriter(OutputStream) использование кодировки по умолчанию.
  • BufferedWriter(OutputStream, String) предоставление имени кодировки
  • BufferedWriter(OutputStream, Charset) предоставление кодировки
  • BufferedWriter(OutputStream, CharsetEncoder) прямая поставка кодировщика кодировки

и, возможно, еще 4 для предоставления размеров буфера, отличных от стандартных.

Я полагаю, они не считали это оправданным.