DataOutputStream#writeBytes (String) vs BufferedWriter#write (String)

Я хотел бы создать HTML-файл для моего отчета. Содержимое отчета может быть создано либо с помощью BufferedWriter#write(String)

File f = new File("source.htm");
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write("Content");

и с помощью DataOutputStream#writeBytes(String)

File f = new File("source.htm");
DataOutputStream dosReport = new DataOutputStream(new FileOutputStream(f)); 
dosReport.wrtiteBytes("Content");

один из них лучше другого? Почему это так?

3 ответов


если вы пишете текст, то вы должны использовать Writer, который обрабатывает преобразование из символов Юникода (внутреннее представление строк Java) в соответствующую кодировку символов, такую как UTF-8. DataOutputStream.writeBytes просто выводит восемь битов низкого порядка каждого char в строке и полностью игнорирует восемь битов высокого порядка - это эквивалентно UTF-8 для символов ASCII с кодами ниже 128 (U+007F и ниже), но почти наверняка неправильно для чего-либо за пределами ФОРМАТ ASCII.

вместо FileWriter вы должны использовать OutputStreamWriter, чтобы выбрать определенную кодировку (FileWriter всегда использует кодировку по умолчанию платформы, которая варьируется от платформы к платформе):

File f = new File("source.htm");
BufferedWriter bw = new BufferedWriter(
  new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
bw.write("Content");

во-первых,DataOutputStream в вашем 2-м примере не служит никакой полезной цели1. Действительно, если ваши строки содержат символы, которые не вписываются в 8 бит,writeBytes(String) метод будет искажать текст. Избавься от него. Потоки данных предназначены для чтения и записи мелкозернистых двоичных данных. Для простых байтов используйте простой (или буферизованный) входной или выходной поток.

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

так в этом случае. вы должны сравнивать:

    File f = new File("source.htm");
    Writer w = new FileWriter(f);
    w.write("Content");

и

    File f = new File("source.htm");
    OutputStream os = new FileOutputStream(f); 
    os.write("Content".getBytes());

на мой взгляд, первый вариант выглядит проще и чище. И лучше всего использовать Reader и Writer стеки для ввода-вывода текста ... потому что для этого они и были созданы. (Они заботятся о проблемах кодирования и декодирования, чисто и прозрачно.)

вы можете проверить их, если вы действительно нужно знать, что быстрее (в вашей системе!) но я подозреваю, что нет большой разницы ... и что первая версия быстрее.

1-я думаю, что DataOutputStream имеет буферизацию под обложками, но для этого случая использования буферизация не помогает производительности.


в случаях использования, когда вы выполняете несколько (малых) записей вместо большого, есть значительное преимущество в производительности при использовании BufferedWriter (или BufferedOutputStream) вместо несвязанный писатель или поток.


другой момент заключается в том, что обе версии вашего кода используют кодировку символов платформы по умолчанию для кодирования выходного файла. Возможно, более целесообразно использовать определенную кодировку независимо от значения по умолчанию или сделать ее параметром конфигурации или командной строки.


OutputStream:

этот абстрактный класс является суперклассом всех классов, представляющих выходной поток байтов. Выходной поток принимает выходные байты и отправляет их в некоторый приемник.

приложения, которые должны определить подкласс OutputStream должен всегда предоставлять по крайней мере метод, который записывает один байт вывода.

например:

OutputStream os = new FileOutputStream("test.txt");

BufferedWriter

пишет текст в поток вывода символов, буферизация символов, чтобы обеспечить эффективную запись отдельных символов, массивов и строк. Может быть указан размер буфера или принят размер по умолчанию. Значение по умолчанию достаточно велико для большинства целей.

A newLine() предоставляется метод, который использует собственное понятие платформы разделителя строк, определенное строкой системного свойства.разделитель. Не все платформы используют символ новой строки ('\n') для завершения строк. Вызов этого поэтому метод завершения каждой выходной строки предпочтительнее, чем запись символа новой строки напрямую.

в общем случае писатель немедленно отправляет свой вывод в базовый символьный или байтовый поток. Если не требуется вывод подсказки, рекомендуется обернуть BufferedWriter вокруг любого писателя, чьи write() операции могут быть дорогостоящими, например,FileWriters и OutputStreamWriters.

например:

 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));