2016-04-02 5 views
1

нам было предложено несколько упражнений в лаборатории, и один из них - преобразовать метод передачи файлов из FileInputStream в BufferedInputStream. Это клиент, отправляющий запрос GET на веб-сервер, который отправляет запрошенный файл. Я придумал простое решение, и я просто хотел проверить, правильно ли это.От преобразования FileInputStream в BufferedInputStream

Оригинальный код:

try { 
     FileInputStream fis = new FileInputStream(req); 
     // req, String containing file name 
     byte[] data = new byte [fis.available()]; 
     fis.read(data); 
     out.write(data); // OutputStream out = socket.getOutputStream(); 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

Моя попытка:

try { 
     BufferedInputStream bis = new BufferedInputStream (new FileInputStream(req)); 
     byte[] data = new byte[4]; 

     while(bis.read(data) > -1) { 
     out.write(data); 
     data = new byte[4]; 
     } 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

Файл представляет собой веб-страницу с именем index.html, который содержит простой HTML-страницы. Мне нужно перераспределять массив каждый раз, потому что при последнем выполнении цикла while, если размер файла не кратен 4, массив данных будет содержать символы из предыдущего выполнения, которые отображаются в браузере , Я выбрал 4 как размер данных для целей отладки. Выход правильный.

Это хорошее решение, или я могу лучше?

ответ

1

Нет необходимости повторно создавать массив байтов каждый раз - просто перезапишите его. Что еще более важно, однако, у вас есть концептуальная ошибка внутри вашей петли. Каждая итерация просто записывает массив в поток, считая его действительным. Если вы проверите документацию BufferedInputStream#read, вы увидите, что она может не читать достаточно данных, чтобы заполнить весь массив и вернет количество байтов, которое оно фактически прочитало. Вы должны использовать этот номер, чтобы ограничить количество байт вы пишете:

while((int len = bis.read(data)) > -1) { 
    out.write(data, 0, len); 
} 
0

Я предлагаю вам закрыть файл, как только вы закончите. BufferedInputStream по умолчанию использует буфер размером 8 КБ, который вы уменьшаете до меньшего буфера. Более простым решением является копирование 8 КБ за раз и не использование добавленного буфера

try (InputStream in = new FileInputStream(req)) { 
    byte[] data = new byte[8 << 10]; 
    for (int len; (len = bis.read(data)) > -1;) 
     out.write(data, 0, len); 
} catch (IOException e) { 
    out.write("404 Not Found\n".getBytes()); 
} 
+0

спасибо за ответ. В случае файлов, хранящихся на hd, FileInputStream обращается к диску при каждой операции чтения, тогда как BufferedInputStream не будет, что делает его более эффективным, вообще говоря. Это то же самое, когда файлы передаются по сети - что я теперь делаю? Или в принципе нет разницы? –

+0

FileInputStream обращается к ОС на каждый прочитанный, ОС может использовать прогнозируемое чтение вперед и будет так часто попадать на диск. BufferedInputStream помогает только в том случае, если блоки данных, которые вы читаете, намного меньше, например. << 512 байт, чем буфер, который он читает. то есть это не волшебство, а просто делает то, что вы уже делаете, читая большой буфер. –

 Смежные вопросы

  • Нет связанных вопросов^_^