Как преобразовать большой примитивный массив байтов в массив байтов объекта?

У меня проблемы с загрузкой файлов с помощью приложения моей компании, оно вылетает при загрузке файлов размером более 50 МБ.

Я получаю файл как массив собственных байтов от WS, а затем конвертирую его в массив Object Byte, чтобы сериализовать его перед преобразованием этих байтов в файл для загрузки.

Это отлично работает с небольшими файлами, но когда вы загружаете файлы размером более 50 МБ, преобразование из bytes[] в Byte[] не выполняется.

Это был код, который у меня был:

private RespuestaDescargarDocumento rellenarRespuestaDescarga(byte[] contenido, String nombreDocumento){

        Byte[] bytes = ArrayUtils.toObject(contenido);

        RespuestaDescargarDocumento respuesta = new RespuestaDescargarDocumento();
        respuesta.setContenido(bytes);
        respuesta.setNombreDocumento(nombreDocumento);

        return respuesta;
    }

Я посмотрел, что делает toObject(), и понял, что он выполняет new Byte() на каждой итерации этого цикла, поэтому, если я загружаю файл, например, размером 52 МБ, он выполняет 53167398 итераций, и для каждой итерации создается новый байт.

public static Byte[] toObject(byte[] array) {
        if (array == null) {
            return null;
        } else if (array.length == 0) {
            return EMPTY_BYTE_OBJECT_ARRAY;
        }
        final Byte[] result = new Byte[array.length];
        for (int i = 0; i < array.length; i++) {
            result[i] = new Byte(array[i]);
        }
        return result;
    } 

Я думаю, что это смешно, поэтому я посмотрел, как выполнить это преобразование без этого метода, и нашел эту ветку:

как преобразовать byte [] в Byte [] и наоборот?

И я попробовал лучший ответ вот так:

private RespuestaDescargarDocumento rellenarRespuestaDescarga(byte[] contenido, String nombreDocumento) {

        //Byte[] bytes = ArrayUtils.toObject(contenido);
        Byte[] bytes = byteToByte(contenido);

        RespuestaDescargarDocumento respuesta = new RespuestaDescargarDocumento();
        respuesta.setContenido(bytes);
        respuesta.setNombreDocumento(nombreDocumento);

        return respuesta;
    }

    private Byte[] byteToByte(byte[] array) {
        if (array == null || array.length == 0) {
            return ArrayUtils.EMPTY_BYTE_OBJECT_ARRAY;
        }
        Byte[] bytes;
        bytes = new Byte[array.length];
        for (int i = 0; i < array.length; i++) {
            bytes[i] = array[i];
        }
        return bytes;
    }

И теперь я могу идеально загрузить этот файл размером 52 МБ, чтобы он работал, или я так думал, когда я попытался загрузить файл большего размера, размером 150 МБ, он снова вылетел. На этот раз цикл выполняет 159551619 итераций.

Я получаю следующую ошибку:

java.lang.OutOfMemoryError: Java heap space

В этой строке:

bytes = new Byte[array.length];

Таким образом, он даже не получает цикл for моей функции, как будто Java не может создать массив такого размера (159551619). Но я обнаружил, что максимальный размер массива в Java составляет 2147483647, поэтому он все равно должен работать с этим.

Я делаю что-то неправильно?

У вас заканчивается память, либо выделите больше памяти для своего приложения, либо не пытайтесь сохранить все эти данные в памяти. Кроме того, почему вы хотите использовать Byte[]? Почему нельзя просто использовать byte[]? Обычно вам следует избегать объектных оберток примитивов: они потребляют намного больше памяти (например, вместо одного байта на байт вам понадобится 4-8 байтов (в зависимости от 32 или 64 бит) для каждого байта в массиве + размер самого экземпляра Byte.

Mark Rotteveel 31.10.2018 12:43

Что вы получаете от преобразования byte [] в Byte []? Почему бы вам не записать байты прямо в файл как есть? Чтобы избежать переполнения памяти, лучше не хранить в памяти весь файл. Байтовые потоки лучше. Прочтите один байтовый блок и запишите этот блок на диск. Затем прочтите следующий блок байтов и так далее.

vanje 31.10.2018 12:47

Ваша вторая попытка делает то же самое, что и первая. new Byte просто не виден, потому что это происходит автоматически из-за автоматического бокса. Полностью избавьтесь от преобразования, это бесполезно, медленно и требует много памяти.

Henry 31.10.2018 13:30

Я действительно не знаю причину этого преобразования, потому что это устаревший код, но вы правы, это преобразование бесполезно. Я обнаружил, что после этого происходит еще одно преобразование из Byte [] в byte [], так что это делает это более глупым. Я удалил это преобразование и использовал массив byte [], который я получил от WS, для непосредственного создания файла, и он хорошо работает с любыми типами файлов (включая файл размером 150 МБ). Спасибо большое.

Ise92 31.10.2018 16:51
0
4
743
0

Другие вопросы по теме