我遇到了需要缓冲CipherInputStream的场景。确切地说,我需要确保缓冲区填充到32K或达到EOF,然后将结果返回到InputStream.read(byte [],int,int)的调用者。在这里,我遇到了一些障碍,我希望你们都可以提供帮助。
使用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)的调用,或者到达了文件末尾。
**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出现问题,而api应该返回一个完整的缓冲区或文件结尾。这与在Windows和iSeries上使用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)文件结束,但我不确定这是否是最好的方法。
有没有人对如何解决这个问题有任何更好的建议或想法?
答案 0 :(得分:2)
忘掉available()和所有代码。只需将CipherInputStream包装在DataInputStream中,声明一个32k缓冲区,然后调用readFully()。两行代码。