Eu tenho este código que lê todos os arquivos de um diretório.
File textFolder = new File("text_directory");
File [] texFiles = textFolder.listFiles( new FileFilter() {
public boolean accept( File file ) {
return file.getName().endsWith(".txt");
}
});
Funciona muito bem. Ele preenche o array com todos os arquivos que terminam com ".txt" do diretório "text_directory".
Como posso ler o conteúdo de um diretório de maneira semelhante em um arquivo JAR?
Então, o que eu realmente quero fazer é listar todas as imagens dentro do meu arquivo JAR, para que possa carregá-las com:
ImageIO.read(this.getClass().getResource("CompanyLogo.png"));
(Esse funciona porque o "CompanyLogo" é "codificado", mas o número de imagens dentro do arquivo JAR pode ser de 10 a 200 de comprimento variável.)
EDITAR
Portanto, acho que meu principal problema seria: Como saber o nome do arquivo JAR onde mora minha classe principal?
Admito que eu poderia ler usando java.util.Zip
.
Minha estrutura é assim:
Eles são como:
my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest
No momento, consigo carregar, por exemplo, "images / image01.png" usando:
ImageIO.read(this.getClass().getResource("images/image01.png));
Mas só porque sei o nome do arquivo, quanto ao resto, tenho que carregá-los dinamicamente.
Respostas:
Observe que no Java 7, você pode criar um a
FileSystem
partir do arquivo JAR (zip) e, em seguida, usar os mecanismos de filtragem e navegação de diretório do NIO para pesquisá-lo. Isso tornaria mais fácil escrever código que lida com JARs e diretórios "explodidos".fonte
Código que funciona para arquivos IDE e .jar:
fonte
FileSystems.newFileSystem()
recebe umMap<String, ?>
, então você precisa especificar paraCollections.emptyMap()
que ele precisa retornar um com o tipo adequado. Isso funciona:Collections.<String, Object>emptyMap()
.fileSystem
!walk
método emFiles
só está disponível em 1.8). O único problema é que o diretório de recursos aparece noFiles.walk(myPath, 1)
, não apenas os arquivos. Eu acho que o primeiro elemento pode ser simplesmente ignoradomyPath = fileSystem.getPath("/resources");
não funciona para mim; não encontra nada. Deveria ser "imagens" no meu caso e o diretório "imagens" definitivamente está incluído no meu jar!resposta de Erickson funcionou perfeitamente:
Aqui está o código de trabalho.
E acabei de modificar meu método de carregamento a partir deste:
Para isso:
fonte
Gostaria de expandir a resposta de acheron55 , uma vez que é uma solução muito insegura , por vários motivos:
FileSystem
objeto.FileSystem
objeto já existe.Esta é uma solução um tanto mais segura:
Não há necessidade real de sincronizar sobre o nome do arquivo; pode-se simplesmente sincronizar no mesmo objeto todas as vezes (ou fazer o método
synchronized
), é puramente uma otimização.Eu diria que esta ainda é uma solução problemática, uma vez que pode haver outras partes do código que usam a
FileSystem
interface sobre os mesmos arquivos, e isso pode interferir neles (mesmo em um único aplicativo threaded).Além disso, ele não verifica se há
null
s (por exemplo, emgetClass().getResource()
.Essa interface Java NIO em particular é horrível, pois apresenta um recurso global / singleton não seguro para thread e sua documentação é extremamente vaga (muitas incógnitas devido a implementações específicas do provedor). Os resultados podem variar para outros
FileSystem
provedores (não JAR). Talvez haja uma boa razão para ser assim; Não sei, não pesquisei as implementações.fonte
Supondo que seu projeto esteja empacotado em um Jar (não necessariamente verdadeiro!), Você pode usar ClassLoader.getResource () ou findResource () com o nome da classe (seguido por .class) para obter o jar que contém uma determinada classe. Você terá que analisar o nome do jar do URL que é retornado (não é tão difícil), que deixarei como um exercício para o leitor :-)
Certifique-se de testar o caso em que a classe não faz parte de um jar.
fonte
CodeSource
.Eu transferi a resposta de acheron55 para Java 7 e fechei o
FileSystem
objeto. Este código funciona em IDE, em arquivos jar e em um jar dentro de uma guerra no Tomcat 7; mas note que não funciona em um jar dentro de uma guerra no JBoss 7 (dáFileSystemNotFoundException: Provider "vfs" not installed
, veja também este post ). Além disso, como o código original, não é seguro para threads, como sugerido por errr . Por essas razões, abandonei essa solução; no entanto, se você pode aceitar esses problemas, aqui está meu código pronto:fonte
Aqui está um método que escrevi para "executar todos os JUnits em um pacote". Você deve ser capaz de adaptá-lo às suas necessidades.
Edit: Ah, nesse caso, você pode querer este snippet também (mesmo caso de uso :))
fonte
Aqui está um exemplo de uso da biblioteca Reflections para escanear recursivamente classpath por padrão de nome regex aumentado com algumas vantagens Guava para buscar conteúdos de recursos:
Isso funciona com potes e classes explodidas.
fonte
Um arquivo jar é apenas um arquivo zip com um manifesto estruturado. Você pode abrir o arquivo jar com as ferramentas java zip usuais e escanear o conteúdo do arquivo dessa forma, inflar streams, etc. Em seguida, use isso em uma chamada getResourceAsStream, e deve ser tudo ótimo.
EDITAR / após esclarecimento
Levei um minuto para lembrar todos os pedaços e tenho certeza de que existem maneiras mais limpas de fazer isso, mas eu queria ver se não estava louco. No meu projeto, image.jpg é um arquivo em alguma parte do arquivo jar principal. Eu pego o carregador de classe da classe principal (SomeClass é o ponto de entrada) e o uso para descobrir o recurso image.jpg. Então, um pouco de magia de fluxo para colocá-lo nessa coisa ImageInputStream e está tudo bem.
fonte
new File("blah.JAR")
para criar um objeto File que representa o JAR, por exemplo. Basta substituir "blah.JAR" pelo nome do seu JAR.Dado um arquivo JAR real, você pode listar o conteúdo usando
JarFile.entries()
. No entanto, você precisará saber a localização do arquivo JAR - você não pode simplesmente pedir ao carregador de classe para listar tudo o que ele pode encontrar.Você deve conseguir descobrir a localização do arquivo JAR com base na URL de onde retornou
ThisClassName.class.getResource("ThisClassName.class")
, mas pode ser um pouco complicado.fonte
new File("baz.jar)
, o objeto File representaria seu arquivo JAR.Há algum tempo, criei uma função que obtém classes de dentro do JAR:
fonte
fonte
Existem dois utilitários muito úteis, ambos chamados JarScan:
www.inetfeedback.com/jarscan
jarscan.dev.java.net
Veja também esta pergunta: JarScan, escaneie todos os arquivos JAR em todas as subpastas para uma classe específica
fonte
O mecanismo mais robusto para listar todos os recursos no caminho de classe atualmente é usar esse padrão com ClassGraph , porque ele lida com a maior variedade possível de mecanismos de especificação de caminho de classe , incluindo o novo sistema de módulo JPMS. (Eu sou o autor de ClassGraph.)
Existem muitas outras maneiras de lidar com recursos também.
fonte
Apenas uma maneira diferente de listar / ler arquivos de uma URL jar e faz isso recursivamente para jars aninhados
https://gist.github.com/trung/2cd90faab7f75b3bcbaa
fonte
Mais um para a estrada:
Isso é um pouco mais flexível para combinar nomes de arquivos específicos porque usa globbing curinga.
Um estilo mais funcional:
fonte