繁体   English   中英

Java 中的内联输入流处理

[英]Inline input stream processing in Java

我需要一些关于以下问题的帮助。 我正在做一个需要处理文件的项目。 我从用户那里获得输入流的句柄,在将其写入磁盘之前,我需要执行某些步骤。

  • 计算文件摘要
  • 检查是否仅存在 1 个 zip 文件,如果已压缩,则解压缩数据
  • dos 2 unix 转换
  • 记录长度验证
  • 并加密并将文件保存到磁盘

如果在我尝试使用管道输出和输入流的过程中出现任何异常,还需要中断流程,但约束是 Java 建议它在 2 个单独的线程中运行。 一旦我从输入流中读取,我就无法在其他处理步骤中使用它。 文件可能非常大,因此无法缓存缓冲区中的所有数据。 请提供您的建议,或者我可以使用任何第三方库。

最大的问题是您需要提前查看提供的 InputStream 以确定您是否收到了 zipfile。

private boolean isZipped(InputStream is) throws IOException {
    try {
        return new ZipInputStream(is).getNextEntry() != null;
    } catch (final ZipException ze) {
        return false;
    }
}

在此之后,您需要在设置 DigestInputStream 之前将输入流重置为初始位置。 然后直接读取 ZipInputstream 或 DigestInputstream。 完成处理后,将 DigestInputStream 读到最后,以便获得摘要。 下面的代码已通过包装“CountingInputstream”进行验证,该包装跟踪从提供的 FileInputStream 读取的总字节数。

    final FileInputStream fis = new FileInputStream(filename);
    final CountingInputStream countIs = new CountingInputStream(fis);

    final boolean isZipped = isZipped(countIs);

    // make sure we reset the inputstream before calculating the digest
    fis.getChannel().position(0);
    final DigestInputStream dis = new DigestInputStream(countIs, MessageDigest.getInstance("SHA-256"));

    // decide which inputStream to use
    InputStream is = null;
    ZipInputStream zis = null;
    if (isZipped) {
        zis = new ZipInputStream(dis);
        zis.getNextEntry();
        is = zis;
    } else {
        is = dis;
    }

    final File tmpFile = File.createTempFile("Encrypted_", ".tmp");
    final OutputStream os = new CipherOutputStream(new FileOutputStream(tmpFile), obtainCipher());
    try {
        readValidateAndWriteRecords(is, os);
        failIf2ndZipEntryExists(zis);
    } catch (final Exception e) {
        os.close();
        tmpFile.delete();
        throw e;
    }

    System.out.println("Digest: " + obtainDigest(dis));
    dis.close();

    System.out.println("\nValidating bytes read and calculated digest");
    final DigestInputStream dis2 = new DigestInputStream(new CountingInputStream(new FileInputStream(filename)), MessageDigest.getInstance("SHA-256"));
    System.out.println("Digest: " + obtainDigest(dis2));
    dis2.close();

不是很相关,但这些是辅助方法:

private String obtainDigest(DigestInputStream dis) throws IOException {
    final byte[] buff = new byte[1024];
    while (dis.read(buff) > 0) {
        dis.read(buff);
    }
    return DatatypeConverter.printBase64Binary(dis.getMessageDigest().digest());
}

private void readValidateAndWriteRecords(InputStream is, final OutputStream os) throws IOException {
    final BufferedReader br = new BufferedReader(new InputStreamReader(is));
    // do2unix is done automatically by readline
    for (String line = br.readLine(); line != null; line = br.readLine()) {
        // record length validation
        if (line.length() < 1) {
            throw new RuntimeException("RecordLengthValidationFailed");
        }
        os.write((line + "\n").getBytes());
    }
}


private void failIf2ndZipEntryExists(ZipInputStream zis) throws IOException {
    if (zis != null && zis.getNextEntry() != null) {
        throw new RuntimeException("Zip File contains multiple entries");
    }
}

==> 输出:

摘要: jIisvDleAttKiPkyU/hDvbzzottAMn6n7inh4RKxPOc=
CountingInputStream 关​​闭。 读取的总字节数:1100

验证字节读取和计算摘要
摘要: jIisvDleAttKiPkyU/hDvbzzottAMn6n7inh4RKxPOc=
CountingInputStream 关​​闭。 读取的总字节数:1072

有趣的问题,我的回答可能太过分了:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM