Search code examples
vb.netfilestreammemorystream

How can I write to a FileStream from a Memorystream starting from a non-zero position?


I need to write from a Memorystream to a simple Filestream. The problem is that my memorystream holds the file name and its sequence of bytes separated with a "|". So it is something like this: name.extension|BYTES. The code I use to write now is:

Dim j As Integer = 1
    Dim name As String
    name = ""
    ms.Read(temp, 0, 1)
    Do While (UTF8.GetString(temp, 0, 1) <> "|")
        name += UTF8.GetString(temp, 0, 1)
        j += 1
        ms.Read(temp, 0, 1)
    Loop

That's how I get the name of the file and this:

Dim fs As FileStream = File.Create(sf.FileName()) 'SaveFileDialog
        ms.Seek(j, SeekOrigin.Begin) 'starting to write after "|" char

        Do
            ms.Read(temp, 0, 1)
            fs.Write(temp, 0, 1)
            j += 1
        Loop While ms.Length - j <> 0 'YES... byte after byte

        fs.Close()
        fs.Dispose()
        ms.close()
        ms.Dispose()

is how I write the file. I know that there may be things that could have been written better, but that's why I am asking your help. I tried to use MememoryStream.WriteTo(FileStream) but it starts writing from the file name too. Can the code be improved? Thanks a lot!


Solution

  • After reading on Mark's suggestion, I think his approach is much better. Streams were meant to be hooked up to each other, so don't do manually what the framework was made to do. Here's a test that worked.

    using (var ms = new MemoryStream())
    {
        //Prepare test data.
        var text = "aFileName.txt|the content";
        var bytes = Encoding.UTF8.GetBytes(text);
        ms.Write(bytes, 0, bytes.Length);
        //Seek back to origin to simulate a fresh stream
        ms.Seek(0, SeekOrigin.Begin);
    
        //Read until you've consumed the | or you run out of stream.
        var oneByte = 0;
        while (oneByte >= 0 && Convert.ToChar(oneByte) != '|')
        {
            oneByte = ms.ReadByte();
        }
    
        //At this point you've consumed the filename and the pipe.
        //Your memory stream is now at the proper position and you
        //can simply tell it to dump its content into the filestream.
        using (var fs = new FileStream("test.txt", FileMode.Create))
        {
            ms.CopyTo(fs);
        }
    }
    

    Note that streams are disposable objects. Instead of closing and disposing, you should use the 'using' construct as that will take care of it for you, even if an exception is thrown.