当 inputStream 对象先前已包装在 BufferedReader 中时,为什么 InputStream.read() 抛出 "Read timed out" 异常?
Why does InputStream.read() throw "Read timed out" exception when the inputStream object has previously been wrapped in a BufferedReader?
我有一个来自套接字的 inputStream 对象。
这个流可以是纯文本,也可以包含二进制数据。它有一个纯文本 "prefix" 告诉我它有哪种类型的数据。我使用 BufferedReader 读取该前缀。然后,如果数据类型是纯文本,我继续使用 BufferedReader 读取其余部分,效果很好。
问题是当我切换回使用 InputStream 时如果前缀指示非文本数据。流似乎在某处丢失了,我得到的是 java.net.SocketTimeoutException: Read timed out
。
代码是这样的:
InputStream instream = mysocket.getInputStream();
BufferedReader br = (new InputStreamReader(instream, "UTF-8")));
byte[] prefixArray = new byte[4];
br.read(prefixArray, 0, 4);
String prefix = new String(prefixArray);
if("text".equals(prefix)) {
// continue to use br.read() here, which works fine...
}else{
byte[] barray = new byte[arraysize]
instream.read(barray, 0, arraysize); // THROWS "Read timed out" exception
}
这是不允许的吗?一旦instream
被包裹在BufferedReader
中,就不能直接使用了吗?
一个BufferedReader
从一个Reader
中读取数据并将数据存储在缓冲区中以供后续读取使用。它一次读取尽可能多的内容,每次缓冲区清空时,它都会向缓冲区中读取更多内容。
您的二进制读取超时,因为 BufferedReader
已经读取了您尝试读取的字节。
检测流类型只需要4个字节。对这 4 个字节使用 Reader
是多余的。首先直接从InputStream
中读取字节,然后只为text
数据创建一个Reader
,例如:
InputStream instream = mysocket.getInputStream();
byte[] prefixArray = new byte[4];
int offset = 0;
int numread;
do
{
numread = instream.read(prefixArray, offset, 4-offset);
if (numread == -1) return;
offset += numread;
}
while (offset < 4);
String prefix = new String(prefixArray);
if ("text".equals(prefix))
{
BufferedReader br = new BufferedReader(new InputStreamReader(instream, "UTF-8"));
//...
}
else
{
byte[] barray = new byte[arraysize];
// consider using BufferedInputStream here ...
do
{
numread = instream.read(barray, 0, arraysize);
if (numread == -1) break;
//...
}
while (true);
}
或者,考虑使用 BufferedInputStream
进行套接字读取,并根据需要在其上添加其他 类,例如:
InputStream instream = mysocket.getInputStream();
BufferedInputStream bis = new BufferedInputStream(instream);
byte[] prefixArray = new byte[4];
DataInputStream dis = new DataInputStream(bis);
dis.readFully(prefixArray);
String prefix = new String(prefixArray);
if ("text".equals(prefix))
{
InputStreamReader isr = new InputStreamReader(bis, "UTF-8"));
//...
}
else
{
byte[] barray = new byte[arraysize];
do
{
numread = bis.read(barray, 0, arraysize);
if (numread == -1) break;
//...
}
while (true);
}
我有一个来自套接字的 inputStream 对象。
这个流可以是纯文本,也可以包含二进制数据。它有一个纯文本 "prefix" 告诉我它有哪种类型的数据。我使用 BufferedReader 读取该前缀。然后,如果数据类型是纯文本,我继续使用 BufferedReader 读取其余部分,效果很好。
问题是当我切换回使用 InputStream 时如果前缀指示非文本数据。流似乎在某处丢失了,我得到的是 java.net.SocketTimeoutException: Read timed out
。
代码是这样的:
InputStream instream = mysocket.getInputStream();
BufferedReader br = (new InputStreamReader(instream, "UTF-8")));
byte[] prefixArray = new byte[4];
br.read(prefixArray, 0, 4);
String prefix = new String(prefixArray);
if("text".equals(prefix)) {
// continue to use br.read() here, which works fine...
}else{
byte[] barray = new byte[arraysize]
instream.read(barray, 0, arraysize); // THROWS "Read timed out" exception
}
这是不允许的吗?一旦instream
被包裹在BufferedReader
中,就不能直接使用了吗?
一个BufferedReader
从一个Reader
中读取数据并将数据存储在缓冲区中以供后续读取使用。它一次读取尽可能多的内容,每次缓冲区清空时,它都会向缓冲区中读取更多内容。
您的二进制读取超时,因为 BufferedReader
已经读取了您尝试读取的字节。
检测流类型只需要4个字节。对这 4 个字节使用 Reader
是多余的。首先直接从InputStream
中读取字节,然后只为text
数据创建一个Reader
,例如:
InputStream instream = mysocket.getInputStream();
byte[] prefixArray = new byte[4];
int offset = 0;
int numread;
do
{
numread = instream.read(prefixArray, offset, 4-offset);
if (numread == -1) return;
offset += numread;
}
while (offset < 4);
String prefix = new String(prefixArray);
if ("text".equals(prefix))
{
BufferedReader br = new BufferedReader(new InputStreamReader(instream, "UTF-8"));
//...
}
else
{
byte[] barray = new byte[arraysize];
// consider using BufferedInputStream here ...
do
{
numread = instream.read(barray, 0, arraysize);
if (numread == -1) break;
//...
}
while (true);
}
或者,考虑使用 BufferedInputStream
进行套接字读取,并根据需要在其上添加其他 类,例如:
InputStream instream = mysocket.getInputStream();
BufferedInputStream bis = new BufferedInputStream(instream);
byte[] prefixArray = new byte[4];
DataInputStream dis = new DataInputStream(bis);
dis.readFully(prefixArray);
String prefix = new String(prefixArray);
if ("text".equals(prefix))
{
InputStreamReader isr = new InputStreamReader(bis, "UTF-8"));
//...
}
else
{
byte[] barray = new byte[arraysize];
do
{
numread = bis.read(barray, 0, arraysize);
if (numread == -1) break;
//...
}
while (true);
}