【问题标题】:What is difference between "while (-1 != (len = in.read(b)))" and "while ((len = in.read(b)) > 0)" in Java IO?Java IO 中的“while (-1 != (len = in.read(b)))”和“while ((len = in.read(b)) > 0)”有什么区别?
【发布时间】:2019-02-15 13:19:01
【问题描述】:

我有这个(工作)代码:

BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
byte[] b = new byte[1024];
int len;
while (-1 != (len = in.read(b))) {
    fos.write(b, 0, len);
}
fos.flush();

但如果我将while (-1 != (len = in.read(b))) 更改为while ((len = in.read(b)) > 0),则流无法完成。这是为什么呢?

【问题讨论】:

  • 好吧,i > 0i != -1 的条件并不完全相同,在这种情况下,差别不大,只是应该在最后返回-1,但是i > 0 也可以停在 0
  • 所以...我已经用ByteArrayInputStream 对此进行了测试,以创建minimal reproducible example 并且两种解决方案都有效(如预期的那样)。您可以在不使用您的 url 连接的情况下提供minimal reproducible example 吗?
  • 对我来说,程序按预期工作并结束执行。你能详细说明一下吗
  • 这是一个没有思考的问题,而不是一个编程问题。

标签: java httpurlconnection java-io


【解决方案1】:

乍一看,这两个条件可能看起来非常不同。让我们重新排列它们,使(len = in.read(b)) 始终位于左侧:

(len = in.read(b)) != -1

(len = in.read(b)) > 0

表达式(len = in.read(b)) 的计算结果为in.read(b)。因此,这两个条件的唯一区别是第一个检查read 是否不返回-1,而第二个检查read 是否返回大于0 的值。

我们来看看what read can return

返回:

读入缓冲区的总字节数,如果由于已到达流的末尾而没有更多数据,则为 -1。

这意味着read 不会返回小于 -1 的任何值,这反过来意味着如果read 返回 0,则所讨论的两个条件只会计算出不同的值。但是看,read 只返回 0当没有读取字节时,唯一没有读取字节的时候是传入长度为 0 的数组时:

如果b的长度为零,则不读取字节,返回0; 否则,将尝试读取至少一个字节。如果没有字节 可用,因为流位于文件末尾,值 返回 -1;否则,至少读取一个字节并将其存储到 b 中。

您的数组具有恒定长度1024,因此在这种特殊情况下,这两个条件将产生相同的结果。

【讨论】:

  • 我完全同意这一点(好吧,谁能不同意文档),但这并不能回答问题。 “如果我将while (-1 != (len = in.read(b))) 更改为while ((len = in.read(b)) > 0),则流无法完成。这是为什么?”。奇怪的是,这让我们假设流永远不会返回-1,而是0,即使这个数组大小为 1024。
  • @AxelH 我会说 OP 代码的其他一些部分导致了问题。
  • 显然,但似乎只有我在等待minimal reproducible example
【解决方案2】:

根据documentations的方法InputSteam.read(byte[] b)

如果b的长度为零,则不读取字节,返回0; 否则,将尝试读取至少一个字节。如果没有字节 可用,因为流位于文件末尾,值 返回-1;否则,至少读取一个字节并将其存储到 b 中。

因此,基本上,当您使用 while ((len = in.read(b)) > 0) 时,如果 read() 返回 0(意味着最后一个读取字节的长度为 0),即使尚未到达流的末尾,您也将退出循环,并且,因此,仍有数据要读取(流未完成)。

【讨论】:

    【解决方案3】:

    您正在完全改变条件规则。第一条语句检查值是否与 -1 不匹配,因此您的新条件应满足值在 (-infinity,-1) 和 (-1, infinity) 范围内的要求

    (-1 != (len = in.read(b))) // read until reach end of stream
    (len = in.read(b)) > 0) // read until data are present but this is wrong
    

    改成:

    (len = in.read(b)) >= 0)
    

    我不知道为什么要改变这个条件。正如文档所说:

    返回读取的字节数,如果已到达流的末尾,则返回 -1。

    情况描述here

    【讨论】:

    • 指定0 的结果何时发生会很有趣。 InputStream doc 表示“如果 b 的长度为零,则不读取字节并返回 0;否则,将尝试读取至少一个字节。如果由于流位于末尾而没有可用字节文件,则返回值 -1;否则,至少读取一个字节并存储到 b。"它似乎允许0 结果的唯一时间是传入的缓冲区长度为零(这里不是这种情况)
    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2017-05-25
    • 2020-07-31
    • 2011-01-16
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    相关资源
    最近更新 更多