far*_*ich 14 java sockets byte inputstream
希望使用inputStream在套接字上读取一些字节.服务器发送的字节数可能是可变的,客户端事先并不知道字节数组的长度.怎么可能完成?
byte b[];
sock.getInputStream().read(b);
这会导致Net BzEAnSZ出现"可能未初始化错误".救命.
d-l*_*ive 24
你需要扩大缓冲区根据需要,通过一次以字节为单位,1024块阅读在本示例代码我写了前一段时间
byte[] resultBuff = new byte[0];
byte[] buff = new byte[1024];
int k = -1;
while((k = sock.getInputStream().read(buff, 0, buff.length)) > -1) {
byte[] tbuff = new byte[resultBuff.length + k]; // temp buffer size = bytes already read + bytes last read
System.arraycopy(resultBuff, 0, tbuff, 0, resultBuff.length); // copy previous bytes
System.arraycopy(buff, 0, tbuff, resultBuff.length, k); // copy current lot
resultBuff = tbuff; // call the temp buffer as your result buff
}
System.out.println(resultBuff.length + " bytes read.");
return resultBuff;
Run Code Online (Sandbox Code Playgroud)
Vla*_*hev 14
假设发件人在数据末尾关闭流:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
while(true) {
int n = is.read(buf);
if( n < 0 ) break;
baos.write(buf,0,n);
}
byte data[] = baos.toByteArray();
Run Code Online (Sandbox Code Playgroud)
Chr*_*ett 11
读取一个int,它是接收的下一个数据段的大小.创建具有该大小的缓冲区,或使用宽敞的预先存在的缓冲区.读入缓冲区,确保它仅限于上述大小.冲洗并重复:)
如果你真的不像你说的那样事先知道大小,请阅读扩展的ByteArrayOutputStream,正如其他答案所提到的那样.但是,尺寸方法确实是最可靠的.
简单的答案是:
byte b[] = byte[BIG_ENOUGH];
int nosRead = sock.getInputStream().read(b);
Run Code Online (Sandbox Code Playgroud)
哪里BIG_ENOUGH
足够大.
但总的来说,这有一个很大的问题.不保证该read
方法返回另一端在单个调用中写入的所有内容.
如果nosRead
值是BIG_ENOUGH
,您的应用程序无法确定是否有更多字节要来; 另一端可能已发送完全BIG_ENOUGH
字节...或多于BIG_ENOUGH
字节.在前一种情况下,如果您尝试阅读,您的应用程序将阻止(永远).在后一种情况下,您的应用程序必须(至少)执行另一个应用程序read
以获取其余数据.
如果该nosRead
值小于BIG_ENOUGH
,则您的应用程序仍然不知道.它可能已收到所有内容,部分数据可能已被延迟(由于网络数据包碎片,网络数据包丢失,网络分区等),或者另一端可能已通过发送数据中途阻塞或崩溃.
最好的答案是你的应用程序需要事先知道要预期的字节数,或者"应用程序协议"需要以某种方式告诉它需要多少字节...或者所有字节都已发送.可能的方法是:
如果没有这些策略之一,您的应用程序就会被猜测,并且偶尔会出错.
小智 6
Without re-inventing the wheel, using Apache Commons:
IOUtils.toByteArray(inputStream);
Run Code Online (Sandbox Code Playgroud)
For example, complete code with error handling:
public static byte[] readInputStreamToByteArray(InputStream inputStream) {
if (inputStream == null) {
// normally, the caller should check for null after getting the InputStream object from a resource
throw new FileProcessingException("Cannot read from InputStream that is NULL. The resource requested by the caller may not exist or was not looked up correctly.");
}
try {
return IOUtils.toByteArray(inputStream);
} catch (IOException e) {
throw new FileProcessingException("Error reading input stream.", e);
} finally {
closeStream(inputStream);
}
}
private static void closeStream(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception e) {
throw new FileProcessingException("IO Error closing a stream.", e);
}
}
Run Code Online (Sandbox Code Playgroud)
Where FileProcessingException
is your app-specific meaningful RT exception that will travel uninterrupted to your proper handler w/o polluting the code in between.