【问题标题】:(int a = DataInputStream.read(b, off, len)) less than (len) in many times(int a = DataInputStream.read(b, off, len)) 多次小于 (len)
【发布时间】:2016-11-19 09:57:19
【问题描述】:

我在计算机上有服务器,它是客户端(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 我在DataInputStream.read(byte[] b, int off, int len) 中的参数len 中设置的最大计数?谢谢。

【问题讨论】:

  • 可能是因为流来自网络,网络数据传输速度慢
  • 您的标题与您的问题无关。 read(buffer, offset, len) 的结果不可能大于 len
  • @EJP,我的英语不太好,抱歉。如果可以,将其更改为更正方差。
  • 放下它。您肯定知道足够的英语来知道“大于”和“小于”之间的区别吗?

标签: java android sockets stream


【解决方案1】:

为什么 DataInputStream 没有完全读取 65536 字节?

因为read(),或Socket,或TCP的合同中没有任何内容说它应该这样做。

如何让它读取我在 DataInputStream.read(byte[] b, int off, int len) 的参数 len 中设置的字节数组 b 的最大计数?

如果必须,请使用DataInputStream.readFully(),但这没有任何意义,就像在发送端使用ByteArrayOutputStream 浪费时间和空间一样。 Java中复制流的标准方法如下:

int count;
while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

您应该在两端都使用此代码。

【讨论】:

    【解决方案2】:

    这可能是因为网络 MTU 大小。在DataInputStream 周围使用BufferedInputStream

    new BufferedInputStream(new DataInputStream(...
    

    或者只是将DataInputStream替换为BufferedInputStream。或者在(new DataInputStream(new BufferedInputStream( ) 周围做相反的事情。这是装饰器模式。

    【讨论】:

    • hmm.. 我正在使用DataInputStream,因为使用方法readInt()readLine()。那我怎么能和BufferedInputStream一起使用呢?
    • 我试过new DataInputStream(new BufferedInputStream(...)) - 没有结果。
    • 网络非常好。接收 = 214mbit/秒;发送 = 218mbit/秒。
    • 刚刚尝试了您的第一个解决方案 - 没有结果。没有区别。
    • 好的。我等到星期一再拿到第二部电话。如果一切正常,我接受你的回答。但现在我也在等待其他解决方案。
    【解决方案3】:

    数据不会神奇地出现在缓冲区中。传输实际上需要时间,并且您的程序执行速度比传输大文件要快。 while 循环每次都会抓取缓冲区中当前可用的内容,即您打印的这些字节数。你可以检查使用

    int availableBytes = in.available();
    

    您可以等待而不读取流,直到流中有一定数量的字节可供读取,例如

    while(in.available() <2000)
    {}
    

    但这是一种阻塞方法,它将冻结您的服务器,直到字节到达。无论出于何种原因,它都会永远阻塞。

    你也应该像这样初始化你的缓冲区

    byte[] i1 = new byte[in.available()];
    

    这样您就不会初始化比实际需要更多的资源,并且可以像这样读取

    in.read(i1);
    

    没有通过 if 语句的持续检查,并且确切地知道数据量是

    i1.length
    

    希望有帮助

    【讨论】:

    • 我就是这么说的,你太热心了。我只是向他展示了一种等待一定数量到达的方法(如果他绝对必须)并说它将“抽 CPU”直到数据到达,你的意思是什么?然后我说他应该初始化并处理当前可用的内容,然后继续前进,直到缓冲区中有更多内容而不是阻塞。仅供参考, available() 单独是非阻塞的,而 (in.available()
    • 无论如何都不是你说的。你说这是一种阻塞方法。这是一种投票方式。你说的是“冻结”,而不是“烟雾”。这些都是完全不同的东西。如果你不知道阻塞和轮询之间的区别,你根本不应该回答 I/O 问题,你应该问他们。实现此代码只有一种合理的方法,即阻塞读取,而这一事实无论如何都不依赖于 OP。发布毫无意义的替代方案是毫无意义的,并声称你没有用黑白的方式说出你在上面所说的内容是不诚实的。
    • 好吧,如果我们在这里讨论技术问题,没有像抽 CPU 这样的事情,这通常是在发生物理损坏的时候发生的......而且这个家伙离任何生产都不远,他正在经历一个陡峭的学习曲线……我知道你在说什么,投票的重点是他可能会想出打印可用字节,看看为什么他每次循环和实验都会得到小块数据他最终会摆脱它......但不,你只是想要正确的答案,而不考虑他的问题的本质
    • 如果你真的认为只有一种做事方式,其余的都是毫无意义的......我相信你一无所知。当然有更好的方法,但是,这是由情况决定的,在他的情况下不是在寻找文件
    • 这里唯一可以确定的是您不了解阻塞和轮询之间的区别,或者不准备承认您让他们感到困惑。两次。 “他的问题的本质”需要正确的答案,而不是无关紧要或错误陈述。我很乐意随时与你的“无知”进行辩论,但到目前为止真的没有什么可辩论的。
    猜你喜欢
    • 2011-06-08
    • 2014-10-08
    • 1970-01-01
    • 2011-06-13
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多