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