I'm trying to convert a string into a bytestream so that I can read said stream. So what I'm doing is that I convert the string into a char array and the write each char/byte into a MemoryStream which I later wrap in a BinaryReader
The way I've tried to implement it is like this:
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
I later try to read it like this
let rec readStream c (br:BinaryReader) =
let bytes = br.ReadBytes 16
printfn "Size read is: %i" bytes.Length
But my result is always 0 bytes read, and I've verified that the string is not 0 bytes obviously. And I've tried calling Flush on the MemoryStream.
Am I missing something fundamental or is the another more obvious way to do this?
This is a terribly inefficient way of producing a MemoryStream
. Specifically for this kind of application, it has a constructor that takes a byte array:
let bytes = System.Text.Encoding.UTF8.GetBytes data
let stream = MemoryStream( bytes )
But even that may be an overkill. You haven't described your ultimate goal, but from your code it kind of looks like you just want to convert a string to a byte array. If that is true, all you need is just Encoding.GetBytes
:
let readData (data:string) = System.Text.Encoding.UTF8.GetBytes data
.
Also note that when you do (byte)x
, you apparently expect this to be a "convert to byte" operation, as in C#, but it's not. The "casting" operation in F# is expressed differently (with operators :>
and :?>
), and it can only be used for sub/supertypes (i.e. inherited classes and interfaces). Doesn't apply to primitives. There is no such thing as casting primitive types in F#.
What you're actually doing is calling a function called byte
. So the parentheses are not needed there, function arguments in F# are specified with a space, i.e. byte x
.
This function does indeed convert a char to a byte, but it does so by just taking the first byte of the char (chars are two-byte things, did you know?) and throwing away the second byte. This works fine when your char is ASCII (second byte is zero anyway), but will lose data when it's not. Try converting to byte and then back to 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
After writing to the MemoryStream
, it's position is at the end. You need to reset the position to the start to read it all. You could add this to the start of your readStream
function
br.BaseStream.Position <- 0L
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With