Copy between two streams in .net 2.0

2019-05-02 02:46发布

问题:

I have been using the following code to Compress data in .Net 4.0:

public static byte[] CompressData(byte[] data_toCompress)
{

    using (MemoryStream outFile = new MemoryStream())
    {
        using (MemoryStream inFile = new MemoryStream(data_toCompress))
        using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
        {
            inFile.CopyTo(Compress);

        }
        return outFile.ToArray();
    }

}

However, in .Net 2.0 Stream.CopyTo method is not available. So, I tried making a replacement:

public static byte[] CompressData(byte[] data_toCompress)
{

    using (MemoryStream outFile = new MemoryStream())
    {
        using (MemoryStream inFile = new MemoryStream(data_toCompress))
        using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
        {
            //inFile.CopyTo(Compress);
            Compress.Write(inFile.GetBuffer(), (int)inFile.Position, (int)(inFile.Length - inFile.Position));
        }
        return outFile.ToArray();
    }

}

The compression fails, though, when using the above attempt - I get an error saying:

MemoryStream's internal buffer cannot be accessed.

Could anyone offer any help on this issue? I'm really not sure what else to do here.

Thank you, Evan

回答1:

Since you have access to the array already, why don't you do this:

using (MemoryStream outFile = new MemoryStream())
{
    using (GZipStream Compress = new GZipStream(outFile, CompressionMode.Compress))
    {
        Compress.Write(data_toCompress, 0, data_toCompress.Length);
    }
    return outFile.ToArray();
}

Most likely in the sample code you are using inFile.GetBuffer() will throw an exception since you do not use the right constructor - not all MemoryStream instances allow you access to the internal buffer - you have to look for this in the documentation:

Initializes a new instance of the MemoryStream class based on the specified region of a byte array, with the CanWrite property set as specified, and the ability to call GetBuffer set as specified.

This should work - but is not needed anyway in the suggested solution:

using (MemoryStream inFile = new MemoryStream(data_toCompress, 
                                              0, 
                                              data_toCompress.Length, 
                                              false, 
                                              true))


回答2:

This is the code straight out of .Net 4.0 Stream.CopyTo method (bufferSize is 4096):

byte[] buffer = new byte[bufferSize];
int count;
while ((count = this.Read(buffer, 0, buffer.Length)) != 0)
    destination.Write(buffer, 0, count);


回答3:

Why are you constructing a memory stream with an array and then trying to pull the array back out of the memory stream?

You could just do Compress.Write(data_toCompress, 0, data_toCompress.Length);

If you need to replace the functionality of CopyTo, you can create a buffer array of some length, read data from the source stream and write that data to the destination stream.



回答4:

You can try

infile.WriteTo(Compress);


回答5:

try to replace the line:

Compress.Write(inFile.GetBuffer(), (int)inFile.Position, (int)(inFile.Length - inFile.Position));

with:

Compress.Write(data_toCompress, 0, data_toCompress.Length);

you can get rid of this line completely:

using (MemoryStream inFile = new MemoryStream(data_toCompress))

Edit: find an example here: Why does gzip/deflate compressing a small file result in many trailing zeroes?



回答6:

You should manually read and write between these 2 streams:

    private static void CopyStream(Stream from, Stream to)
    {
        int bufSize = 1024, count;
        byte[] buffer = new byte[bufSize];
        count = from.Read(buffer, 0, bufSize);
        while (count > 0)
        {
            to.Write(buffer, 0, count);
            count = from.Read(buffer, 0, bufSize);
        }
    }


回答7:

The open-source NuGet package Stream.CopyTo implements Stream.CopyTo for all versions of the .NET Framework.

Available on GitHub and via NuGet (Install-Package Stream.CopyTo)