我在计算机上安装了服务器及其客户端(Android应用程序)。客户端将大文件发送到服务器(2934822字节)。那个客户代码:
this.socket_out = this.socket.getOutputStream();
ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream();
FileInputStream mFileInputStream = new FileInputStream(mFile);
while (true) {
byte[] i1 = new byte[65536];
int i2 = mFileInputStream.read(i1, 0, 65536);
Log.v("", "read=" + i2);
if (i2 < 0) {
mByteArrayOutputStream.close();
mFileInputStream.close();
break;
} else {
mByteArrayOutputStream.write(i1, 0, i2);
mByteArrayOutputStream.flush();
}
}
mFile.delete();
byte[] i1 = mByteArrayOutputStream.toByteArray();
Log.v("", "sent=" + i1.length);
this.socket_out.write(i1);
this.socket_out.flush();
并记录:
读取= 65536
读取= 65536
...
读取= 65536
读= 51238
发送= 2934822
这是服务器代码:
this.in = new DataInputStream(this.socket.getInputStream());
while (
byte[] i1 = new byte[65536];
int i2 = this.in.read(i1, 0, 65536);
if (i2 > -1) {
System.out.print(i2);
...
} else {
break;
}
}
标准输出:
12974 1440 1440 11520 1440 1440 1440 7200 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 11520 1440 1440 59040 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 1440 17280 ...
为什么DataInputStream
没有完全读取65536个字节?如何在b
的参数len
中设置的字节数DataInputStream.read(byte[] b, int off, int len)
最大计数中读取?谢谢。
答案 0 :(得分:1)
为什么DataInputStream没有完全读取65536字节?
因为read()
或Socket
或TCP的合同中没有任何内容表明它应该。
如何在字节数组中读取b在DataInputStream.read(byte [] b,int off,int len)中参数len中设置的最大计数?
如果必须,请使用DataInputStream.readFully()
,但没有任何意义,只有在发送端使用ByteArrayOutputStream
浪费时间和空间时才会有任何意义。在Java中复制流的标准方法如下:
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
您应该在两端使用此代码。
答案 1 :(得分:0)
这可能是因为网络MTU大小。在BufferedInputStream
周围使用DataInputStream
。
new BufferedInputStream(new DataInputStream(...
或者只需将DataInputStream
替换为BufferedInputStream
。或者以(new DataInputStream(new BufferedInputStream( )
为导向。这是装饰模式。
答案 2 :(得分:-1)
数据不会在缓冲区中神奇地出现。它实际上需要一段时间才能完成传输,程序执行速度比传输大文件要快。 while循环每次抓取缓冲区中当前可用的内容,即打印时的这些字节数。你可以使用
检查int availableBytes = in.available();
并且您可以等待并且不读取流,直到流中有一定数量的字节可用于读取,例如
while(in.available() <2000)
{}
但这是一种阻塞方法,会冻结您的服务器,直到字节到达。无论出于何种原因,它都将永远阻挡。
你也应该像那样初始化缓冲区
byte[] i1 = new byte[in.available()];
这样你就不会初始化比实际需要更多的资源,而且可以像这样阅读
in.read(i1);
没有连续检查if语句并且确切知道数据量是
i1.length
希望有所帮助