【问题标题】:How can I tell that a stream has been read to the end?我怎么知道一个流已经读到最后?
【发布时间】:2009-04-05 15:59:35
【问题描述】:

我只是在编写一个简单的方法,从一般流中读取数据——这意味着它可能是 FileStream 或 NetworkStream 而不知道它的长度。我反复将流读入 byte[] 并将数据推送到另一个流或其他任何东西。我的问题是,我怎么能注意到流已经结束了?当 Read 方法返回 0 时,我尝试返回 - 这是正确的方法吗?读取文件好像没问题,但有时会遇到从网络读取数据的问题。

【问题讨论】:

    标签: .net stream


    【解决方案1】:

    是的,重复调用Read 并在它返回 0 时结束是完全正确的方法。

    网络流也可以这样做 - 它们会阻塞,直到接收到任何数据或流断开连接。查看Stream.Read的文档:

    只有当 位置目前在末尾 流。实施将 阻塞直到至少一个字节的数据 可以读取,在没有数据的情况下 可用。读取仅在以下情况下返回 0 流中没有更多数据 并且没有更多的预期(例如 关闭套接字或文件结尾)。

    【讨论】:

    • 那看来我们得知道网络流的数据长度了?
    • 知道长度会有所帮助,但这并不是绝对必要的。
    • 对于套接字,您实际上只有两个选择:具有固定格式的协议(即固定长度字段描述流中后面可变字段的长度),或使用分隔符(嵌入在流,告诉你什么时候停止)。
    • 其实还有第三个。您可能有一个固定长度的协议。即,所有字段都是 x 字节。
    • 我对 WebClient 类如何知道这一点非常感兴趣。
    【解决方案2】:

    对于网络流,如果 Stream.ReadByte() 返回小于 0 的值,则表明流已读到末尾。

    【讨论】:

    • 你的意思是我应该在 NetworkStream 的循环体中的 Read 方法之后立即调用 ReadByte() 方法吗?
    【解决方案3】:

    正如 Jon 所说,您知道这是文件的结尾,因为它将返回 0 个字节。但是,您还必须考虑可能引发的各种异常。因为网络本质上是不可靠的,所以总会有一些例外。

    例如,如果流断开连接(与另一端简单地关闭套接字相反),那么您可能会收到IOException 异常。始终将 I/O 调用包装在异常处理程序中,除非您绝对确定它们不会引发异常。

    【讨论】:

    • 仅仅因为它们可能会抛出异常并不意味着您应该将它们包装在处理程序中。根据我的经验,如果一个 IO 调用抛出 IOException,该调用的方法making 通常应该只允许异常冒泡。我往往只有很少的 try/catch 块 - 通常就在顶部附近。
    • 我不是说你必须马上抓住它。但它应该在某个时候被抓住。
    猜你喜欢
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 2021-05-17
    相关资源
    最近更新 更多