(int a = DataInputStream.read(b,off,len))多次小于(len)

时间:2016-11-19 09:57:19

标签: java android sockets stream

我在计算机上安装了服务器及其客户端(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)最大计数中读取?谢谢。

3 个答案:

答案 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

希望有所帮助