我有一个问题,我正在使用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;
}
}
问题是:每次都没有读到最终结果!如果我尝试读取文件,它的效果非常好。如果我从网络Socket中读取(例如手动请求WebPage),它有时会在两者之间停止。
我能做些什么来读到最后?
我不想使用这样的东西:
StringBuilder result = new StringBuilder();
while(true){
int ans = is.read();
if(ans == -1) break;
result.append((char)ans);
}
return result.toString();
因为这种实施很慢。
我希望你能解决我的问题。也许我的代码中有一些错误。
答案 0 :(得分:1)
这会导致问题:
... } while (bytesRead >= size);
当读取至少一个字节时(或者即使在非阻塞的情况下没有字节),从套接字读取也可能返回。因此,如果OS套接字缓冲区中没有足够的字节,条件将打破循环,尽管显然没有读取完整内容。如果size
标识了要接收的预期长度,请实施total += bytesRead
并在total
到达size
时中断循环。或者如果你到达文件末尾当然......
答案 1 :(得分:0)
您的复制循环完全错误。没有理由bytesRead
永远 >= size
,并且它在流的末尾行为不当。它应该是这样的:
while ((bytesRead = channel.read(buffer)) > 0)
{
bos.write(buffer.array(), 0, bytesRead);
buffer.clear();
}
通过适当的调整来限制传输到size
字节,这是非常重要的。
但是,在现有InputStream
上对所有这些进行分层不可能比直接使用InputStream
快得多,除非因为提前终止。除非你使用InputStream
的想法是你发布的,这是非常慢的。尝试使用“BufferedInputStream
。