簡體   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