getResourceAsStream () vs FileInputStream

Eu estava tentando carregar um arquivo em um webapp, e eu estava recebendo uma exceção FileNotFound quando eu usei FileInputStream . No entanto, usando o mesmo caminho, consegui carregar o arquivo quando getResourceAsStream() . Qual é a diferença entre os dois methods e por que um funciona enquanto o outro não?

O java.io.File e consorts atua no sistema de arquivos do disco local. A causa raiz do seu problema é que os caminhos relativos em java.io são dependentes do diretório de trabalho atual. Ou seja, o diretório a partir do qual a JVM (no seu caso: o servidor da Web) é iniciado. Isso pode ser, por exemplo, C:\Tomcat\bin ou algo totalmente diferente, mas não C:\Tomcat\webapps\contextname ou o que você espera que seja. Em um projeto normal do Eclipse, seria C:\Eclipse\workspace\projectname . Você pode aprender sobre o diretório de trabalho atual da seguinte maneira:

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

No entanto, o diretório de trabalho não é de forma programável. Você deve realmente preferir usar caminhos absolutos na API de File vez de caminhos relativos. Por exemplo, C:\full\path\to\file.ext .

Você não quer codificar ou adivinhar o caminho absoluto em aplicativos Java (web). Isso é apenas um problema de portabilidade (ou seja, ele é executado no sistema X, mas não no sistema Y). A prática normal é colocar esses tipos de resources no classpath ou adicionar seu caminho completo ao caminho de class (em um IDE como o Eclipse, que é a pasta src e o “caminho de construção”, respectivamente). Dessa forma, você pode pegá-los com a ajuda do ClassLoader por ClassLoader#getResource() ou ClassLoader#getResourceAsStream() . É capaz de localizar arquivos relativos à “raiz” do caminho de class, como você descobriu por coincidência. Em aplicativos da web (ou qualquer outro aplicativo que use vários classloaders) é recomendável usar o ClassLoader conforme retornado por Thread.currentThread().getContextClassLoader() para isso, assim você pode procurar “fora” do contexto da webapp também.

Outra alternativa no webapps é o ServletContext#getResource() e sua contraparte ServletContext#getResourceAsStream() . É capaz de acessar arquivos localizados na pasta web pública do projeto webapp, incluindo a pasta /WEB-INF . O ServletContext está disponível em servlets pelo método herdado getServletContext() , você pode chamá-lo como está.

Veja também:

  • Onde colocar e como ler arquivos de resources de configuração no aplicativo baseado em servlet?
  • O que significa servletcontext.getRealPath (“/”) e quando devo usá-lo?
  • A maneira recomendada para salvar arquivos enviados em um aplicativo de servlet
  • Como salvar o arquivo gerado temporariamente no aplicativo da web baseado em servlet

getResourceAsStream é o caminho certo para fazer isso para aplicativos da web (como você já aprendeu).

O motivo é que a leitura do sistema de arquivos não funciona se você empacotar seu aplicativo da Web em um WAR. Essa é a maneira correta de empacotar um aplicativo da web. É portável dessa maneira, porque você não depende de um caminho de arquivo absoluto ou do local em que o servidor de aplicativos está instalado.

FileInputStream carregará o caminho do arquivo que você passa para o construtor como relativo a partir do diretório de trabalho do processo Java. Geralmente em um contêiner da web, isso é algo como a pasta bin .

getResourceAsStream() carregará um caminho de arquivo relativo do classpath do seu aplicativo .

A class FileInputStream trabalha diretamente com o sistema de arquivos subjacente. Se o arquivo em questão não estiver presente fisicamente, ele não conseguirá abri-lo. O método getResourceAsStream() funciona de maneira diferente. Ele tenta localizar e carregar o recurso usando o ClassLoader da class em que é chamado. Isso permite encontrar, por exemplo, resources incorporados em arquivos jar .

classname.getResourceAsStream () carrega um arquivo através do classloader de classname. Se a class veio de um arquivo jar, é de onde o recurso será carregado.

FileInputStream é usado para ler um arquivo do sistema de arquivos.