Обработка исключений IO в Java
В принципе, я хочу открыть файл, прочитать несколько байтов, а затем закрыть файл. Вот что я придумал:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
try
{
// ...
inputStream.read(buffer);
// ...
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try
{
inputStream.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Возможно, я испорчен RAII, но должен быть лучший способ сделать это в Java, правильно?
Ответы
Ответ 1
Если у вас есть тот же код обработки исключений для IOException
и FileNotFoundException
, вы можете переписать свой пример более компактным способом только с одним предложением catch
:
try {
InputStream input = new BufferedInputStream(new FileInputStream(file));
try {
// ...
input.read(buffer);
// ...
}
finally {
input.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
Вы даже можете избавиться от внешнего try-catch
, если вы можете распространять исключение, которое, вероятно, имеет больше смысла, а затем вручную печатает трассировку стека. Если вы не поймаете какое-то исключение в своей программе, вы автоматически получите трассировку стека.
Также необходимость вручную закрыть поток будет рассмотрена в Java 7 с помощью автоматического управления ресурсами.
С автоматическим управлением ресурсами и распространением исключений код сводится к следующему:
try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
// ...
input.read(buffer);
// ...
}
Ответ 2
Обычно эти методы завершаются в библиотеках. Если вы не хотите писать на этом уровне, лучше всего создать свои собственные вспомогательные методы или использовать существующие, например FileUtils.
String fileAsString = Fileutils.readFileToString(filename);
// OR
for(String line: FileUtils.readLines(filename)) {
// do something with each line.
}
Ответ 3
Я не знаю, правильно ли это, но вы можете использовать весь свой код в одном блоке try, а затем иметь разные блоки catch сразу после друг друга.
try {
...
}
catch (SomeException e) {
...
}
catch (OtherException e) {
...
}
Ответ 4
Если вы хотите сделать это в простой Java, код, который вы опубликовали, выглядит нормально.
Вы можете использовать сторонние библиотеки, такие как Commons IO, в которых вам нужно будет писать гораздо меньше кода. например.
Отъезд Commons IO по адресу:
http://commons.apache.org/io/description.html
Ответ 5
Иногда вы можете уменьшить код до следующего:
public void foo(String name) throws IOException {
InputStream in = null;
try {
in = new FileInputStream(name);
in.read();
// whatever
} finally {
if(in != null) {
in.close();
}
}
}
Конечно, это означает, что вызывающий объект foo
должен обрабатывать IOException
, но в любом случае это должно быть в большинстве случаев. В конце концов, вы действительно не уменьшаете всю эту сложность, но код становится намного более читаемым из-за меньших вложенных обработчиков исключений.
Ответ 6
Мое использование этого без использования утилит:
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
// ...
inputStream.read(buffer);
// ...
} catch (IOException e) {
e.printStackTrace();
throw e; // Rethrow if you cannot handle the exception
} finally {
if (inputStream != null) {
inputStream.close();
}
}
Не однострочный, но не очень плохой. Используя, скажем, Apache Commons IO, это будет:
//...
buffer = FileUtils.readFileToByteArray(file);
//...
Дело в том, что стандартная Java не содержит многих из этих небольших утилит и простых в использовании интерфейсов, которые нужны всем, поэтому вам нужно полагаться на некоторые библиотеки поддержки, такие как Apache Commons, Google Guava,... в ваших проектах (или реализовать свои собственные служебные классы).
Ответ 7
Используйте org.apache.commons.io.FileUtils.readFileToByteArray(File)
или что-то подобное из этого пакета. Он по-прежнему бросает IOException, но он занимается очисткой для вас.
Ответ 8
Попробуйте следующее:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[1024];
try
{
// ...
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
//Process the chunk of bytes read
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
inputStream.close();
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Ответ 9
Google guava попытался решить эту проблему, введя Closeables.
В противном случае вам нужно подождать, пока AutoCloseable из JDK 7 не появится, поскольку он обращается к некоторым случаям, когда вызывается IOException.