2012-02-11 2 views
0

Я загружаю базы данных из сети, которые составляют от 100 Кбайт до 500 Кбайт. Вот мой код (удален бесполезный код):FileOutputStream очень медленный

URLConnection uConnection = downloadUrl.openConnection(); 
InputStream iS = uConnection.getInputStream(); 
BufferedInputStream bIS = new BufferedInputStream(iS); 
byte[] buffer = new byte[1024]; 
FileOutputStream fOS = new FileOutputStream(db); 
int bufferLength = 0; 
while ((bufferLength = bIS.read(buffer)) > 0) { 
fOS.write(buffer, 0, bufferLength); 
} 
fOS.close(); 

Моя проблема в том, что она занимает много времени для него, чтобы закончить While-заявление. Я что-то испортил код? Это не должно занять столько времени для таких небольших файлов, не так ли? Я говорю о 1 минуте, за три файла размером не более 1 Мб ... Спасибо заранее!

+2

Что заставляет вас думать, что проблема связана с 'FileOutputStream'? Проблема может быть так же легко доступна для загрузки ваших данных. Вы использовали что-то вроде Traceview, чтобы точно определить, где вы тратите ваше время? – CommonsWare

+0

Я не знаю, что такое Traceview. Я отлаживал код, и из-за того, что while-statement он очень медленный. Я также подумал, что загрузка данных выполняется, когда мой InputStream-Object инстанцируется. Или он не загружен там? – ezcoding

+0

, используя буфер размером 1024, является ИМХО плохая идея. На смартфоне все носители обычно имеют размер блока размером 4096 байт или больше (например, SD-Card). – Robert

ответ

4

«Медленное» действительно довольно неоднозначное. При этом, учитывая то, что вы пытаетесь сделать, вы не должны использовать BufferedInputStream, а ваш buffer слишком мал.

Буферизованные обертки предназначены для оптимизации небольших операций чтения/записи. Поскольку все, что вы делаете, пытается как можно быстрее прочитать тонну данных, вы должны просто прочитать непосредственно из InputStream и использовать большой буфер (скажем, 64k, поскольку основной код на самом деле, вероятно, будет фрагментировать размер в любом случае).

byte[] buffer = new byte[65536]; 
... 
while ((bufferLength = iS.read(buffer, 0, buffer.length) > 0) { 
    ... 
+0

Я попробую. Есть ли хорошая онлайн-литература о Java I/O? Это меня смущает :) – ezcoding

+1

Мне нужно было бы общаться с Google, но это не относится к Java. Подумайте об этом так: если вам нужно было перемещать кучу воды из одного места в другое, что было бы быстрее; используя чашку 16 унций или ведро 5gal? С помощью этого небольшого буфера вам нужно заполнить и опорожнить его намного больше, а это будет стоить. Буферизованная обертка предназначена для того, когда вы знаете, что вам понадобится куча воды, но только хотите иметь дело с ней в чашку за раз. Он предварительно берет ведро и позволяет вам получать от него кубки. Когда ковш пуст, он заправляет его. –

+0

Хорошо, спасибо :) – ezcoding

-3

Я нашел реальное решение в JDK 1,7, который сделан по надежным, быстрым, простым и почти окончательно породит жалкое завесу на старых java.io solutions.Despite полотно еще много полный примеров копирования файлов в java с использованием In/out Streams. Я буду предлагать всем использовать простой метод.: java.nio.Files.copy (путь, путь назначения) с необязательными параметрами для замены адресата, перенести атрибуты файлов метаданных и даже попробовать транзакционное перемещение файлов (если это разрешено базовой ОС). Это действительно хороший Иов, так долго ждал! Вы можете легко преобразовать код из copy (Файл file1, File file2), добавив «.toPath()» в экземпляр файла (например, file1.toPath(), file2.toPath(). логический метод isSameFile (file1.toPath(), file2.toPath()), уже используется внутри вышеуказанного метода копирования, но его можно легко использовать в любом случае. Для каждого случая вы не можете обновить до 1.7, используя библиотеки сообщества из Apache (commons-io) или Google (guava commons) по-прежнему предлагается.

+2

И что это связано с чтением данных из сокета и его записью файл? –