FileOutputStream.close очень медленно при записи большого файла
У меня есть метод, который получает файл через сокет 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 ответа
В зависимости от ОС, 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
Из скорости видно, что в этой системе данные не записываются даже при закрытии. т.е. диск не такой быстрый.
Я видел то же самое с использованием файлового потока. Я обнаружил, что если вы откроете файл как readwrite, он кэширует все и не пишет, пока вы не закроете или не удалите его. Флеш не писал. Однако, если ваши записи увеличивают размер файла, он будет автоматически очищаться.
Открытие как раз и пишется автоматически при каждой записи.