#java #inputstream #fileoutputstream
#java #входной поток #fileoutputstream
Вопрос:
У меня есть этот список файлов ArrayList
for(File file : files){
InputStream in = FileInputStream(file);
// process each file and save it to file
OutputStream out = FileOutputStream(file);
try{
} finally {
in.close();
out.close();
}
}
производительность действительно низкая, поскольку в каждом цикле есть in / out close(), есть ли лучший способ сделать это? Я попытался вывести outputstream из цикла, это не работает.
Комментарии:
1. хм… но, по крайней мере, это должно быть быстрее, когда несколько файлов читаются одновременно … в разных потоках… если вы читаете много файлов.. тогда это должно иметь смысл
2. (Что произойдет, если вы
new FileOutputStream
создадите исключение (возможно,FileNotFoundException
но, возможно, непроверенное исключение)? То же самое дляin.close();
. Требуется по одномуtry
—finally
на ресурс.)
Ответ №1:
Использование буферизованных потоков имеет огромную разницу.
Попробуйте это:
for(final File file : files) {
final InputStream in = new BufferedInputStream(new FileInputStream(file));
final OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(...)));
try {
// Process each file and save it to file
}
finally {
try {
in.close();
}
catch (IOException ignored) {}
try {
out.close();
}
catch (IOException ignored) {}
}
}
Обратите внимание, что IOException
ы, которые могут быть выданы при закрытии потоков, должны игнорироваться, иначе вы потеряете потенциальное исходное исключение.
Другая проблема заключается в том, что оба потока находятся в одном файле, что не работает. Итак, я полагаю, вы используете два разных файла.
Комментарии:
1. Я пытаюсь это сделать и возвращаюсь к вам с результатом
2. Я предлагаю придерживаться одного
try
—finally
для каждого базового ресурса. Еслиnew BufferedOutputStream(new FileOutputStream(new File(...)))
генерируется исключение, вы получаете беспорядок. Если закрытие выходного потока, скажем, вызывает исключение, вы просто пошли и создали поврежденный файл и проигнорировали его. Возможно, есть другая ошибка, но если вы делаете это неумным способом, все просто работает, и вам не нужно думать об этом.3. только что попробовал, и результат в два раза быстрее, чем в предыдущей версии, и он не займет места.
Ответ №2:
Close() может занимать до 20 мс. Я сомневаюсь, что это ваша программа, если у вас нет 1000 файлов.
Я подозреваю, что ваша проблема с производительностью заключается в отсутствии буферизации ввода и вывода. Можете ли вы также показать свои буферные оболочки?
Комментарии:
1. outputfile имеет размер около 200 МБ, поэтому он закрывает файл размером 200 мб в каждом цикле, вызывает ли это замедление?
2. close () закрывает flush (), поэтому сброс на диск (до) 100 МБ замедлит его, да.
3. Если у вас есть диск, на который вы выполняете чтение / запись, вы должны ожидать, что скорость чтения / записи на нем составит около 30 МБ в секунду. Если вы читаете и записываете 200 МБ, это должно занять около 13 секунд. 200*2/30. Это сколько времени это занимает?
4. Это съело весь мой / temp в c: , в любом случае, я думаю, что buffer решил проблему
Ответ №3:
вы, конечно, можете создать очередь выходных потоков и передать ее фоновому потоку, который обрабатывает закрытие этих выходных потоков. То же самое для входных потоков. В качестве альтернативы вы можете оставить это на усмотрение JVM — просто не закрывайте файлы и предоставьте GC делать это, когда объекты будут завершены.
Комментарии:
1. то есть вы имеете в виду, что мне не нужно закрывать () ?
2. речь не о «должен» — поскольку все зависит от контекста. Я лично не оставил бы close() в jvm, однако вы могли бы это сделать.
3. Если вы попытаетесь разделить потоки, вы можете фактически снизить производительность при вводе-выводе. Особенно, если это происходит при запуске этих старых электромеханических устройств с вращающимися носителями. (Хотя вы получаете буферизацию, подумайте о бедных маленьких головах, мечущихся вокруг, как будто они потеряли своих цыплят.)