F#从CryptoStream读取所有字节的最简便方法

问题描述

|| 我正在研究使用AesCryptoServiceProvider解密二进制数据的过程。对于最后一步,检索解密的数据并将其作为字节数组返回,我目前正在使用以下实现:
let rec streamBytes (s : CryptoStream) (b : int) = seq {
    if b >= 0 then
        yield byte b
        yield! streamBytes s (s.ReadByte()) }
streamBytes cryptoStream (cryptoStream.ReadByte())
|> Seq.toArray
它可以工作,但是对我来说感觉不“正确”。将CryptoStream.ReadByte()的结果作为参数传递给streamBytes(),然后在该递归调用中检查值是否似乎有点Rube Goldberg-y。有更好的方法吗?     

解决方法

逐字节排空流将非常慢。 如果您拥有.NET 4.0,那么最直接的方法是:
open System.IO

let readAllBytes (s : Stream) = 
    let ms = new MemoryStream()
    s.CopyTo(ms)
    ms.ToArray()
否则您需要手动重现CopyTo功能
let readAllBytes (s : Stream) =
    let ms = new MemoryStream()
    let buf = Array.zeroCreate 8192
    let rec impl () = 
        let read = s.Read(buf,buf.Length) 
        if read > 0 then 
            ms.Write(buf,read)
            impl ()
    impl ()
    ,是否有理由不使用
Read
而不是
ReadBytes
?似乎那将更加直接。否则,您的解决方案对我来说并不算太糟糕-API的设计非常有限,因为您需要使用返回值
ReadByte
来确定是否中断循环并确定要输出的值。这是一种替代实现:
[| let currentByte = ref 0
   let moveNext() = 
       currentByte := cryptoStream.ReadByte()
       !currentByte >= 0
   while moveNext() do
       yield byte !currentByte |]