GetResourceAsStream() vs FileInputStream

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

Ответы

Ответ 1

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

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

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

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

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

См. также:

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

Я здесь, разделяя оба использования, помечая их как "Чтение файла" (java.io) и "Чтение ресурса" (ClassLoader.getResourceAsStream()).

Чтение файлов - 1. Работает в локальной файловой системе. 2. Пытается найти файл, запрошенный из текущей запущенной директории JVM, как root 3. Идеально подходит для использования файлов для обработки в заранее определенном месте, например, /dev/files или C:\Data.

Чтение ресурса - 1. Работает на пути к классу 2. Пытается найти файл/ресурс в текущем или родительском пути к загрузчику классов. 3. Идеально подходит для загрузки файлов из упакованных файлов, таких как war или jar.