Подтвердить что ты не робот

Обработка исключений 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, правильно?

4b9b3361

Ответ 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.