it-swarm.com.de

Der effizienteste Weg, um InputStream in Byte [] zu konvertieren?

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();
}

Dieser Code wird bei jedem Seitenaufruf meiner Web-App aufgerufen. Es scheint ziemlich schnell zu laufen, aber gibt es irgendetwas, das es schneller laufen lassen könnte?

Bearbeiten - Aktualisiert mit dem Bytearray-Ausgabestream

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"));

Bearbeiten - Benchmark-Testcode

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"));

Durchschnittliche Zeit nach mehr als 100 Anfragen - 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"));

Average Time after 100+ request - 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);

Durchschnittliche Zeit nach mehr als 100 Anfragen - 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);

Durchschnittliche Zeit nach mehr als 100 Anfragen - 20180

11
sissonb

Ja. Verwenden Sie eine ByteArrayOutputStream anstelle einer ArrayList. Dann lesen Sie Byte-Blöcke aus dem InputStream (ohne available() zu verwenden, was fast immer nie verwendet werden sollte), und schreiben Sie diese Blöcke in den ByteArrayOutputStream, bis die read()-Methode -1 zurückgibt. Dann rufen Sie toByteArray () auf Ihrer ByteArrayOutputStream auf.

Sie können die Guava-Methode ByteStreams.toByteArray() verwenden, die all dies für Sie erledigt, oder Sie können den Quellcode lesen, um eine bessere Vorstellung davon zu erhalten, wie sie funktioniert. Das Lesen des IO-Tutorials kann ebenfalls hilfreich sein.

13
JB Nizet

Was ist los mit der Apache Commons IO IOUtils.toByteArray -Methode? Das wurde über viele Jahre für diesen Zweck optimiert.

4
bmargulies

Warum? Dieser Code entspricht vollständig read(byte[]), mit der Ausnahme, dass zwei zusätzliche Kopierschritte für die gesamten Daten ausgeführt werden. Sie brauchen nichts davon. Eine einfache read(byte[]) wäre mehrmals so schnell.

Die Verwendung von available() ist ebenfalls ungültig. Sie benötigen die gesamte Antwort, nicht nur den Teil, der ohne Blockierung gelesen werden kann. Du musst eine Schleife machen.

1
user207421