Шифрование большого файла с помощью AES с использованием JAVA
Я тестировал свой код с файлами меньше этого (10mb, 100mb, 500mb), и шифрование работает. Однако я столкнулся с проблемами с файлами размером более 1 ГБ.
Я создал большой файл (около 2 гб), и я хочу зашифровать его с помощью AES с помощью JAVA, но я столкнулся с этой ошибкой:
"Исключение в потоке" main "java.lang.OutOfMemoryError: Java heap space"
Я попытался увеличить доступную память, используя -Xmx8G, но не кубики.
Часть моего кода выглядит следующим образом
File selectedFile = new File("Z:\\dummy.txt");
Path path = Paths.get(selectedFile.getAbsolutePath());
byte[] toencrypt = Files.readAllBytes(path);
byte[] ciphertext = aesCipherForEncryption.doFinal(toencrypt);
FileOutputStream fos = new FileOutputStream(selectedFile.getAbsolutePath());
fos.write(ciphertext);
fos.close();
Насколько я могу судить, причина, по которой он ведет себя таким образом, заключается в том, что он пытается сразу прочитать весь файл, зашифровать его и сохранить в другой массив байтов вместо буферизации и потоковой передачи. кто-нибудь поможет мне с некоторыми подсказками кода?
Я новичок в кодировании, поэтому я действительно мало знаю, любая помощь будет оценена.
Ответы
Ответ 1
Даже не пытайтесь читать целые большие файлы в памяти. Шифрование буфера за раз. Просто выполните стандартный цикл копирования с соответствующим образом инициализированным CipherOutputStream
, завернутым вокруг FileOutputStream
. Вы можете использовать это для всех файлов, не нужно делать из него особый случай. Используйте буфер размером 8k или более.
EDIT "Стандартный цикл копирования" в Java выглядит следующим образом:
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
где в этом случае out = new CipherOutputStream(new FileOutputStream(selectedFile), cipher)
.
Ответ 2
Вы также можете упростить процесс, используя Encryptor4j: https://github.com/martinwithaar/Encryptor4j
File srcFile = new File("original.zip");
File destFile = new File("original.zip.encrypted");
String password = "mysupersecretpassword";
FileEncryptor fe = new FileEncryptor(password);
fe.encrypt(srcFile, destFile);
В этой библиотеке используется потоковое шифрование, поэтому она не будет вызывать OutOfMemoryError
даже большими файлами. Кроме того, вместо использования паролей вы также можете использовать свой собственный Key
.
Посмотрите пример на странице Github здесь: https://github.com/martinwithaar/Encryptor4j#file-encryption