getResourceAsStream () против FileInputStream - PullRequest
168 голосов
/ 22 февраля 2010

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

Ответы [ 6 ]

253 голосов
/ 22 февраля 2010

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

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

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

26 голосов
/ 22 февраля 2010

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

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

13 голосов
/ 22 февраля 2010

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

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

12 голосов
/ 22 февраля 2010

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

6 голосов
/ 22 февраля 2010

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

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

0 голосов
/ 16 января 2019

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

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

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

...