Сканер: избавление от утечки ресурсов: «‹unassigned Closeable value›» никогда не закрывается

Я пытаюсь создать своего рода служебный метод для чтения текстовых файлов из ресурсов в Spring Boot. Чтобы прочитать файлы, я смотрю на них как InputStreams:

Resource resource = new ClassPathResource(fileLocationInClasspath);
InputStream resourceInputStream = resource.getInputStream();

(Обратите внимание, что Resource#getInputStream выдает IOException)

Затем я пытаюсь использовать сканер, как указано в глупые трюки со сканером вместо Reader или чего-то подобного, так как это элегантный и простой способ сделать это.

Однако у меня возникли проблемы с избавлением от предупреждения, упомянутого в заголовке вопроса. Даже если я просто вызову scanner.close() (до способа java-8), предупреждение останется.

Попытка №1 (первая попытка):

public static String readFileFromResources(String fileName) throws IOException {
    try (Scanner sc = new Scanner(new ClassPathResource(fileName).getInputStream()).useDelimiter("\\A")) {
        return sc.next();
    }
}

Попытка №2:

public static String readFileFromResources(String fileName) throws IOException {
    Scanner sc = new Scanner(new ClassPathResource(fileName).getInputStream()).useDelimiter("\\A");
    String text = sc.next();
    sc.close();
    return text;
}

Попробуйте 3 (предупреждение исчезнет):

public static String readFileFromResources(String fileName) throws IOException {
    try (Scanner sc = new Scanner(new ClassPathResource(fileName).getInputStream()).useDelimiter("\\A")) {
        return sc.next();
    } catch (Exception e) // Note Exception class
    {
        throw new IOException(e); //Need to catch this later
    }
}

Может ли кто-нибудь объяснить, почему try#1 и try#2 выдают предупреждение? Я предполагаю, что попытка #3 не работает, потому что мы перехватываем все возможные исключения. Но единственное исключение, которое может быть выброшено, — это метод IOException from getInputStream(). Если Scanner вызывает подозрение на какое-либо исключение, то почему оно не заставляет нас перехватывать это исключение? Ведь ловить исключения с помощью Exception не рекомендуется.

Наконец, я подумал, может быть, это проблема STS (набор инструментов Spring)?

(Если это играет какую-то роль-> JDK Version: 1.8.0_191)


person George Z.    schedule 08.03.2019    source источник
comment
Имейте в виду, статья, на которую вы ссылаетесь, написана в 2004 году, это очень давно. Вещи, упомянутые в статье, могут устареть.   -  person MC Emperor    schedule 08.03.2019
comment
@MCEmperor Да, я заметил это и полностью понимаю, что вы имеете в виду. Если это будет проблемой, не следует ли тогда Scanner#useDelimeter устареть? или что-то в документации хотя бы?   -  person George Z.    schedule 08.03.2019
comment
Это не проблема с useDelimiter. Мой комментарий был просто общим предупреждением о возрасте статьи.   -  person MC Emperor    schedule 08.03.2019
comment
@MCEmperor Вы уверены? i.imgur.com/gZQyDpl.png   -  person George Z.    schedule 08.03.2019
comment
Ну, я должен был сказать, что должно не быть проблемой с useDelimiter. Но я не мог воспроизвести его, так как не использую Eclipse. Я подозреваю, однако, что вызов useLocale вместо useDelimiter выдает предупреждение таким же образом.   -  person MC Emperor    schedule 08.03.2019


Ответы (1)


На самом деле проблема связана с useDelimiter(), поскольку следующий код не имеет такой проблемы и должен давать тот же результат:

public static String readFileFromResources(String fileName) throws IOException {
    try (Scanner sc = new Scanner(new ClassPathResource(fileName).getInputStream())) {
        sc.useDelimiter("\\A");
        return sc.next();
    }
}

Я не уверен, что именно вызывает утечку ресурсов, но я считаю, что это цепочка команд, которую вы использовали

person XtremeBaumer    schedule 08.03.2019
comment
Эх... Это то, чего я не пробовал. Да, это заставит его исчезнуть. Спасибо. - person George Z.; 08.03.2019