it-swarm.com.ru

Разница в Java между FileWriter и BufferedWriter

Какая разница между ними? Я только изучаю Java ATM, но кажется, что я могу записать в файл обоими способами, т.е. (я не скопировал здесь блок try-catch).

FileWriter file = new FileWriter("foo.txt");
file.write("foobar");
file.close();

а также

FileWriter file = new FileWriter("foo.txt");
BufferedWriter bf = new BufferedWriter(file);
bf.write("foobar");
bf.close();

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

63
Opi

BufferedWriter более эффективен, если вы

  • иметь несколько записей между сбросом/закрытием
  • записи небольшие по сравнению с размером буфера.

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

это означает, что первый пример записывает символы один за другим, а второй первый буферизует его в памяти и записывает один раз

В обоих случаях строка записывается сразу.

Если вы используете только FileWriter ваши вызовы записи (String)

 public void write(String str, int off, int len) 
        // some code
        str.getChars(off, (off + len), cbuf, 0);
        write(cbuf, 0, len);
 }

Это делает один системный вызов на каждый вызов для записи (String).


Где BufferedWriter повышает эффективность, заключается в нескольких небольших записях.

for(int i = 0; i < 100; i++) {
    writer.write("foorbar");
    writer.write(NEW_LINE);
}
writer.close();

Без BufferedWriter это может сделать 200 (2 * 100) системных вызовов и запись на диск, что неэффективно. С помощью BufferedWriter все они могут быть объединены в буфер, и, поскольку размер буфера по умолчанию составляет 8192 символа, это становится всего одним системным вызовом для записи.

79
Peter Lawrey

Вы правы. Вот как выглядит write() метод BufferedWriter:

public void write(int c) throws IOException {
    synchronized (lock) {
        ensureOpen();
        if (nextChar >= nChars)
            flushBuffer();
        cb[nextChar++] = (char) c;
    }
}

Как вы можете видеть, он действительно проверяет, заполнен ли буфер (if (nextChar >= nChars)), и очищает буфер. Затем он добавляет новый символ в буфер (cb[nextChar++] = (char) c;).

8
AlexR

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

4
RNJ

Из спецификации Java API:

FileWriter

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

BufferedWriter

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

0
Magicode

http://docs.Oracle.com/javase/1.5.0/docs/api/Java/io/BufferedWriter.html

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

PrintWriter out = новый PrintWriter (новый BufferedWriter (новый FileWriter ("foo.out")));

буферизует вывод PrintWriter в файл. Без буферизации каждый вызов метода print () приведет к преобразованию символов в байты, которые затем будут немедленно записаны в файл, что может быть очень неэффективным.

0
Ilia Nedoluzhko