从Java中读取非常大的加密文件时,我使用以下代码:
FileInputStream in = new FileInputStream("file.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(saveLocation), "utf-8"));
int read;
byte buffer[] = new byte[16384];
byte getData[] = new byte[16384];
while((read = in.read(buffer)) != -1)
{
baos.write(buffer, 0, read);
Cipher cipher = Cipher.getInstance(symCipher);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initVecBytes);
cipher.init(Cipher.DECRYPT_MODE, originalKey, ivParameterSpec);
byte[] original = cipher.doFinal(baos.toByteArray());
String s = new String(original);
writer.append(s);
baos.reset();
}
writer.close();
由于文件非常大(对于我来说太大而无法一次性加载到内存中)我将其读入一个小缓冲区,然后加密小字节数据,最后将它们写入文件。
然而,当我这样做时,一些数据看起来已损坏:
</AddressLine><_��SR����_�hEE</AddressLine></AddressLines><Postcode>
当我使用的文件不是16k时,它运行正常,我似乎只是在新数组读取开始时获得少量损坏的数据,然后它就会#39 ; s再次没问题,直到下一个数组读取,依此类推。
任何人都知道为什么这不能正常工作?
答案 0 :(得分:1)
ByteArrayOutputStream
和Writer
并将解密后的数组直接写入FileOutputStream
。Cipher
,并将其初始化一次,而不是每次读取一次。CipherInputStream
约五行代码完成所有这些操作。答案 1 :(得分:1)
它无效,因为大多数密码都是有状态的。具体来说,在密码块链接模式中,明文必须与先前的密文块进行异或。但是每16k,你用IV反而对它进行异或。您无法在解密操作过程中重新初始化Cipher
。
以下是五行代码to which EJP alluded.
Cipher cipher = Cipher.getInstance(symCipher);
cipher.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initVecBytes));
try (InputStream in = Files.newInputStream(Paths.get("file.txt"))) {
Files.copy(new CipherInputStream(in, cipher), Paths.get(saveLocation));
}