Страницы

Поиск по вопросам

суббота, 11 января 2020 г.

В чем разница указать BufferedReader или указать буфер в методе read(byte[] byte)?

#java


Вот есть такой пример 

public static void main(String[] args) throws Exception {
FileInputStream inputStream = new FileInputStream("c:/data.txt");
FileOutputStream outputStream = new FileOutputStream("c:/result.txt");

byte[] buffer = new byte[1000];
while (inputStream.available() > 0){

int count = inputStream.read(buffer); 
outputStream.write(buffer, 0, count); 
}

inputStream.close();
outputStream.close();
}


Вот тут несколько вопросов 


Зачем нужно указывать outputStream.write(buffer, 0, count);
количество байтов для записи (от и до 0, count) , если все равно
метод read(byte[] byte) будет читать байты до тех пор пока буфер
не заполнится или пока байты в файле не кончатся. 

Я так понимаю, что сколько дали байтов столько и записал
outputStream.write(buffer);, зачем ставить от и до?
Зачем указывать буфер когда есть BufferedInputStream()? Если я
правильно понимаю, то он будет работать также как если мы укажем  byte[] byte = new
byte[1000]... Он так же будет буферизировать байты перед записью....


ПРАВКА

По поводу второго моего вопроса вот метод для примера 

private void writeFile(File file, byte[] bytes) {
    BufferedOutputStream bos = null;

    try {
        bos = new BufferedOutputStream(new FileOutputStream(file));
        bos.write(bytes);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (image != null) {
            image.close();
        }
        if (null != bos) {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


ПРАВКА2


    


Ответы

Ответ 1



Методам write(byte[] data) или write(byte[] data, int offset, int length) классов FileOutputStream и BufferedOutputStream для записи массива все равно надо указать массив с прочитанными байтами, так что в любом случае перед записью байтов их надо будет прочитать во внутренний буфер. Так что использование BufferedInputStream вместо FileInputStream не освобождает от необходимости читать данные во внутренний буфер. Более того, если не использовать специфические возможности буферизованных потоков, код для работы с буферизованными и небуферизованными потоками будет вообще одинаковый. Другое дело, что в большинстве случаев работа с буферизованными потоками будет на порядок быстрее. Вы в своих рассуждениях забываете о том, что последний (а возможно, единственный) фрагмент входного файла не обязан по размеру совпадать с размером буфера, так что в любом случае при записи последнего фрагмента необходимо указывать, сколько байтов надо записать - а именно, столько, сколько фактически было прочитано. Иначе при записи к концу файла припишется лишний мусор, которого не было во входном файле (в случае единственного фрагмента это будут нули, а в случае неединственного повторно запишется часть предыдущего фрагмента). Поэтому в любом случае для записи по крайней мере одного (последнего) фрагмента надо будет использовать write(byte[] data, int offset, int length), а использование разных методов для записи последнего и непоследнего фрагментов - это лишнее усложнение кода.

Ответ 2



Создавая массив байт, вы вылеляете 1000 байт в куче, которые java любезно заливает вам нулями. Т.е. в этой строке: byte[] buffer = new byte[1000]; вы говорите: пожалуйста, залей мне 1000 байт нулями и сохрани ссылку на массив в переменную buffer. Когда вы вызываете метод is.read(buffer), он читает то количество байт, которое удалось прочитать. И после возвращает количество байт, которые он прочитал, которое вы и сохраняете в переменную count. После этих манипуляций у вас будет массив из 1000 байт, count из которых будут залиты прочитаными значениями, а остальные байты будут нулями. Чтобы не записывать в файл ненужные нули, которых по сути и не было в исходном файле, вы говорите: os.write(buffer, 0, count), что равносильно: пожалуйста, залей мне в поток байты из буфера buffer начиная с 0-го, всего count штук. А в BufferedOutputStream нет метода write с сигнатурой (byte[]). Еще раз. Так как выходной поток понятия не имеет, хотите вы записать в него весь массив байт, или часть, то он спрашивает у вас начальную позицию и количество байт, которые записывать. Поймите. Это сделано для удобства. Вы можете считывать куда угодно байты из InputStream, создавать правильный массив нужной длины, копировать в него нужные значения и передавать на запись целый массив, не указывая начальную позицию и количество байт, но это: Не рационально. Требуется процессорные время и дополнительный кусок памяти для создания массива нужной длины. Не удобно, так как много лишнего кода. Т.е. подведя черту: с таким api вы можете создать некоторый буфер размером n и переиспользовать его сколько угодно раз для чтения байт из потока, а переменная count будет сообщать, сколько на данный момент содержится валидных байт в вашем буфере. А так же: при чтении из потока в цикле учитывайте то, что может прочитаться меньшее кол-во байт, чем размер вашего буфера. И переменная count будет говорить о том, сколько было прочитано байт. Как-то так

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

Отправить комментарий