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

Ear*_*ine 1 f# asynchronous 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
}
Run Code Online (Sandbox Code Playgroud)

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

Tom*_*cek 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
}
Run Code Online (Sandbox Code Playgroud)

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

如果在调用之前已经关闭了流,copyData那么你需要检查CanRead或处理异常,但是如果在调用之前流是打开的AsyncRead,那么你只需要返回0.