Вопрос-ответ

getResourceAsStream() vs FileInputStream

getResourceAsStream() против FileInputStream

Я пытался загрузить файл в веб-приложение, и я получал 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());

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

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

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

Смотреть также:

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

java