getResourceAsStream () vs FileInputStream

Stavo cercando di caricare un file in una webapp e FileInputStream un’eccezione FileNotFound quando FileInputStream . Tuttavia, utilizzando lo stesso percorso, sono stato in grado di caricare il file quando ho fatto getResourceAsStream() . Qual è la differenza tra i due metodi e perché uno funziona mentre l’altro no?

java.io.File e consorts agiscono sul file system del disco locale. La causa principale del problema è che i percorsi relativi in java.io dipendono dalla directory di lavoro corrente. Cioè la directory da cui viene avviata la JVM (nel tuo caso: quella del server web). Questo può essere ad esempio C:\Tomcat\bin o qualcosa di completamente diverso, ma non C:\Tomcat\webapps\contextname o qualunque cosa ci si aspetterebbe che fosse. In un normale progetto Eclipse, sarebbe C:\Eclipse\workspace\projectname . Puoi conoscere la directory di lavoro corrente nel seguente modo:

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

Tuttavia, la directory di lavoro non è in alcun modo controllabile a livello di programmazione. Dovresti davvero preferire l’utilizzo di percorsi assoluti nell’API File anziché in percorsi relativi. Ad esempio C:\full\path\to\file.ext .

Non vuoi hardcode o indovinare il percorso assoluto nelle applicazioni Java (web). Questo è solo un problema di portabilità (cioè funziona nel sistema X, ma non nel sistema Y). La pratica normale è quella di posizionare quel tipo di risorse nel classpath , o di aggiungere il suo percorso completo al classpath (in un IDE come Eclipse che è rispettivamente la cartella src e il “percorso di build”). In questo modo è ansible afferrarli con l’aiuto di ClassLoader di ClassLoader#getResource() o ClassLoader#getResourceAsStream() . È in grado di individuare i file relativi alla “root” del classpath, come si è capito per coincidenza. Nelle applicazioni web (o in qualsiasi altra applicazione che utilizza più classloader) si consiglia di utilizzare ClassLoader come restituito da Thread.currentThread().getContextClassLoader() per questo in modo da poter guardare “al di fuori” anche del contesto webapp.

Un’altra alternativa in webapps è ServletContext#getResource() e la sua controparte ServletContext#getResourceAsStream() . È in grado di accedere ai file che si trovano nella cartella web pubblica del progetto webapp, inclusa la cartella /WEB-INF . ServletContext è disponibile nei servlet dal metodo getServletContext() ereditato, puoi chiamarlo così com’è.

Guarda anche:

  • Dove posizionare e come leggere i file di risorse di configurazione nell’applicazione basata su servlet?
  • Cosa significa servletcontext.getRealPath (“/”) e quando dovrei usarlo
  • Modo consigliato per salvare i file caricati in un’applicazione servlet
  • Come salvare temporaneamente il file generato nell’applicazione web basata su servlet

getResourceAsStream è il modo giusto per farlo per le app Web (come hai già imparato).

Il motivo è che la lettura dal file system non può funzionare se impacchettate la vostra app Web in un WAR. Questo è il modo corretto di confezionare un’applicazione web. È portatile in questo modo, perché non si dipende da un percorso file assoluto o dalla posizione in cui è installato il server delle app.

FileInputStream carica il percorso del file passato al costruttore come relativo dalla directory di lavoro del processo Java. Di solito in un contenitore web, questo è qualcosa come la cartella bin .

getResourceAsStream() caricherà un percorso relativo al file dal percorso di class dell’applicazione .

La class FileInputStream funziona direttamente con il file system sottostante. Se il file in questione non è presente fisicamente, non riuscirà ad aprirlo. Il metodo getResourceAsStream() funziona in modo diverso. Prova a individuare e caricare la risorsa utilizzando ClassLoader della class su cui è chiamato. Ciò consente di trovare, ad esempio, risorse incorporate in file jar .

classname.getResourceAsStream () carica un file tramite il classloader di classname. Se la class proviene da un file jar, è da qui che verrà caricata la risorsa.

FileInputStream è usato per leggere un file dal filesystem.