如何检测F#中的流结束?

时间:2013-01-07 01:15:44

标签: asynchronous f# stream

我有一个F#函数,如下所示:

open System.IO
open Microsoft.FSharp.Control.CommonExtensions

let rec copyData (ins:Stream) (outs:Stream) = async {   
    let! bytes = ins.AsyncRead(1)
    do! outs.AsyncWrite(bytes)
    return! moveData ins outs
}

ins流到达结尾时,它会抛出AtEndOfStream异常。所以我必须在调用函数中捕获它。如何通过检测流当前结束来阻止此异常?

2 个答案:

答案 0 :(得分:7)

您在此处使用的AsyncRead重载会尝试准确读取您指定的字节数(如果它到达末尾则会失败,因为它无法读取指定的字节数)。

或者,您可以使用带缓冲区的重载并返回读取的字节数:

let rec copyData (ins:Stream) (outs:Stream) = async {   
  let buffer = Array.zeroCreate 1024
  let! bytes = ins.AsyncRead(buffer)
  if bytes > 0 then
    do! outs.AsyncWrite(buffer, 0, bytes)
    return! moveData ins outs
}

此重载不会在流的末尾抛出异常,而是返回0(并且它不会将任何内容写入缓冲区)。因此,您只需检查读取的字节数是否大于0,否则停止。

如果在调用copyData之前已经关闭了流,那么您需要检查CanRead或处理异常,但如果在调用AsyncRead之前流已打开,那么您'我只会回来0。

答案 1 :(得分:1)

只需检查CanRead属性,如下所示:

let rec copyData (ins:Stream) (outs:Stream) = async {
    if ins.CanRead then
        let! bytes = ins.AsyncRead(1)
        do! outs.AsyncWrite(bytes)
        return! moveData ins outs
}