Comment créer un nouveau fichier java.io.File en mémoire?

98

Comment puis-je créer un nouveau File(à partir de java.io) en mémoire, pas sur le disque dur?

J'utilise le langage Java. Je ne veux pas enregistrer le fichier sur le disque dur.

Je suis confronté à une mauvaise API ( java.util.jar.JarFile). Il attend File filede String filename. Je n'ai pas de fichier (uniquement du byte[]contenu) et je peux créer un fichier temporaire, mais ce n'est pas une belle solution. Je dois valider le condensé d'un pot signé.

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();

Tout exemple sur la façon d'obtenir un manifeste sans créer de fichier temporaire serait apprécié.

Ggorlen
la source
8
Alors vous voulez juste des octets en mémoire?
Sotirios Delimanolis
6
Qu'essayez-vous de faire avec ça File?
Jon Skeet du
5
Un Filepar définition est sur le disque dur.
Uwe Plonus
3
quel est l'intérêt de créer un fichier si vous ne le souhaitez pas sur la mémoire persistante?
Bhavik Shah du
7
Wow, le manque d'imagination sur StackOverflow est stupéfiant. Quelqu'un peut avoir besoin d'un fichier en mémoire simple car il utilise une interface qui nécessite un fichier. L'interface aurait dû être écrite pour un InputStream, mais ce n'était pas le cas. Un fichier temporaire semble exagéré, donc un fichier java.io.File en mémoire serait préférable.
Novaterata

Réponses:

30

Pour écrire dans un flux, en mémoire, utilisez:

new ByteArrayOutputStream();
haraldK
la source
5
Cela ne répond pas à la question car ByteArrayOutputStream n'est pas utilisable avec une interface qui nécessite un objet fichier.
FableBlaze
1
@FableBlaze Eh bien, la réponse à la question est alors "ce n'est pas possible". Cette réponse essaie d'être pragmatique et de dire ce que l'utilisateur pourrait faire à la place. La réponse d'Andreas est clairement plus approfondie et une meilleure (tentative de) réponse.
haraldK
«Ce n'est pas possible» serait une réponse valable à mon avis. Cependant, je pense qu'un système de fichiers en mémoire (mentionné dans les commentaires de la réponse d'Andreas) pourrait également être mentionné, car si vous ne pouvez pas pour une raison quelconque écrire sur le disque dur, cela pourrait être un moyen de le contourner.
FableBlaze
80

Comment puis-je créer un nouveau fichier (à partir de java.io) en mémoire, pas sur le disque dur?

Peut-être que vous êtes déroutant Fileet Stream:

  • A Fileest une représentation abstraite des chemins de fichiers et de répertoires . À l'aide d'un Fileobjet, vous pouvez accéder aux métadonnées de fichier dans un système de fichiers et effectuer certaines opérations sur les fichiers de ce système de fichiers, comme supprimer ou créer le fichier. Mais la Fileclasse ne fournit pas de méthodes pour lire et écrire le contenu du fichier.
  • Pour lire et écrire à partir d'un fichier, vous utilisez un Streamobjet, comme FileInputStreamou FileOutputStream. Ces flux peuvent être créés à partir d'un Fileobjet, puis être utilisés pour lire et écrire dans le fichier.

Vous pouvez créer un flux basé sur un tampon d'octets qui réside en mémoire , en utilisant a ByteArrayInputStreamet a ByteArrayOutputStreampour lire et écrire dans un tampon d'octets de la même manière que vous lisez et écrivez à partir d'un fichier. Le bytetableau contient le contenu du «fichier». Vous n'avez donc pas besoin d'un Fileobjet.

Les File...et les ByteArray...flux héritent de java.io.OutputStreamet java.io.InputStream, respectivement, afin que vous puissiez utiliser la superclasse commune pour masquer si vous lisez à partir d'un fichier ou d'un tableau d'octets.

Andreas Fester
la source
95
Je ne sais pas si c'est ce que voulait l'affiche originale, mais un exemple où un "Fichier en mémoire" serait utile est lorsque vous souhaitez réutiliser une bibliothèque existante qui a besoin d'un fichier java.io.File comme paramètre d'entrée, mais vous veulent réellement utiliser des «fichiers» stockés en mémoire. Dans ce cas, je pense qu'une solution serait d'utiliser Apache Commons VFS pour instancier un DefaultFileSystemManager et de l'utiliser pour créer un RamFileProvider. J'aurais ajouté cela comme une réponse correcte (plus complète), mais il semble que cette question ait été fermée il y a quelque temps ...
Sorin Postelnicu
2
+1 Je cherchais ce genre de solution, pour tester unitaire un composant sans avoir à utiliser un fichier réel
GClaramunt
3
Si vous ne souhaitez pas créer "un fichier réel", vous pouvez essayer de créer un fichier temporaire. Voir createTempFilepour java.io.file. Ce fichier peut être configuré pour être supprimé automatiquement à la fin du test unitaire.
Andrew-Dufresne
2
Cela ne répond pas à la question. Comme @SorinPostelnicu l'a bien dit, un "fichier" en mémoire est quelque chose comme un système de fichiers en mémoire ou plus.
Felipe
1
Résume probablement le cas d'utilisation de l'OP et une méthode précieuse pour réduire la latence avec des entrées / sorties de disque système coûteuses.
Eddie B
3

Vous pouvez utiliser un système de fichiers en mémoire, tel que Jimfs

Voici un exemple d'utilisation de leur 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
la source