Java中的内联输入流处理

Java中的内联输入流处理,java,stream,zip,inputstream,Java,Stream,Zip,Inputstream,下面的问题我需要一些帮助。我正在做一个需要处理文件的项目。 我从用户那里获得输入流的句柄,在将其写入磁盘之前,我需要执行某些步骤 计算文件摘要 检查仅存在1个zip文件,如果已压缩,则解压缩数据 dos 2 unix转换 记录长度验证 并将文件加密并保存到磁盘 如果流程中出现任何异常,也需要中断流程 我尝试使用管道输出和输入流,但限制是Java建议它在两个单独的线程中运行。一旦我从输入流中读取数据,我就无法从其他处理步骤中使用它。文件可能非常大,因此无法缓存缓冲区中的所有数据。 请提供您的建

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

  • 计算文件摘要
  • 检查仅存在1个zip文件,如果已压缩,则解压缩数据
  • dos 2 unix转换
  • 记录长度验证
  • 并将文件加密并保存到磁盘
如果流程中出现任何异常,也需要中断流程 我尝试使用管道输出和输入流,但限制是Java建议它在两个单独的线程中运行。一旦我从输入流中读取数据,我就无法从其他处理步骤中使用它。文件可能非常大,因此无法缓存缓冲区中的所有数据。
请提供您的建议,或者是否有任何第三方库可供我使用。

最大的问题是,您需要在提供的输入流中提前查看,以确定是否收到zipfile

private boolean isZipped(InputStream is) throws IOException {
    try {
        return new ZipInputStream(is).getNextEntry() != null;
    } catch (final ZipException ze) {
        return false;
    }
}
在此之后,您需要在设置DigestInputStream之前将inputstream重置为初始位置。 然后直接读取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");
    }
}
私有字符串获取摘要(DigestInputStream dis)引发IOException{
最终字节[]buff=新字节[1024];
而(显示读取(buff)>0){
dis.read(buff);
}
返回DatatypeConverter.printBase64Binary(dis.getMessageDigest().digest());
}
私有void readValidateAndWriteRecords(InputStream为,最终OutputStream os)引发IOException{
final BufferedReader br=新的BufferedReader(新的InputStreamReader(is));
//do2unix由readline自动完成
对于(字符串line=br.readLine();line!=null;line=br.readLine()){
//记录长度验证
if(line.length()<1){
抛出新的运行时异常(“RecordLengthValidationFailed”);
}
写((行+“\n”).getBytes();
}
}
私有void failIf2ndZipEntryExists(ZipInputStream zis)引发IOException{
if(zis!=null&&zis.getNextEntry()!=null){
抛出新的RuntimeException(“Zip文件包含多个条目”);
}
}
==>输出:

摘要:jIisvDleAttKiPkyU/hDvbzzottAMn6n7inh4RKxPOc=
正在计数的输入流已关闭。读取的总字节数:1100

正在验证读取的字节和计算的摘要
摘要:jIisvDleAttKiPkyU/hDvbzzottAMn6n7inh4RKxPOc=
正在计数的输入流已关闭。读取的总字节数:1072


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

谢谢你的回答。这很有帮助。同样,是否有一种方法可以组合使用dos2unix流,而不是手动转换?