views:

2781

answers:

2

suppose this code (C#):

using (MemoryStream stream = new MemoryStream())
{
    StreamWriter normalWriter = new StreamWriter(stream);
    BinaryWriter binaryWriter = new BinaryWriter(stream);

    foreach(...)
    {
        binaryWriter.Write(number);
        normalWriter.WriteLine(name); //<~~ easier to reader afterward.
    }

    return MemoryStream.ToArray();
}

questions are:

  1. Do I need to use flush inside the loop to preserve order?
  2. Is returning MemoryStream.ToArray() legal? I using using as a convention, I'm afraid it will mess things up.
+4  A: 

Scratch the previous answer - I hadn't noticed that you were using two wrappers around the same stream. That feels somewhat risky to me.

Either way, I'd put the StreamWriter and BinaryWriter in their own using blocks.

Oh, and yes, it's legal to call ToArray() on the MemoryStream - the data is retained even after it's disposed.

If you really want to use the two wrappers, I'd do it like this:

using (MemoryStream stream = new MemoryStream())
{
    using (StreamWriter normalWriter = new StreamWriter(stream))
    using (BinaryWriter binaryWriter = new BinaryWriter(stream))
    {
        foreach(...)
        {
            binaryWriter.Write(number);
            binaryWriter.Flush();
            normalWriter.WriteLine(name); //<~~ easier to read afterward.
            normalWriter.Flush();
        }
    }    
    return MemoryStream.ToArray();
}

I have to say, I'm somewhat wary of using two wrappers around the same stream though. You'll have to keep flushing each of them after each operation to make sure you don't end up with odd data. You could set the StreamWriter's AutoFlush property to true to mitigate the situation, and I believe that BinaryWriter currently doesn't actually require flushing (i.e. it doesn't buffer any data) but relying on that feels risky.

If you have to mix binary and text data, I'd use a BinaryWriter and explicitly write the bytes for the string, fetching it with Encoding.GetBytes(string).

Jon Skeet
Wrapping one stream with two stream writers does seem dangerous/error prone though I don't think flushing them will do anything in this case. Flush doesn't affect the reading of the MemoryStream, only the writing of the buffered bytes into their respective streams.
GoodEnough
It affects the order in which the values may be written though - unless you set AutoFlush to true, StreamWriter may not write anything to the MemoryStream for a long time (or *ever* if you don't dispose it). It just feels brittle to me.
Jon Skeet
the thing is, I want a newline at the end of the the name, and WriteLine seems the safe way to so so.
Nefzen
"Flush doesn't affect the reading of the MemoryStream, only the writing of the buffered bytes into their respective streams" .... but that's exactly what the OP is doing... writing.
dss539
@Nefzen - see Environment.NewLine http://msdn.microsoft.com/en-us/library/system.environment.newline.aspx
dss539
@dss539 - but will that be read when using readline every time?
Nefzen
@Nefzen: Using ReadLine is going to be dodgy with a StreamReader anyway, if you're mixing it with binary data. ReadLine will read into an internal buffer, consuming some of that binary data. Mixing text and binary data without a well-defined container (e.g. length-prefixing the text having indicated that there *will* be text) is always tricky.
Jon Skeet
binary data is constant in length - 32 bit.I came at a new problem - in the other side, I want to read the line, yes? well, if I use StreamReader, I'm not sure what encoding it is using, and if I use BinaryReader, I need to find the end of line. Hmm, maybe I should use '\0'.
Nefzen
@dss539 the buffer will be filled in the correct order so flushing or not, the bytes will be written in the correct order.
GoodEnough
A: 

Update

Nevermind this answer, I got confused with the writers...


  1. No, the order will be preserved (update: maybe not). Flush is useful/needed in other situations, though I can't remember when.
  2. I think so, using makes sure everything cleans up nicely.
GoodEnough
I don't think the order *will* necessarily be preserved, between the binary writer and the stream writer here - you may end up with a load of values from the binary writer and then the next buffer's worth of the stream writer.
Jon Skeet
1. No the order won't be preserved.2. No the `using` does not `Dispose()` normalWriter or binaryWriter.
dss539
Both writers share the same buffer?
GoodEnough
@Crossbrowser: No - the BinaryWriter doesn't know about the StreamWriter or vice versa. The StreamWriter has its own buffer.
Jon Skeet
Dam, I was so confused, I kept focusing on the writer part not thinking that one of the writers took his source from what the other wrote in the stream. In that case, I think only the first flush is necessary.
GoodEnough