Existe uma API para obter um recurso de caminho de classe (por exemplo, o que eu obteria Class.getResource(String)
) como um java.nio.file.Path
? Idealmente, eu gostaria de usar as novas Path
APIs sofisticadas com recursos de caminho de classe.
143
Paths.get(URI)
, então, 'URL.toURI (), and last
getResource () `, que retorna aURL
. Você poderá encadear essas pessoas. Ainda não tentei.Respostas:
Este funciona para mim:
fonte
Thread.currentThread().getContextClassLoader().getResource(resourceName).toURI()
Supondo que o que você deseja fazer é chamar Files.lines (...) em um recurso que vem do caminho de classe - possivelmente de dentro de um jar.
Como o Oracle complicou a noção de quando um Path é um Path, não fazendo com que getResource retorne um caminho utilizável se ele residir em um arquivo jar, o que você precisa fazer é algo como isto:
fonte
class.getResource
requer uma barra, masgetSystemResourceAsStream
não consigo encontrar o arquivo quando prefixado com uma barra.A solução mais geral é a seguinte:
O principal obstáculo é lidar com as duas possibilidades: ter um sistema de arquivos existente que devemos usar, mas não fechar (como
file
URIs ou o armazenamento do módulo do Java 9), ou ter que abrir e fechar com segurança o sistema de arquivos (como arquivos zip / jar).Portanto, a solução acima encapsula a ação real em um
interface
, lida com os dois casos, fechando com segurança depois no segundo caso e funciona do Java 7 ao Java 10. Ele investiga se já existe um sistema de arquivos aberto antes de abrir um novo, portanto também funciona no caso de outro componente do seu aplicativo já ter aberto um sistema de arquivos para o mesmo arquivo zip / jar.Pode ser usado em todas as versões Java mencionadas acima, por exemplo, para listar o conteúdo de um pacote (
java.lang
no exemplo) comoPath
s, desta forma:Com o Java 8 ou mais recente, você pode usar expressões lambda ou referências a métodos para representar a ação real, por exemplo
para fazer o mesmo.
A versão final do sistema de módulos do Java 9 quebrou o exemplo de código acima. O JRE inconsistentemente retorna o caminho
/java.base/java/lang/Object.class
para oObject.class.getResource("Object.class")
que deveria ser/modules/java.base/java/lang/Object.class
. Isso pode ser corrigido acrescentando a falta/modules/
quando o caminho pai é relatado como inexistente:Em seguida, ele funcionará novamente com todas as versões e métodos de armazenamento.
fonte
Acontece que você pode fazer isso, com a ajuda do provedor interno do Zip File System . No entanto, passar um URI de recurso diretamente para
Paths.get
não funcionará; em vez disso, é necessário primeiro criar um sistema de arquivos zip para o URI do jar sem o nome da entrada e, em seguida, consultar a entrada nesse sistema de arquivos:Atualizar:
Foi corretamente apontado que o código acima contém um vazamento de recursos, pois o código abre um novo objeto FileSystem, mas nunca o fecha. A melhor abordagem é passar um objeto de trabalho semelhante ao consumidor, como a resposta de Holger faz. Abra o ZipFS FileSystem apenas o tempo suficiente para o trabalhador fazer o que for necessário com o Path (desde que o trabalhador não tente armazenar o objeto Path para uso posterior) e feche o FileSystem.
fonte
newFileSystem
pode levar a vários recursos abertos para sempre. Embora o adendo @raisercostin evite o erro ao tentar criar um sistema de arquivos já criado, se você tentar usar o retornadoPath
, receberá umClosedFileSystemException
. Resposta @Holger funciona bem para mim.FileSystem
. Se você carregar um recurso de um Jar e criar o necessárioFileSystem
- oFileSystem
também permitirá que você carregue outros recursos do mesmo Jar. Além disso, depois de criar o novo,FileSystem
você pode apenas tentar carregar o recurso novamente usandoPaths.get(Path)
e a implementação usará automaticamente o novoFileSystem
.#getPath(String)
método noFileSystem
objeto.Eu escrevi um pequeno método auxiliar para ler
Paths
os recursos da sua classe. É bastante útil, pois só precisa de uma referência da classe em que você armazenou seus recursos, bem como do nome do próprio recurso.fonte
Você não pode criar URI a partir de recursos dentro do arquivo jar. Você pode simplesmente gravá-lo no arquivo temporário e usá-lo (java8):
fonte
Leia um arquivo da pasta de recursos usando o NIO, em java8
fonte
Você precisa definir o sistema de arquivos para ler o recurso do arquivo jar, conforme mencionado em https://docs.oracle.com/javase/8/docs/technotes/guides/io/fsp/zipfilesystemprovider.html . Tenho sucesso ao ler o recurso do arquivo jar com os códigos abaixo:
fonte