Шифрование большого файла с помощью AES с помощью JAVA

Я тестировал свой код с файлами меньше этого (10mb, 100mb, 500mb), и шифрование работает. Однако, я бегу в проблемы с файлами больше 1Гб. Я создал большой файл (около 2 ГБ), и я хочу зашифровать его с помощью AES с помощью JAVA, но я сталкиваюсь с этой ошибкой:

"исключение в потоке "main" java.ленг.OutOfMemoryError: пространство кучи Java"

Я попытался увеличить доступную память с помощью -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();

насколько я могу судить, причина, по которой он ведет себя таким образом, заключается в том, что он пытается прочитать весь файл сразу, зашифровать его и сохранить в другом массиве байтов вместо буферизации и потоковой передачи. Может ли кто-нибудь помочь мне с некоторыми подсказками кода?

Я новичок в кодировании, поэтому я не очень много знаю,любая помощь будет оценена.

2 ответов


даже не пытайтесь читать целые большие файлы в память. Шифрование буфера за раз. Просто сделайте стандартный цикл копирования с соответствующим инициализированным CipherOutputStream обернуть вокруг FileOutputStream. Вы можете использовать это для всех файлов, не нужно делать из него особый случай. Используйте буфер 8k или больше.

редактировать "стандартный цикл копирования" в 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).


можно упростить процесс еще больше, используя 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