我遇到了需要缓冲 CipherInputStream 的情况。确切地说,在将结果返回给 InputStream.read(byte[], int, int) 的调用者之前,我需要确保缓冲区已填充到 32K 或达到 EOF。在这里,我遇到了一些障碍,希望大家能帮忙解决。

  • Oracle JRE - CipherInputStream 有一个 512 字节的内部缓冲区,用于
    没有特别的原因。
  • IBM JRE - CipherInputStream 有一个内部缓冲区
    8KB

  • 简单地用 BufferedInputStream 包装 CipherInputStream 不会给我任何好处,因为 CipherInputStream.available() 将返回 0,这使得缓冲毫无意义。 CipherInputStream 的 javadoc 指出这应该被子类 http://docs.oracle.com/javase/7/docs/api/javax/crypto/CipherInputStream.html#available() 覆盖

    由于我将 FileInputStream 的(在大多数情况下)作为我的最低级别流,并且我的密码算法是没有填充的 CTR,我在加密前和加密后的字节数相同,但这就是事情开始变得模糊的地方为我。我已经覆盖了 CipherInputStream.available() 以返回 super.available(),这对于使用 Oracle 的 CipherInputStream 的本地文件似乎非常有用。

    我可以确保我的 32K 缓冲区充满了对 read(byte[], int, int) 的调用,或者到达了文件末尾。

    使用 Oracle JRE 的输出
    **CipherInputStream.available: 51121
    **CipherInputStream.available: 50609
    **CipherInputStream.available: 50097
    ...
    **CipherInputStream.available: 19889
    **CipherInputStream.available: 19377
    **BufferedInputStream.read: 32768
    **CipherInputStream.available: 18353
    **CipherInputStream.available: 17841
    **CipherInputStream.available: 17329
    ...
    **CipherInputStream.available: 433
    **CipherInputStream.available: 0
    **BufferedInputStream.read: 18865
    **EOF
    

    但是,在 IBM 的 JVM 上,就好像跳过了对底层 FileInputStream 上的 in.available 调用,这会导致预期返回完整缓冲区或文件结尾的 api 出现问题。这与在 Windows 和 iSeries 上使用 IBM JRE 的行为相同。

    使用 IBM JRE 输出
    **CipherInputStream.available: 43441
    **CipherInputStream.available: 35249
    **CipherInputStream.available: 27057
    **BufferedInputStream.read: 32768
    (where's the 18865)?
    **CipherInputStream.available: 10673
    **CipherInputStream.available: 2481
    **CipherInputStream.available: 0
    **BufferedInputStream.read: 18864
    **CipherInputStream.available: 0
    **BufferedInputStream.read: 1
    EOF
    

    代码
    int BUFFER_SIZE = 32768;
    BufferedInputStream bis = null;
    CipherInputStream cis = null;
    try {
        // returns an AES256 CTR cipher with no padding
        Cipher cipher = getCipher();
    
        cis = new CipherInputStream(fis, cipher) {
    
            @Override
            public int available() throws IOException {
                // The cipher input stream always returns 0 because
                // in certain implementations (padded ciphers), a
                // standard implementation may not be able to
                // accurately determine the number of available
                // bytes. In our case, however, we are not using a
                // padded cipher and the number of available bytes
                // 'should' be the same as the number available from
                // the underlying stream.
    
                int available = in.available();
                System.out.println("**CipherInputStream.available: "
                    + available);
                return available;
            }
        };
        bis = new BufferedInputStream(cis, BUFFER_SIZE);
    
        byte[] buf = new byte[BUFFER_SIZE];
        int read = 0;
        while (read >= 0) {
            read = bis.read(buf, 0, BUFFER_SIZE);
            if (read >= 0) {
                System.out.println("**BufferedInputStream.read: " + read);
            }
        }
        System.out.println("EOF");
    }
    finally {
        if (cis != null) {
            try {
                cis.close();
            }
            catch (IOException exp) {
                // ignore
            }
        }
        if (bis != null) {
            try {
                bis.close();
            }
            catch (IOException exp) {
                // ignore
            }
        }
    }
    

    我尝试创建自己的 BufferedInputStream 并更改 read(byte[], int, int) 方法以不检查包装流的 available() 。这样,它将继续读取,直到 a) 缓冲区已满,或 b) 到达文件末尾,但我不确定这是否是最佳方法。

    有没有人对如何解决这个问题有更好的建议或想法?

    最佳答案

    忘记 available() 和所有这些代码。只需将 CipherInputStream 包装在 DataInputStream 中,声明一个 32k 缓冲区,然后调用 readFully()。两行代码。

    关于java - 缓冲从 CipherInputStream 读取,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20623076/

    10-16 19:49