Como ler um arquivo do jar em Java?

Eu quero ler um arquivo XML que está localizado dentro de um dos jar s incluídos no meu caminho de class. Como posso ler qualquer arquivo incluído no jar ?

Se você quiser ler esse arquivo de dentro do seu aplicativo, use:

 InputStream input = getClass().getResourceAsStream("/classpath/to/my/file"); 

O caminho começa com “/”, mas esse não é o caminho no seu sistema de arquivos, mas no seu classpath. Portanto, se o seu arquivo estiver no classpath “org.xml” e for chamado myxml.xml, seu caminho será exibido como “/org/xml/myxml.xml”.

O InputStream lê o conteúdo do seu arquivo. Você pode envolvê-lo em um Reader, se quiser.

Espero que isso ajude.

Ah, esse é um dos meus assuntos favoritos. Existem basicamente duas maneiras de carregar um recurso por meio do caminho de class:

 Class.getResourceAsStream(resource) 

e

 ClassLoader.getResourceAsStream(resource) 

(existem outras maneiras que envolvem a obtenção de um URL para o recurso de forma semelhante, em seguida, abrir uma conexão com ele, mas estas são as duas maneiras diretas).

O primeiro método realmente delega no segundo, depois de manchar o nome do recurso. Existem basicamente dois tipos de nomes de resources: absoluto (por exemplo, “/ caminho / para / recurso / recurso”) e relativo (por exemplo, “recurso”). Caminhos absolutos começam com “/”.

Aqui está um exemplo que deve ilustrar. Considere uma class com.example.A. Considere dois resources, um localizado em / com / example / nested, o outro em / top, no caminho de class. O programa a seguir mostra nove maneiras possíveis de acessar os dois resources:

 pacote com.example;

 class pública A {

     public static void main (args de seqüência de caracteres []) {

         // Class.getResourceAsStream
         Recurso do object = A.class.getResourceAsStream ("nested");
         System.out.println ("1: A.class nested =" + recurso);

         resource = A.class.getResourceAsStream ("/ com / example / nested");
         System.out.println ("2: A.class / com / example / nested =" + resource);

         resource = A.class.getResourceAsStream ("top");
         System.out.println ("3: A.class top =" + recurso);

         resource = A.class.getResourceAsStream ("/ top");
         System.out.println ("4: A.class / top =" + recurso);

         // ClassLoader.getResourceAsStream
         ClassLoader cl = A.class.getClassLoader ();
         resource = cl.getResourceAsStream ("nested");        
         System.out.println ("5: cl nested =" + recurso);

         resource = cl.getResourceAsStream ("/ com / example / nested");
         System.out.println ("6: cl / com / example / nested =" + recurso);
         resource = cl.getResourceAsStream ("com / example / nested");
         System.out.println ("7: cl com / example / nested =" + recurso);

         resource = cl.getResourceAsStream ("top");
         System.out.println ("8: cl top =" + recurso);

         resource = cl.getResourceAsStream ("/ top");
         System.out.println ("9: cl / top =" + recurso);
     }

 }

A saída do programa é:

 1: A.class nested=java.io.BufferedInputStream@19821f
 2: A.class /com/example/nested=java.io.BufferedInputStream@addbf1
 3: A.class top = null
 4: A.class /top=java.io.BufferedInputStream@42e816
 5: cl aninhada = null
 6: cl / com / example / nested = null
 7: cl com/example/nested=java.io.BufferedInputStream@9304b1
 8: cl top=java.io.BufferedInputStream@190d11
 9: cl / top = nulo

Principalmente as coisas fazem o que você esperaria. O caso 3 falha porque a resolução relativa da class é em relação à class, portanto, “top” significa “/ com / example / top”, mas “/ top” significa o que ela diz.

O caso 5 falha porque a resolução relativa do carregador de class está relacionada ao carregador de class. Mas, inesperadamente, o Case-6 também falha: pode-se esperar que “/ com / example / nested” seja resolvido corretamente. Para acessar um recurso nested através do carregador de class, você precisa usar o Case-7, ou seja, o caminho nested é relativo à raiz do carregador de class. Da mesma forma, o caso 9 falha, mas o caso 8 passa.

Lembre-se: para java.lang.Class, getResourceAsStream () é delegado para o classloader:

      public InputStream getResourceAsStream (String name) {
         name = resolveName (nome);
         ClassLoader cl = getClassLoader0 ();
         if (cl == null) {
             // Uma class de sistema.
             return ClassLoader.getSystemResourceAsStream (name);
         }
         return cl.getResourceAsStream (nome);
     }

então é o comportamento de resolveName () que é importante.

Por fim, como o comportamento do carregador de class que carregou a class controla essencialmente o getResourceAsStream () e o carregador de class costuma ser um carregador personalizado, as regras de carregamento de resources podem ser ainda mais complexas. por exemplo, para aplicativos da Web, carregue a partir de WEB-INF / classs ou WEB-INF / lib no contexto do aplicativo da Web, mas não de outros aplicativos da Web isolados. Além disso, os carregadores de classs bem comportados delegam aos pais, para que os resources duplicados no caminho de class não sejam acessíveis usando esse mecanismo.

Verifique primeiro o seu carregador de classs.

 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = Class.class.getClassLoader(); } classLoader.getResourceAsStream("xmlFileNameInJarFile.xml"); // xml file location at xxx.jar // + folder // + folder // xmlFileNameInJarFile.xml 

Um JAR é basicamente um arquivo ZIP, então trate-o como tal. Abaixo, há um exemplo de como extrair um arquivo de um arquivo WAR (também tratá-lo como um arquivo ZIP) e gerar o conteúdo da string. Para o binário, você precisará modificar o processo de extração, mas há muitos exemplos para isso.

 public static void main(String args[]) { String relativeFilePath = "style/someCSSFile.css"; String zipFilePath = "/someDirectory/someWarFile.war"; String contents = readZipFile(zipFilePath,relativeFilePath); System.out.println(contents); } public static String readZipFile(String zipFilePath, String relativeFilePath) { try { ZipFile zipFile = new ZipFile(zipFilePath); Enumeration< ? extends ZipEntry> e = zipFile.entries(); while (e.hasMoreElements()) { ZipEntry entry = (ZipEntry) e.nextElement(); // if the entry is not directory and matches relative file then extract it if (!entry.isDirectory() && entry.getName().equals(relativeFilePath)) { BufferedInputStream bis = new BufferedInputStream( zipFile.getInputStream(entry)); // Read the file // With Apache Commons I/O String fileContentsStr = IOUtils.toString(bis, "UTF-8"); // With Guava //String fileContentsStr = new String(ByteStreams.toByteArray(bis),Charsets.UTF_8); // close the input stream. bis.close(); return fileContentsStr; } else { continue; } } } catch (IOException e) { logger.error("IOError :" + e); e.printStackTrace(); } return null; } 

Neste exemplo, estou usando o I / O do Apache Commons e, se você estiver usando o Maven, aqui está a dependência:

  commons-io commons-io 2.4  

Apenas por completo, recentemente houve uma pergunta na lista de discussão do Jython, onde uma das respostas se referia a este tópico.

A questão era como chamar um script Python contido em um arquivo .jar de dentro do Jython, a resposta sugerida é a seguinte (com “InputStream” como explicado em uma das respostas acima:

 PythonInterpreter.execfile(InputStream)