getResourceAsStream () по сравнению с FileInputStream

Я пытался загрузить файл в веб-приложении, и я получал a FileNotFound исключение, когда я использовал FileInputStream. Однако с помощью того же пути, я смог загрузить файл, когда я сделал getResourceAsStream(). Каково различие между этими двумя методами, и почему каждый работает, в то время как другой не делает?

168
задан Roman C 19 March 2016 в 08:54
поделиться

5 ответов

java.io.File и консорты действуют в файловой системе локального диска. Основная причина вашей проблемы в том, что относительные пути в java.io зависят от текущего рабочего каталога. Т.е. каталог, из которого запускается JVM (в вашем случае: веб-сервер). Это может быть, например, C: \ Tomcat \ bin или что-то совершенно другое, но, таким образом, не C: \ Tomcat \ webapps \ contextname или что-то еще, что вы ожидаете быть.В обычном проекте Eclipse это будет C: \ Eclipse \ workspace \ projectname . Вы можете узнать о текущем рабочем каталоге следующим образом:

System.out.println(new File(".").getAbsolutePath());

Однако рабочий каталог никоим образом не управляется программно. Вы действительно должны предпочесть использовать абсолютные пути в File API вместо относительных путей. Например. C: \ полный \ путь \ к \ file.ext .

Вы не хотите жестко кодировать или угадывать абсолютный путь в приложениях Java (веб). Это только проблема переносимости (т.е. он работает в системе X, но не в системе Y). Обычной практикой является размещение таких ресурсов в пути к классам или добавление их полного пути в путь к классам (в среде IDE, такой как Eclipse, это папка src и «путь сборки " соответственно). Таким образом, вы можете получить их с помощью ClassLoader с помощью ClassLoader # getResource () или ClassLoader # getResourceAsStream () . Как вы случайно поняли, он может располагать файлы относительно «корня» пути к классам. В веб-приложениях (или любых других приложениях, использующих несколько загрузчиков классов) рекомендуется использовать ClassLoader , возвращенный Thread.currentThread (). GetContextClassLoader () для этого, чтобы вы могли смотреть "вовне". "контекст веб-приложения.

Другой альтернативой в веб-приложениях является ServletContext # getResource () и его аналог ServletContext # getResourceAsStream () .Он может получить доступ к файлам, расположенным в общедоступной папке web проекта webapp, включая папку / WEB-INF . ServletContext доступен в сервлетах с помощью унаследованного метода getServletContext () , вы можете вызывать его как есть.

См. Также:

255
ответ дан 23 November 2019 в 20:55
поделиться

getResourceAsStream - правильный способ сделать это для веб-приложений (как вы уже узнали).

Причина в том, что чтение из файловой системы не может работать, если вы упаковываете свое веб-приложение в WAR. Это правильный способ упаковки веб-приложения. Таким образом, он переносится, потому что вы не зависите от абсолютного пути к файлу или места, где установлен ваш сервер приложений.

26
ответ дан 23 November 2019 в 20:55
поделиться

FileInputStream загрузит путь к файлу вы переходите к конструктору как относительный из рабочего каталога процесса Java. Обычно в веб-контейнере это что-то вроде папки bin .

getResourceAsStream () загрузит относительный путь к файлу из пути к классам вашего приложения .

13
ответ дан 23 November 2019 в 20:55
поделиться

Класс FileInputStream работает напрямую с базовой файловой системой. Если рассматриваемого файла там физически нет, он не сможет его открыть. Метод getResourceAsStream () работает иначе. Он пытается найти и загрузить ресурс, используя ClassLoader класса, для которого он вызван. Это позволяет ему находить, например, ресурсы, встроенные в файлы jar .

12
ответ дан 23 November 2019 в 20:55
поделиться

classname.getResourceAsStream() загружает файл через загрузчик класса classname. Если класс пришел из jar-файла, то ресурс будет загружен именно оттуда.

FileInputStream используется для чтения файла из файловой системы.

6
ответ дан 23 November 2019 в 20:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: