通过 ReadableByteChannel 的 InputStream 没有读到结束

InputStream via ReadableByteChannel does not read to end

我在使用 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();

因为这个实现很慢。

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

这会导致问题:

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

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

你的复制循环是完全错误的。没有理由 bytesRead 应该 曾经 >= size,并且它在流的末尾行为不端。它应该是这样的:

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

适当调整以将传输限制为 size 字节,这是非常重要的。

但是将所有这些叠加在现有的 InputStream 上不可能 'much faster' 直接使用 InputStream,除非因为提前终止。除非您发布了使用 InputStream 的想法,否则速度非常慢。尝试使用 'BufferedInputStream.