Stream.CopyTo not copying any stream data
Asked Answered
A

3

22

I'm having an issue with copying data from a MemoryStream into a Stream inside a ZipArchive. The following is NOT working - it returns only 114 bytes:

GetDataAsByteArray(IDataSource dataSource)
{
    using (var zipStream = new MemoryStream())
    {
        using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
        {
            var file = archive.CreateEntry("compressed.file");
            using (var targetStream = file.Open())
            {
                using (var sourceStream = new MemoryStream())
                {
                    await dataSource.LoadIntoStream(sourceStream);
                    sourceStream.CopyTo(targetStream);
                }
            }
        }
        var result = zipStream.ToArray();
        zipStream.Close();
        return result;
    }
}

However, using the implementation below for the "copy"-process, all 1103 bytes are written to the array/memory stream:

await targetStream.WriteAsync(sourceStream.ToArray(), 0, (int) sourceStream.Length);

I'm wondering why the CopyTo yields less bytes. Also I'm feeling unsecure with the cast to Int32 in the second implementation.

FYI: Comparing the byte array: It looks like only the header and footer of the zip file were written by the first implementation.

Airlia answered 4/8, 2014 at 15:29 Comment(0)
M
65

Stream.CopyTo() starts copying from the stream's current Position. Which probably isn't 0 after that LoadIntoStream() call. Since it is a MemoryStream, you can simply fix it like this:

    await dataSource.LoadIntoStream(sourceStream);
    sourceStream.Position = 0;
    sourceStream.CopyTo(targetStream);
Miticide answered 4/8, 2014 at 15:53 Comment(2)
Thank you Hans!! 6 years later, still a helpful post.Berman
Yes, thank you Hans. 7 years later now. Also note that if you have the base class Stream (not specifically MemoryStream), then you use this: justAStream.Seek(0, SeekOrigin.Begin);Woolsey
H
10

Set sourceStream.Position = 0 before copying it. The copy will copy from the current position to the end of the stream.

Hostelry answered 4/8, 2014 at 15:53 Comment(0)
J
2

As other have said the Position is probably no longer 0. You can't always set the Position back to 0 though, such as for Network and Compressed streams. You should check the stream.CanSeek property before doing any operations and if it is false then copy the stream to a new MemoryStream first (which can be seeked) and then after each operation which changes the position set the Position back to 0.

Jabot answered 8/11, 2018 at 5:10 Comment(2)
The original problem was that copying is not working because of the position. So you suggest to copy it first :D? Or am I missing something?Cockchafer
@fl034 copy it to a memory stream first and then use the memory stream rather than the original stream. Not, do something with it first which changes the position and then try to copy it from the original stream. That won't work.Jabot

© 2022 - 2024 — McMap. All rights reserved.