#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 для предоставления размеров буфера, отличных от стандартных.
Я полагаю, они не считали это оправданным.