我正在创建一个简单的套接字应用程序,通过TCP连接我的服务器。我有时需要读取2个字节的值,所以它们都像:
public byte[] read(int bytes)
{
byte b[] = new byte[bytes];
try {
in.read(b); //in is InputStream from properly connected Socket.getInputStream()
return b;
} catch (IOException e) {
return null;
}
}
此函数应接收给定的字节数并将其返回数组。问题是,有时它在休息可用之前读取一个字节并返回奇怪的数据。
byte a[]=read(2); //Program is blocked here untill some bytes arrive...
System.out.prntln(a[0]); //always correct
System.out.prntln(a[1]); //unprintable character (probably 0 or -1)
我的快速解决方法是添加while循环检查是否有足够的数据来读取:
public byte[] read(int bytes)
{
byte b[] = new byte[bytes];
try {
while (in.available()<bytes); //It does the thing
in.read(b);
return b;
} catch (IOException e) {
return null;
}
}
但是这个循环使用100%的处理器能力(实际上是一个核心),这非常烦人。有没有办法重写该函数(param和返回值必须完全相同)才能正常工作?
提前Thanx:)
答案 0 :(得分:7)
是。你的快速解决方案是一个坏主意。事实上,任何使用available
的代码都可能被破坏。
以下是我如何做到这一点:
public byte[] read(int bytes) throws IOException {
byte b[] = new byte[bytes];
int pos = 0;
while (pos < b.length) {
int nosRead = in.read(b, pos, b.length - pos);
if (nosRead == -1) {
return null; // Not the best idea ... see below.
} else {
pos += nosRead;
}
}
return b;
}
无需使用available()
“轮询”流。没有必要睡觉。你只是利用read
只有在读取了至少一个字节或者你已经适合“流的结尾”的情况下才会返回的事实。
请注意,如果您的null
方法失败,我也认为退回read
是不对的。最好抛出异常......或者让IOException
调用中的in.read()
传播。
这也适用于我的重写...我不想在这方面改变你的代码行为。
答案 1 :(得分:2)
扔掉它并使用DataInputStream.readFully()。