12
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

4

3 回答 3

14

是的。使用 aByteArrayOutputStream而不是 ArrayList。然后从 InputStream 中读取字节块(不使用available(),这几乎总是不应该使用)并将这些块写入 ByteArrayOutputStream,直到该read()方法返回 -1。然后在你的ByteArrayOutputStream.

您可以使用 Guava 的ByteStreams.toByteArray()方法,它为您完成所有这些工作,或者您可以阅读它的源代码以更好地了解它是如何做到的。阅读IO 教程也可能有所帮助。

于 2013-04-22T21:30:37.997 回答
4

Apache Commons IO IOUtils.toByteArray方法有什么问题?为此目的已经优化了很多年。

于 2013-04-22T21:47:18.060 回答
1

为什么?这段代码完全等效,read(byte[])只是它对整个数据做了两个额外的复制步骤。你不需要这些。一个简单read(byte[])的速度会快几倍。

的使用available()也是无效的。您需要整个响应,而不仅仅是可以在没有阻塞的情况下读取的部分。你需要循环。

于 2013-04-22T21:42:56.843 回答