将字符串转换为流

时间:2017-06-03 12:42:47

标签: f# .net-core

我试图将字符串转换为字节流,以便我可以读取所述流。所以我正在做的是将字符串转换为char数组并将每个char / byte写入MemoryStream,然后将其包装在BinaryReader中

我尝试实施它的方式是这样的:

let readData (data:string) = 
    let ms = new MemoryStream()
    let bw = new BinaryWriter(ms)
    data.ToCharArray() |> Array.iter (fun x -> bw.Write((byte)x))
    let br = new BinaryReader(bw.BaseStream)
    readStream 0 br

我后来试着像这样阅读

let rec readStream c (br:BinaryReader) =
    let bytes = br.ReadBytes 16
    printfn "Size read is: %i" bytes.Length

但是我的结果总是读取0字节,并且我已经验证字符串显然不是0字节。我已经尝试在MemoryStream上调用Flush。

我错过了一些基本的东西,还是另一种更明显的方法呢?

2 个答案:

答案 0 :(得分:9)

这是一种产生MemoryStream的非常低效的方法。特别是对于这种应用程序,它有一个带字节数组的构造函数:

let bytes = System.Text.Encoding.UTF8.GetBytes data
let stream = MemoryStream( bytes )

但即使 也可能是一种矫枉过正。您还没有描述您的最终目标,但是从您的代码中看起来您只想将字符串转换为字节数组。如果这是真的,那么您只需要Encoding.GetBytes

let readData (data:string) = System.Text.Encoding.UTF8.GetBytes data

在施法时

另请注意,当您执行(byte)x时,您显然希望这是一个“转换为字节”操作,就像在C#中一样,但事实并非如此。 F#中的“强制转换”操作表达方式不同(使用运算符:>:?>),它只能用于子/超类型(即继承的类和接口)。不适用于原语。在F#中没有投射基元类型的东西。

您实际在做的是调用名为byte函数。因此,那里不需要括号,F#中的函数参数用空格指定,即byte x

这个函数确实将char转换为一个字节,但它只是取char的第一个字节(字符是双字节的东西,你知道吗?)并扔掉第二个字节。当你的char是ASCII(第二个字节为零)时,这种方法很好,但是当它不是时会丢失数据。尝试转换为byte,然后返回char:

let x = 'a'
let y = char (byte x)
> val y : char = 'a'  // This worked

let x = 'Г'
let y = char (byte x)
> val y : char = '\019'  // Oops

答案 1 :(得分:2)

写到MemoryStream后,它的位置就在最后。您需要将位置重置为开头才能全部读取。您可以将其添加到readStream功能

的开头
br.BaseStream.Position <- 0L