2

我有一个使用 InputStreams 的现有问题,我想提高从该通道读取的性能。因此我用ReadableByteChannel.

因此,使用此代码读取速度要快得多:

public static String readAll(InputStream is, String charset, int size) throws IOException{

    try(ByteArrayOutputStream bos = new ByteArrayOutputStream()){
        java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(size);

        try(ReadableByteChannel channel = Channels.newChannel(is)){

            int bytesRead = 0;

            do{
                bytesRead = channel.read(buffer);
                bos.write(buffer.array(), 0, bytesRead);
                buffer.clear();
            }
            while(bytesRead >= size);
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        String ans = bos.toString(charset);
        return ans;
    }
}

问题是:每次都读不完!如果我尝试读取文件,它的效果非常好。如果我从网络套接字读取(例如手动请求网页),它有时会在两者之间停止。

我该怎么做才能读到最后?

我不想使用这样的东西:

StringBuilder result = new StringBuilder();
while(true){
    int ans = is.read();
    if(ans == -1) break;
    result.append((char)ans);
}
return result.toString();

因为这个实现很慢。

我希望你能帮助我解决我的问题。也许我的代码中有一些错误。

4

2 回答 2

1

这会导致问题:

    ... } while (bytesRead >= size);

当至少一个字节被读取时(或者即使在非阻塞的情况下没有字节),从套接字读取可能会返回。因此,如果 OS 套接字缓冲区中没有足够的字节,则条件将中断循环,尽管显然没有读取完整的内容。如果size确定要接收的预期长度,则在达到total += bytesRead时执行并中断循环。或者,如果您当然到达文件末尾...totalsize

于 2015-11-25T17:13:21.020 回答
0

你的复制循环是完全错误的。没有理由bytesRead应该永远存在>= size,并且它在流结束时行为不端。它应该是这样的:

while ((bytesRead = channel.read(buffer)) > 0)
{
    bos.write(buffer.array(), 0, bytesRead);
    buffer.clear();
}

通过适当的调整来限制传输到size字节,这是不平凡的。

但是将所有这些分层在现有的InputStream基础上不可能比InputStream直接使用“快得多”,除非因为过早终止。除非您使用 an 的想法InputStream是您发布的内容,否则速度非常慢。尝试使用 ' BufferedInputStream

于 2015-11-25T18:48:04.940 回答