Como criar um novo java.io.File na memória?

98

Como posso criar novo File(de java.io) na memória, não no disco rígido?

Estou usando a linguagem Java. Não quero salvar o arquivo no disco rígido.

Estou diante de uma API ruim ( java.util.jar.JarFile). Ele está esperando File filede String filename. Não tenho nenhum arquivo (apenas byte[]conteúdo) e posso criar um arquivo temporário, mas não é uma solução bonita. Preciso validar o resumo de um frasco assinado.

byte[] content = getContent();
File tempFile = File.createTempFile("tmp", ".tmp");
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(archiveContent);
JarFile jarFile = new JarFile(tempFile);
Manifest manifest = jarFile.getManifest();

Todos os exemplos de como obter o manifesto sem criar um arquivo temporário serão bem-vindos.

ggorlen
fonte
8
Então você quer apenas bytes na memória?
Sotirios Delimanolis
6
O que você está tentando fazer com isso File?
Jon Skeet
5
A, Filepor definição, está no disco rígido.
Uwe Plonus
3
de que adianta criar um arquivo se você não o quer na memória persistente?
Bhavik Shah
7
Uau, a falta de imaginação no StackOverflow é espantosa. Alguém pode precisar de um arquivo simples na memória porque está usando uma interface que requer um arquivo. A interface deveria ter sido escrita para um InputStream, mas não foi. Um arquivo temporário parece um exagero, portanto, um java.io.File na memória seria preferível.
Novaterata de

Respostas:

30

Para escrever em um fluxo, na memória, use:

new ByteArrayOutputStream();
haraldK
fonte
5
Isso não responde à pergunta, pois ByteArrayOutputStream não pode ser usado com uma interface que requer um objeto de arquivo.
FableBlaze
1
@FableBlaze Bem, a resposta à pergunta então, é “não é possível”. Essa resposta tenta ser pragmática e dizer o que o usuário poderia fazer. A resposta de Andreas é claramente mais completa e uma melhor (tentativa de) resposta.
haraldK
"Não é possível" seria uma resposta válida em minha opinião. No entanto, acho que um sistema de arquivos em memória (mencionado nos comentários da resposta de Andreas) também poderia ser mencionado, porque se você não consegue por algum motivo gravar no disco rígido, então isso pode ser uma maneira de contornar isso.
FableBlaze
80

Como posso criar um novo arquivo (de java.io) na memória, não no disco rígido?

Talvez você esteja confuso Filee Stream:

  • A Fileé uma representação abstrata de nomes de caminho de arquivo e diretório . Usando um Fileobjeto, você pode acessar os metadados do arquivo em um sistema de arquivos e realizar algumas operações nos arquivos desse sistema, como excluir ou criar o arquivo. Mas a Fileclasse não fornece métodos para ler e gravar o conteúdo do arquivo.
  • Para ler e escrever a partir de um arquivo, você está usando um Streamobjeto, como FileInputStreamou FileOutputStream. Esses fluxos podem ser criados a partir de um Fileobjeto e, em seguida, usados ​​para ler e gravar no arquivo.

Você pode criar um fluxo baseado em um buffer de bytes que reside na memória , usando ae ByteArrayInputStreama ByteArrayOutputStreampara ler e gravar em um buffer de bytes de maneira semelhante à leitura e gravação de um arquivo. A bytematriz contém o conteúdo do "Arquivo". Você não precisa de um Fileobjeto então.

Tanto o File...e os ByteArray...fluxos de herdar java.io.OutputStreame java.io.InputStream, respectivamente, de modo que você pode usar a superclasse comum para esconder se você está lendo a partir de um arquivo ou de uma matriz de bytes.

Andreas Fester
fonte
95
Não tenho certeza se isso é o que o autor do pôster original queria, mas um exemplo de quando um "Arquivo na memória" seria útil é quando você deseja reutilizar uma biblioteca existente que precisa de um java.io.File como parâmetro de entrada, mas você realmente deseja usar "arquivos" armazenados na memória. Nesse caso, acho que uma solução seria usar o Apache Commons VFS para instanciar um DefaultFileSystemManager e usá-lo para criar um RamFileProvider. Eu teria acrescentado isso como uma resposta adequada (mais completa), mas parece que esta questão foi encerrada há algum tempo ...
Sorin Postelnicu
2
1 Eu estava procurando por esse tipo de solução, para testar a unidade vindo do componente sem ter que usar um arquivo real
GClaramunt
3
Se você não quiser criar "um arquivo real", pode tentar criar um arquivo temporário. Veja createTempFilepara java.io.file. Este arquivo pode ser definido para exclusão automática quando o teste de unidade termina.
Andrew-Dufresne de
2
Isso não responde à pergunta. Como @SorinPostelnicu bem disse, um "Arquivo" na memória é algo como um Sistema de arquivos na memória ou algo assim.
Felipe
1
Provavelmente soma o caso de uso do OP e um método valioso de redução da latência com E / S de disco caro do sistema.
Eddie B
3

Você pode usar um sistema de arquivos na memória, como Jimfs

Aqui está um exemplo de uso do readme:

FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
Path foo = fs.getPath("/foo");
Files.createDirectory(foo);

Path hello = foo.resolve("hello.txt"); // /foo/hello.txt
Files.write(hello, ImmutableList.of("hello world"), StandardCharsets.UTF_8);
Tedward
fonte