如何在内存中创建一个新的 java.io.File? [复制]

Posted

技术标签:

【中文标题】如何在内存中创建一个新的 java.io.File? [复制]【英文标题】:How to create a new java.io.File in memory? [duplicate] 【发布时间】:2013-07-09 19:49:32 【问题描述】:

如何在内存而不是硬盘上创建新的File(来自java.io)?

我正在使用 Java 语言。我不想将文件保存在硬盘上。

我遇到了一个糟糕的 API (java.util.jar.JarFile)。它期待File fileString filename。我没有文件(只有byte[] 内容)并且可以创建临时文件,但这不是很好的解决方案。我需要验证签名 jar 的摘要。

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

任何关于如何在不创建临时文件的情况下获得清单的示例都将不胜感激。

【问题讨论】:

所以你只想要内存中的字节? 你想用这个File做什么 一个File定义在硬盘上。 @UwePlonus 没有...new File("/dev/null") 哇,*** 缺乏想象力真是令人震惊。有人可能需要一个简单的内存文件,因为他们使用的接口需要一个文件。该接口应该是为 InputStream 编写的,但事实并非如此。临时文件似乎有点矫枉过正,所以内存中的 java.io.File 会更好。 【参考方案1】:

如何在内存而不是硬盘中创建新文件(来自 java.io)?

也许你混淆了FileStream

File 是文件和目录路径名 的抽象表示。使用File 对象,您可以访问文件系统中的文件元数据,并对该文件系统上的文件执行一些操作,例如删除或创建文件。但是File 类没有提供读写文件内容的方法。 要读取和写入文件,您使用的是Stream 对象,例如FileInputStreamFileOutputStream。这些流可以从File 对象创建,然后用于读取和写入文件。

您可以创建一个基于驻留在内存中的字节缓冲区的流,通过使用ByteArrayInputStreamByteArrayOutputStream 来读取和写入字节缓冲区 strong> 以类似的方式从文件中读取和写入。 byte 数组包含“文件”的内容。那么你就不需要File 对象了。

File...ByteArray... 流分别继承自 java.io.OutputStreamjava.io.InputStream,因此您可以使用通用超类来隐藏您是从文件中读取,还是从字节数组中读取。

【讨论】:

我不确定这是否是原始发布者想要的,但是当您想要重用需要 java.io 的现有库时,“内存中的文件”很有用的一个示例。文件作为输入参数,但您实际上想使用存储在内存中的“文件”。在这种情况下,我认为一种解决方案是使用 Apache Commons VFS 来实例化 DefaultFileSystemManager 并使用它来创建 RamFileProvider。我会将此添加为(更完整的)正确答案,但似乎这个问题已在一段时间前关闭...... +1 我一直在寻找这种解决方案,无需使用实际文件即可对组件进行单元测试 如果您不想创建“实际文件”,那么您可以尝试创建一个临时文件。对于java.io.file,请参阅createTempFile。该文件可以设置为在单元测试退出时自动删除。 这不能回答问题。正如@SorinPostelnicu 所说,内存中的“文件”类似于内存中的文件系统。 OP 绝对不会混淆文件和流。他认为他想使用 jarFile 来读取文件,而他所拥有的只是来自某个来源的字节(getContent())。【参考方案2】:

无法创建将其内容保存在(Java 堆)内存 * 中的 java.io.File

相反,通常您会使用流。要写入内存中的流,请使用:

OutputStream out = new ByteArrayOutputStream();
out.write(...);

但不幸的是,流不能用作java.util.jar.JarFile 的输入,正如您提到的,它只能使用包含有效 JAR 路径的 FileString 文件。我相信像你现在这样使用临时文件是唯一的选择,除非你想使用不同的 API。

如果您可以使用不同的 API,那么在同一个包中可以方便地使用一个名为 JarInputStream 的类。只需将 archiveContent 数组包装在 ByteArrayInputStream 中,即可读取 JAR 的内容并提取清单:

try (JarInputStream stream = new JarInputStream(new ByteArrayInputStream(archiveContent))) 
     Manifest manifest = stream.getManifest();


*) 显然可以创建一个驻留在内存中的完整文件系统,例如 RAM 磁盘,但就 Java 进程而言,它仍然是“在磁盘上”(而不是在 Java 堆内存中)担心。

【讨论】:

这不能回答问题,因为 ByteArrayOutputStream 不能用于需要文件对象的接口。 @FableBlaze 那么问题的答案是“不可能”。这个答案试图是务实的,并告诉用户可以做什么。安德烈亚斯的回答显然更彻底,更好(尝试)回答。 “不可能”在我看来是一个有效的答案。但是我认为也可以提到内存中的文件系统(在 Andreas 的回答中提到的 cmets),因为如果您由于某种原因不能写入硬盘驱动器,那么这可能是一种解决方法。【参考方案3】:

您可以使用内存中的文件系统,例如 Jimfs

这是他们自述文件中的一个用法示例:

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

【讨论】:

Jimfs 不支持 File 对象【参考方案4】:

我认为临时文件可能是另一种解决方案。

File tempFile = File.createTempFile(prefix, suffix, null);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteArray);

有一个关于here的答案。

【讨论】:

以上是关于如何在内存中创建一个新的 java.io.File? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby 中创建一个新的 Date 实例

如何在 Xcode 中创建一个新的 C++ 项目?

如何在新的 NavigationView 中创建一个简单的分隔线?

在目录中创建文件之前检查目录中的写访问权限

如何在反应钩子中创建一个新的 JSON 对象?

如何拆除 SparkSession 并在一个应用程序中创建一个新的?