FileOutputStream.close очень медленно при записи большого файла - PullRequest
5 голосов
/ 21 октября 2011

У меня есть метод, который получает файл через сокет TCP, используя этот код:

FileOutputStream fileStream = new FileOutputStream(filename.getName());
while (totalRead < size) {
    if (size - totalRead > CHUNKSIZE) {
        read = getInputStream().read(buffer, 0, CHUNKSIZE);
    } else {
        read = getInputStream().read(buffer, 0, size - totalRead);
    }
    totalRead += read;
    fileStream.write(buffer, 0, read);
    fileStream.flush();

    if (System.currentTimeMillis() > nextPrint) {
        nextPrint += 1000;
        int speed = (int) (totalRead / (System.currentTimeMillis() - startTime));
        double procent = ((double)totalRead / size) * 100;
        gui.setStatus("Reciving: " + filename + " at " + speed + " kb/s, " + procent + "% complete");
    }
}
gui.setStatus("Reciving: " + filename + " complete.");
fileStream.close();

FileOutputStream.close занимает очень много времени при получении больших файлов, почему так?Как вы видите, я очищаю поток в каждом полученном фрагменте ..

Ответы [ 2 ]

3 голосов
/ 21 октября 2011

В зависимости от ОС, flush() не делает ничего больше, чем принудительно записывает данные в ОС. В случае FileOutputStream write () передает все данные в ОС, поэтому flush () ничего не делает. Где close() может гарантировать, что файл фактически записан на диск (или не зависит от ОС). Вы можете посмотреть, занят ли диск при записи данных.

500 МБ файлов, занимающих 30 секунд, означают, что вы пишете 17 МБ / с. Это звучит как очень медленный диск или файл на общем сетевом ресурсе / диске.


Вы можете попробовать это

File file = File.createTempFile("deleteme", "dat"); // put your file here.
FileOutputStream fos = new FileOutputStream(file);
long start = System.nanoTime();
byte[] bytes = new byte[32 * 1024];
for (long l = 0; l < 500 * 1000 * 1000; l += bytes.length)
    fos.write(bytes);
long mid = System.nanoTime();
System.out.printf("Took %.3f seconds to write %,d bytes%n", (mid - start) / 1e9, file.length());
fos.close();
long end = System.nanoTime();
System.out.printf("Took %.3f seconds to close%n", (end - mid) / 1e9);

печать

Took 0.116 seconds to write 500,006,912 bytes
Took 0.002 seconds to close

Из скорости видно, что в этой системе данные не записываются даже при закрытии. то есть диск не такой быстрый.

1 голос
/ 31 декабря 2011

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

Открытие как только запись автозаполняется при каждой записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...