【问题标题】:Can we create file/zipfile as InputStream without a temporary file in java我们可以在没有临时文件的情况下在 java 中创建文件/zipfile 作为 InputStream
【发布时间】:2020-03-19 19:58:45
【问题描述】:

我需要创建一个测试,我需要在其中传递 InputStream 作为输入,这将是一个 zip 文件。有没有办法我们可以直接创建InputStream,而不是在内存/本地文件副本中创建,以便可以使用流进行测试。

【问题讨论】:

  • 您在寻找ByteArrayInputStream吗?
  • 感谢 slaw 的回复。 bytearrayinputstream 也应该有帮助。有没有一种方法可以在没有内存文件的情况下使用 bytearrayInputStream 创建一个临时 zipfile?
  • 使用 ZipOutputStream() 写入 ByteArraoyOutputSream。然后,您可以从 ByteArrayOutputStream 中获取字节数组并创建一个 ByteArrayInputStream。您可以使用 ZipInputStream 从此流中读取数据。
  • 我的问题是.. 有没有一种方法可以在不创建文件的情况下创建 zipInputStream/InputStream/FileInputStream ? new ZipInputStream(theFile) 这是我们创建 ZipInputStream 所需的方式,但如果您可以帮助我提供一些示例代码或任何已经可用的实用程序都会有所帮助。感谢回复
  • 我的要求是,有一个 Junit,我需要在其中调用一个将 Zip 文件作为 Input 的 rest API。所以我想用一些在 test 中硬编码的虚拟数据来创建这个 Zip 文件。所以为此我想创建 InputStream 并通过 rest api 发送它来验证我的测试 如果有办法,则创建 ondisk zipfile。

标签: java inputstream fileinputstream


【解决方案1】:

如果我正确理解您的问题,您想从硬编码数据创建一个内存中(即不在磁盘上)的 ZIP 文件。这当然可以使用以下类:

这是一个例子:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Main {

  public static void main(String[] args) throws IOException {
    // Destination of the ZIP file (an in-memory byte array)
    ByteArrayOutputStream boas = new ByteArrayOutputStream();

    /*
     * Write the ZIP file. This creates a single entry named "file.txt"
     * with "Hello, World!" as its contents.
     */
    try (ZipOutputStream zos = new ZipOutputStream(boas)) {
      zos.putNextEntry(new ZipEntry("file.txt"));
      zos.write("Hello, World!".getBytes());
      zos.closeEntry();
    }

    // Create an InputStream to read the raw bytes of the ZIP file
    ByteArrayInputStream bois = new ByteArrayInputStream(boas.toByteArray());

    /*
     * The following writes the ZIP file to disk, specifically to a file named "test.zip"
     * in the working directory. The purpose of this is to allow you to run the code
     * and see a tangible result (i.e. lets you inspect the resulting ZIP file). Obviously
     * you would not do this in your own code since you want to avoid writing the ZIP file
     * to disk.
     * 
     * Note: Will fail if the file already exists.
     */
    Files.copy(bois, Path.of("test.zip"));
  }
}

【讨论】:

    【解决方案2】:

    详细说明上面找到的一些答案,让我描述一下我遇到的情况以及我是如何解决的。我遇到了一种情况,我收到了 PGP 加密的文件(.pgp、.asc 等),所以我必须解密文件(.txt)本身,然后将其传递给流阅读器来解析行条目。而不是在读入之前将解密的文件作为临时文件保存在文件系统中以解析条目。我在内存中做了如下。

    我有一个函数将 InputStream 通过管道传输到 ByteArrayOutputStream(而不是 FileOutputStream,检索字节数组并将其初始化为 ByteArrayInputStream 并使用阅读器打印出每个条目

    InputStream encFileIn = new FileInputStream("some_encrypted_file.asc");
    byte[] decryptFile = util.decryptFile(encFileIn);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
                    new ByteArrayInputStream(decryptFile), StandardCharsets.UTF_8));
    reader.lines().forEach(f -> System.out.println(f));
    

    这里有一些关于在我的解密函数中管道 InputStream 的代码 sn-ps,由于我正在处理 PGP 文件,因此可能不适用于您。所以你可能会尝试直接实例化一个 ByteArrayInputStream

    public static void pipeAll(InputStream inStr, OutputStream outStr)
        throws IOException
    {
        byte[] bs = new byte[BUFFER_SIZE];
        int numRead;
        while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
        {
            outStr.write(bs, 0, numRead);
        }
    }
    
    public static byte[] readAll(InputStream inStr)
        throws IOException
    {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        pipeAll(inStr, buf);
        return buf.toByteArray();
    }
    

    【讨论】:

    • 当您已经拥有InputStream 时,为什么还要在ByteArrayOutputStreamByteArrayInputStream 上浪费内存?您可以通过CipherInputStream 直接从原始InputStream 解密文件并将其提供给InputStreamReader。除了以不相关的方式重复先前答案的方法之外,这些都没有解决所提出的问题。
    • 您对使用 CipherInputStream 的建议更有效且直截了当,谢谢。问题是我正在使用 openpgp (mvnrepository.com/artifact/org.bouncycastle/bcpg-jdk15on/1.68) 的 bouncycastle 实现,并且在内部它没有为他们的密钥实现 java.security.key 接口。我知道如何在没有 bouncycastle 的情况下对其进行初始化,但出于各种原因,我更喜欢使用这个库,例如其他外部程序会扫描我们的应用程序的漏洞并推荐升级版本。抱歉重复了,我过激了。
    猜你喜欢
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-05
    • 2014-12-03
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多