我试图将字符串转换为字节流,以便我可以读取所述流。所以我正在做的是将字符串转换为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。
我错过了一些基本的东西,还是另一种更明显的方法呢?
答案 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