web-dev-qa-db-fra.com

getResourceAsStream () vs FileInputStream

J'essayais de charger un fichier dans une application Web et j'avais une exception FileNotFound lorsque j'utilisais FileInputStream. Cependant, en utilisant le même chemin, j’ai pu charger le fichier quand j’ai fait getResourceAsStream(). Quelle est la différence entre les deux méthodes et pourquoi l’une fonctionne-t-elle alors que l’autre ne fonctionne pas?

166
Vivin Paliath

Le Java.io.File et consorts agit sur le système de fichiers du disque local. La cause première de votre problème est que les relatifs chemins dans Java.io dépendent du répertoire de travail en cours. C'est à dire. le répertoire à partir duquel la machine virtuelle Java (dans votre cas: celle du serveur Web) est démarrée. Ceci peut par exemple être C:\Tomcat\bin ou quelque chose de complètement différent, mais donc pasC:\Tomcat\webapps\contextname ou quoi que vous pensiez. Dans un projet Eclipse normal, ce serait C:\Eclipse\workspace\projectname. Vous pouvez en savoir plus sur le répertoire de travail actuel de la manière suivante:

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

Cependant, le répertoire de travail n'est en aucun cas contrôlable par programme. Vous devriez vraiment préférer utiliser les chemins absolus dans l'API File aux chemins relatifs. Par exemple. C:\full\path\to\file.ext

Vous ne voulez pas coder en dur ni deviner le chemin absolu dans les applications Java (Web). Ce n’est qu’un problème de portabilité (c’est-à-dire qu’il fonctionne dans le système X mais pas dans le système Y). La pratique normale consiste à placer ce type de ressources dans classpath ou à ajouter son chemin complet au classpath (dans un IDE comme Eclipse qui correspond respectivement au dossier src et au "chemin de génération"). De cette façon, vous pouvez les récupérer avec la variable ClassLoader de ClassLoader#getResource() ou ClassLoader#getResourceAsStream() . Il est capable de localiser les fichiers par rapport à la "racine" du chemin de classe, comme vous l'avez découvert par hasard. Dans les applications Web (ou dans toute autre application utilisant plusieurs chargeurs de classe), il est recommandé d'utiliser la variable ClassLoader renvoyée par Thread.currentThread().getContextClassLoader() pour que vous puissiez également "regarder" en dehors du contexte de l'application Web.

Une autre alternative dans les applications Web est la ServletContext#getResource() et son homologue ServletContext#getResourceAsStream() . Il est capable d'accéder aux fichiers situés dans le dossier public web du projet webapp, y compris le dossier /WEB-INF. La ServletContext est disponible dans les servlets par la méthode getServletContext() héritée, vous pouvez l'appeler telle quelle. 

Voir également:

251
BalusC

getResourceAsStream est la bonne façon de procéder pour les applications Web (comme vous l'avez déjà appris).

La raison en est que la lecture du système de fichiers ne peut pas fonctionner si vous empaquetez votre application Web dans un fichier WAR. C’est la bonne façon de conditionner une application Web. C'est portable, car vous ne dépendez pas d'un chemin de fichier absolu ni de l'emplacement où votre serveur d'applications est installé.

26
duffymo

FileInputStream chargera le chemin de fichier que vous transmettez au constructeur sous forme relative à partir du répertoire de travail du processus Java. Généralement, dans un conteneur Web, il s’agit du dossier bin.

getResourceAsStream() chargera un chemin de fichier relatif à partir du chemin de classe de votre application .

13
matt b

La classe FileInputStream fonctionne directement avec le système de fichiers sous-jacent. Si le fichier en question n'y est pas physiquement présent, il ne pourra pas être ouvert. La méthode getResourceAsStream() fonctionne différemment. Il tente de localiser et de charger la ressource à l'aide de la variable ClassLoader de la classe à laquelle elle est appelée. Cela lui permet de rechercher, par exemple, des ressources incorporées dans des fichiers jar.

12
Dirk

classname.getResourceAsStream () charge un fichier via le chargeur de classe de classname. Si la classe provient d'un fichier jar, la ressource sera chargée à partir de là.

FileInputStream est utilisé pour lire un fichier à partir du système de fichiers.

6
Lachlan Roche

Je suis ici en séparant les deux utilisations en les marquant comme Lecture de fichier (Java.io) et Lecture de ressource (ClassLoader.getResourceAsStream ()).

Fichier lu - 1. Fonctionne sur le système de fichiers local. 2. Essaie de localiser le fichier demandé à partir du répertoire actuel de la machine virtuelle Java lancé en tant que racine 3. Idéalement utile lorsque vous utilisez des fichiers à traiter dans un emplacement prédéterminé, tel que/dev/files ou C:\Data.

Lecture de ressources - 1. Fonctionne sur le chemin de classe 2. Essaie de localiser le fichier/la ressource dans le chemin d'accès aux classes du chargeur de classe actuel ou parent. 3. Idéalement bon pour essayer de charger des fichiers à partir de fichiers tels que war ou jar.

0
Aditya Bhuyan