我正在编写java程序来加密视频文件,它按预期执行的小视频文件然而当我尝试大约800兆字节的巨大文件时,它会引发异常
java.lang.OutOfMemoryError: Java heap space
。
我已经研究了从here获取有关垃圾收集器的更多信息并查看类似问题here的主题。根据最佳选择的答案你怎么能一次加密一个字节&#34 ;:使用块密码加密是由块(AES:16字节)`。
我的源代码的内容
main.java
public static void main(String[] args) {
String key = "Mary has one cat";
File inputFile = new File("C:\\Users\\xyz\\Music\\test\\-.mp4");
File encryptedFile = new File("C:\\Users\\xyz\\Music\\test\\-.mp4.encrypted");
File decryptedFile = new File("C:\\Users\\xyz\\Music\\test\\decrypted.mp4");
try {
CryptoUtils.encrypt(key, inputFile, encryptedFile);
CryptoUtils.decrypt(key, encryptedFile, decryptedFile);
} catch (CryptoException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
CryptoUtils.java
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
public static void encrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
public static void decrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
private static void doCrypto(int cipherMode, String key, File inputFile,
File outputFile) throws CryptoException {
try {
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | IOException ex) {
throw new CryptoException("Error encrypting/decrypting file", ex);
}
}
CryptoException.java
public class CryptoException extends Exception {
public CryptoException() {
}
public CryptoException(String message, Throwable throwable) {
super(message, throwable);
}}
答案 0 :(得分:3)
我认为您应该考虑使用CipherOutputStream。这样您就不需要将文件加载到内存中了:
https://docs.oracle.com/javase/9/docs/api/javax/crypto/CipherOutputStream.html
答案 1 :(得分:3)
不要一次处理整个文件:使用缓冲区:
try (FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] inputBytes = new byte[4096];
for (int n = inputStream.read(inputBytes); n > 0; n = inputStream.read(inputBytes)) {
byte[] outputBytes = cipher.update(inputBytes, 0, n);
outputStream.write(outputBytes);
}
byte[] outputBytes = cipher.doFinal();
outputStream.write(outputBytes);
}