Самый эффективный способ преобразования InputStream в байт []?

ChannelBufferInputStream responseStream = (ChannelBufferInputStream) response.getBodyAsStream();
ArrayList<Byte> arrayList = new ArrayList<Byte>();
try {
    while (responseStream.available() > 0) {
        arrayList.add(responseStream.readByte());
    }
} catch (IOException e) {
    e.printStackTrace();
    return internalServerError();
}
Iterator<Byte> iterator = arrayList.iterator();
byte[] bytes = new byte[arrayList.size()];
int i = 0;
while (iterator.hasNext()) {
    bytes[i++] = iterator.next();
}

Этот код вызывается при каждой загрузке страницы моего веб-приложения. Кажется, он работает довольно быстро, но есть ли что-нибудь, что могло бы ускорить этот запуск?

Редактировать - обновляется с использованием потока байтов массива

ChannelBufferInputStream responseStream = (ChannelBufferInputStream) response.getBodyAsStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
    int read = responseStream.read();
    while (read != -1) {
        byteArrayOutputStream.write(read);
        read = responseStream.read();
    }
} catch (IOException e) {
    e.printStackTrace();
    return internalServerError();
}
byte[] bytes = byteArrayOutputStream.toByteArray();
return ok(bytes).as(response.getHeader("Content-type"));

Изменить - тестовый тестовый код

ChannelBufferInputStream responseStream = (ChannelBufferInputStream) response.getBodyAsStream();
long t1 = System.nanoTime();

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
    int read = responseStream.read();
    while (read != -1) {
        byteArrayOutputStream.write(read);
        read = responseStream.read();
    }
} catch (IOException e) {
    e.printStackTrace();
    return internalServerError();
}
byte[] bytes = byteArrayOutputStream.toByteArray();

long t2 = System.nanoTime();
System.out.println(t2-t1);
return ok(bytes).as(response.getHeader("Content-type"));

Среднее время после запроса 100+ - 46873

ChannelBufferInputStream responseStream = (ChannelBufferInputStream) response.getBodyAsStream();
long t1 = System.nanoTime();

ArrayList<Byte> arrayList = new ArrayList<Byte>();
try {
    while (responseStream.available() > 0) {
        arrayList.add(responseStream.readByte());
    }
} catch (IOException e) {
    e.printStackTrace();
    return internalServerError();
}
Iterator<Byte> iterator = arrayList.iterator();
byte[] bytes = new byte[arrayList.size()];
int i = 0;
while (iterator.hasNext()) {
    bytes[i++] = iterator.next();
}

long t2 = System.nanoTime();
System.out.println(t2-t1);
return ok(bytes).as(response.getHeader("Content-type"));

Среднее время после запроса 100+ - 522848

long t1 = System.nanoTime();
byte[] bytes;
try {
    bytes = org.apache.commons.io.IOUtils.toByteArray(responseStream);
} catch (Exception e) {
    return internalServerError();
}

long t2 = System.nanoTime();
System.out.println(t2-t1);

Среднее время после запроса 100+ - 45088

long t1 = System.nanoTime();
byte[] bytes;
try {
    bytes = sun.misc.IOUtils.readFully(responseStream, -1, true);
} catch (Exception e) {
    return internalServerError();
}

long t2 = System.nanoTime();
System.out.println(t2 - t1);

Среднее время после запроса 100+ - 20180

Ответ 1

Да. Используйте ByteArrayOutputStream а не ArrayList. Затем прочитайте фрагменты байтов из InputStream (без использования available(), которые почти никогда не будут использоваться) и напишите эти куски в ByteArrayOutputStream, пока метод read() вернет -1. Затем вызовите toByteArray() в ByteArrayOutputStream.

Вы можете использовать метод Guava ByteStreams.toByteArray(), который делает все это для вас, или вы можете прочитать его исходный код, чтобы лучше понять, как он это делает. Чтение учебника IO также может помочь.

Ответ 2

Что случилось с методом Apache Commons IO IOUtils.toByteArray? Для этой цели это было оптимизировано на протяжении многих лет.

Ответ 3

Зачем? Этот код полностью эквивалентен read(byte[]) за исключением того, что он выполняет два дополнительных этапа копирования для всех данных. Тебе это не нужно. Простое read(byte[]) будет в несколько раз быстрее.

Использование available() недействительно. Вам нужен весь ответ, а не только часть, которую можно прочитать без блокировки. Вам нужно зациклиться.