Попытка использовать BufferedInputStream и Base64 для кодирования большого файла на Java

#java #base64 #apache-commons #bufferedinputstream

Вопрос:

Я новичок в вводе-выводе Java, поэтому, пожалуйста, помогите.

Я пытаюсь обработать большой файл(например, файл pdf размером 50 МБ) с помощью библиотеки apache commons. Сначала я пытаюсь:

 byte[] bytes = FileUtils.readFileToByteArray(file);
String encodeBase64String = Base64.encodeBase64String(bytes);
byte[] decoded = Base64.decodeBase64(encodeBase64String);
 

Но зная, что
FileUtils.readFileToByteArray в org.apache.commons.io загрузит весь файл в память, я пытаюсь использовать BufferedInputStream его для чтения файла по частям:

 BufferedInputStream bis = new BufferedInputStream(inputStream);
StringBuilder pdfStringBuilder = new StringBuilder();
int byteArraySize = 10;
byte[] tempByteArray = new byte[byteArraySize];
while (bis.available() > 0) {
                if (bis.available() < byteArraySize) { // reaching the end of file
                    tempByteArray = new byte[bis.available()];
                }
                int len = Math.min(bis.available(), byteArraySize);
                read = bis.read(tempByteArray, 0, len);

                if (read != -1) {
                    pdfStringBuilder.append(Base64.encodeBase64String(tempByteArray));
                } else {
                    System.err.println("End of file reached.");
                }
            }
byte[] bytes = Base64.decodeBase64(pdfStringBuilder.toString());
 

Однако массив из 2 декодированных байтов выглядит не совсем так… … На самом деле, только 10 байт, что соответствует размеру моего временного массива… …

Кто-нибудь может, пожалуйста, помочь:

  • что я делаю неправильно, читая файл по частям?
  • почему декодированный массив байтов возвращает только 10 байтов во 2-м решении?

Заранее спасибо:)

Комментарии:

1. Честно говоря, я бы посоветовал вам попытаться закодировать весь файл сразу: 50 МБ на самом деле не так уж велики; максимальная длина строки Java составляет 2 ГБ.

2. @paulsm4 Спасибо за ваше предложение:)

3. Никогда не правильно использовать InputStream.available() для проверки конца потока. Вместо этого проверьте read , вернул ли метод отрицательное значение. Подробные сведения см. в документации .

4. @VGR: Спасибо за ваш совет:) В качестве дополнительного вопроса, есть ли какие-либо предложения о том, как удалить/обрезать нули в конце последнего байтового массива?

5. Безусловно, существуют способы обработки только части массива байтов, но я бы сначала спросил, почему вы кодируете данные в base64, а затем сразу же декодируете эти же данные в bse64. Вы правы, что загрузка всего файла в память в память-плохая идея, но в конечном счете вы все равно делаете это (дважды!), так как вы все еще используете bytes переменную. Какую обработку файла вы на самом деле хотите выполнить?

Ответ №1:

После некоторого копания выясняется, что размер массива байтов должен быть кратен 3, чтобы избежать заполнения. После использования временного массива размером, кратным 3, программа может пройти.

Я просто меняюсь

 int byteArraySize = 10;
 

быть

 int byteArraySize = 1024 * 3;