Производительность: BufferedOutputStream против FileWriter

Я всегда использовал FileWriter для записи текст в файл на Java. Очевидно, вы также можете использовать BufferedOutputStream. . Внимательно прочитав оба javadocs, я не могу сказать, что было быстрее/эффективнее.

Поэтому я спрашиваю: есть ли разница в производительности (хотя бы минимальная) между этими двумя методами файлового ввода-вывода? Если да, то какие они и почему? Если нет, то почему они фактически одинаковы?

Существуют ли сценарии, в которых один предпочтительнее другого? Заранее спасибо!


person Community    schedule 08.07.2013    source источник


Ответы (2)


Если вы действительно хотите сравнить FileWriter с BufferedOutputStream для записи текстового файла, последний должен быть быстрее, так как там меньше операций ввода-вывода.

  • В случае FileWriter каждый вызов метода записи будет сохранен сразу (он не буферизуется).
  • В случае BufferedOutputStream данные будут записаны на диск, если буфер заполнен (или буфер явно сброшен с помощью метода flush).

Но если вы пишете текстовые файлы, вы должны использовать Writer; в этом случае мы можем сравнить FileWriter с BufferedWriter:

Смотря на

FileWriter fw = new FileWriter(...)

и

BufferedWriter bw = new BufferedWriter(new FileWriter(...)

у вас такая же ситуация с количеством операций ввода-вывода.


FileWriter использует FileOutputStream внутри. Причина использования FileWriter заключается в том, что он автоматически использует кодировку символов по умолчанию, когда вы записываете в файл (например, внутренняя строка Java кодируется в UTF-8). Если вы используете OutputStream, вам придется кодировать вручную при каждой записи:

Итак, этот пример для BufferedWriter:

bw.write("Hello");

соответствует этому примеру для BufferedOutputStream:

bos.write("Hello".getBytes(Charset.forName("utf-8")));

если ваша кодировка по умолчанию utf-8.

OutputStream имеет дело с (необработанными) байтами, тогда как Writer имеет дело с (текстовыми) символами.

person Beryllium    schedule 08.07.2013

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

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

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

person Joni    schedule 08.07.2013
comment
Спасибо @Joni (+1) - интересное наблюдение, но можно ли не писать текст в файлы с BufferedOutputStream?!? Эта статья, кажется, думает иначе. Если эта статья верна, то хотя FileWriter и BufferedOutputStream могут быть предназначены для двух разных целей, возможно (и, следовательно, суть моего вопроса) сравнить их производительность при записи текста в файл. - person ; 08.07.2013
comment
Опять же, очень интересные вещи @Joni! Согласно этот SO вопрос представляется возможным переопределить внутренний буфер, который использует FileWriter. Я хотел бы попробовать это, если ни для чего другого, для моего личного развлечения. На всю жизнь я не могу понять, как настроить OutputStreamWriter и FileOutputStream и внедрить их в конструктор FileWriter - есть идеи? И где мне указать новый размер буфера? Еще раз спасибо за всю большую помощь до сих пор! - person ; 08.07.2013
comment
Как вы можете видеть в статье, для того, чтобы сначала написать текст с BufferedOutputStream, они должны конвертировать любой текст в байты вручную, вызывая getBytes, что неудобно и создает массив байтов, который сразу становится мусором. - person Joni; 08.07.2013
comment
FileWriter на самом деле является подклассом OutputStreamWriter rigged, поэтому он может записывать только в FileOutputStream, поэтому, если вы хотите настроить какое-то свойство, вы можете просто создать OutputStreamWriter, связанный с FileOutputStream. Однако нет возможности изменить размер внутреннего буфера. Буфер по умолчанию 8 КБ, вероятно, достаточно велик для большинства приложений. - person Joni; 08.07.2013