it-swarm.com.de

getResourceAsStream () vs FileInputStream

Ich habe versucht, eine Datei in eine Webanwendung zu laden, und bekam eine FileNotFound-Ausnahme, als ich FileInputStream verwendete. Unter Verwendung des gleichen Pfades konnte ich die Datei jedoch laden, wenn ich getResourceAsStream() verwendete. Was ist der Unterschied zwischen den beiden Methoden und warum funktioniert eine Methode, während die andere nicht funktioniert?

166
Vivin Paliath

Das Java.io.File und Konsortium wirkt auf das lokale Festplattendateisystem. Die Hauptursache für Ihr Problem ist, dass die Pfade von relative in Java.io vom aktuellen Arbeitsverzeichnis abhängig sind. D.h. das Verzeichnis, von dem aus die JVM (in Ihrem Fall: die des Webservers) gestartet wird. Dies kann zum Beispiel C:\Tomcat\bin oder etwas völlig anderes sein, aber somit nichtC:\Tomcat\webapps\contextname oder was auch immer Sie erwarten. In einem normalen Eclipse-Projekt wäre das C:\Eclipse\workspace\projectname. Sie können das aktuelle Arbeitsverzeichnis auf folgende Weise lernen:

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

Das Arbeitsverzeichnis ist jedoch in keiner Weise programmgesteuert steuerbar. Sie sollten statt der relativen Pfade wirklich absolute - Pfade in der File-API verwenden. Z.B. C:\full\path\to\file.ext

Sie möchten den absoluten Pfad in Java (Web) -Anwendungen nicht hardcodieren oder erraten. Das ist nur ein Problem mit der Portabilität (d. H. Es läuft in System X, aber nicht in System Y). Normalerweise wird diese Art von Ressourcen im classpath abgelegt oder der Klassenpfad wird vollständig hinzugefügt (in einem IDE wie Eclipse ist dies der Ordner src und der "build-Pfad"). Auf diese Weise können Sie sie mit Hilfe der ClassLoader durch ClassLoader#getResource() oder ClassLoader#getResourceAsStream() greifen. Es ist in der Lage, Dateien relativ zum "Stamm" des Klassenpfads zu finden, wie Sie durch Zufall herausgefunden haben. In Webapplikationen (oder einer anderen Anwendung, die mehrere Classloader verwendet) wird empfohlen, die ClassLoader, wie von Thread.currentThread().getContextClassLoader() zurückgegeben, zu verwenden, damit Sie auch außerhalb des webapp-Kontexts nachschauen können.

Eine weitere Alternative in Webapps ist das ServletContext#getResource() und sein Gegenstück ServletContext#getResourceAsStream() . Es kann auf Dateien zugreifen, die sich im öffentlichen web-Ordner des webapp-Projekts befinden, einschließlich des /WEB-INF-Ordners. Die ServletContext steht in Servlets über die geerbte Methode getServletContext() zur Verfügung. Sie können sie unverändert aufrufen. 

Siehe auch:

251
BalusC

getResourceAsStream ist der richtige Weg für Web-Apps (wie Sie es bereits gelernt haben).

Der Grund ist, dass das Lesen aus dem Dateisystem nicht funktioniert, wenn Sie Ihre Web-App in einem WAR packen. Dies ist der richtige Weg, um eine Web-App zu verpacken. Es ist auf diese Weise portabel, da Sie nicht auf einen absoluten Dateipfad oder den Speicherort Ihres App-Servers angewiesen sind.

26
duffymo

FileInputStream lädt den Dateipfad, den Sie dem Konstruktor als relativ übergeben, aus dem Arbeitsverzeichnis des Java-Prozesses. Normalerweise ist dies in einem Webcontainer etwa der Ordner bin.

getResourceAsStream() lädt einen Dateipfad relativ aus dem Klassenpfad Ihrer Anwendung .

13
matt b

Die FileInputStream-Klasse arbeitet direkt mit dem zugrunde liegenden Dateisystem zusammen. Wenn die betreffende Datei dort nicht physisch vorhanden ist, kann sie nicht geöffnet werden. Die getResourceAsStream()-Methode funktioniert anders. Es versucht, die Ressource mithilfe der Variablen ClassLoader der Klasse, in der sie aufgerufen wird, zu finden und zu laden. Auf diese Weise kann er beispielsweise Ressourcen finden, die in jar-Dateien eingebettet sind.

12
Dirk

classname.getResourceAsStream () lädt eine Datei über den Classloader von classname. Wenn die Klasse aus einer JAR-Datei stammt, wird die Ressource von dort geladen.

FileInputStream wird verwendet, um eine Datei aus dem Dateisystem zu lesen.

6
Lachlan Roche

Ich bin hier, indem ich beide Verwendungen trenne, indem ich sie als File Read (Java.io) und Resource Read (ClassLoader.getResourceAsStream ()) markiere.

Datei lesen - 1. Funktioniert auf dem lokalen Dateisystem. 2. Versucht, die aus dem aktuellen JVM-Startverzeichnis angeforderte Datei als root .__ zu finden. Im Idealfall gut, wenn Sie Dateien zur Verarbeitung an einem zuvor festgelegten Ort verwenden, z. B./dev/files oder C:\Data.

Ressourcen lesen - 1. Funktioniert mit Klassenpfad 2. Versucht, die Datei/Ressource im aktuellen oder übergeordneten Classloader-Klassenpfad zu lokalisieren. 3. Im Idealfall gut, wenn Sie versuchen, Dateien aus gepackten Dateien wie Krieg oder Glas zu laden.

0
Aditya Bhuyan