#java #stream #findbugs #software-quality
Вопрос:
Я пишу метод, но вижу эту ошибку: возможно, не удастся закрыть поток. Согласно некоторым решениям в разных сообщениях, я добавил «попробуйте и поймайте» в блоке «Наконец». Я также добавил IOUtils.closeQuietly(полный объект, (Журнал) РЕГИСТРАТОР). Но это все равно не работает. Кто-нибудь может помочь взглянуть? Спасибо!
S3Object fullObject = null;
StringBuffer buffer = new StringBuffer();
try {
S3Object s3Response = s3Client.getObject(s3BucketName, s3Key);
BufferedReader reader = new BufferedReader(new InputStreamReader(s3Response.getObjectContent()));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
} finally {
if (fullObject != null) {
try {
fullObject.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
IOUtils.closeQuietly(fullObject, (Log) LOGGER);
}
}
return buffer.toString();
}
Комментарии:
1. Вы пробовали поставить
IOUtils.closeQuietly(fullObject, (Log) LOGGER);
внутриfinally
блок для внутреннегоtry-catch
?2. Кроме того, в текущем коде
fullObject
всегдаnull
есть ?
Ответ №1:
InputStreamReader
инвентарь AutoCloseable
. Это означает, что предполагаемое использование try-with-resources
:
try (InputStreamReader reader = new InputStreamReader(s3Response.getObjectContent()) {
...
}
Это всегда должно закрывать поток независимо от того, как блок завершается (т. Е. через обычное завершение catch
или finally
предложения).
То же самое верно S3Object
и для BufferedReader
и. Все они могут быть объявлены как ресурсы в одном try
блоке.
Видишь https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html для получения более подробной информации.
Ответ №2:
Вы должны использовать Java 7 попробуйте с ресурсами. Он позаботится о закрытии ресурсов, которые вы объявите в списке. Любые исключения, которые могут возникнуть в процессе закрытия, будут рассмотрены надлежащим образом. (Им либо разрешается распространяться, либо они «подавляются», если исключение уже распространялось.)
Ваш код, использующий try с ресурсами, будет выглядеть следующим образом. Это вдвое меньше первоначальной версии, и в ней не будет никаких утечек ресурсов. Вы «выигрываете» в обоих направлениях.
try (S3Object s3Response = s3Client.getObject(s3BucketName, s3Key);
BufferedReader reader = new BufferedReader(
new InputStreamReader(s3Response.getObjectContent()));
)
{
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
return buffer.toString();
}
Обратите внимание, что я избавился от fullObject
того, что ваш код не использовал.
На самом деле в приведенном выше описании есть два управляемых ресурса: the s3Response
и the reader
. Возможно, нет особой необходимости закрывать оба, но (ИМО) закрывать их в любом случае правильно … с точки зрения читабельности, если ничего другого.
(Также может быть возможно сделать «чтение содержимого в виде строки» более простым и/или более эффективным, но это выходит за рамки данного вопроса.)