How do I copy the contents of one stream to another?

后端 未结 13 2338
悲哀的现实
悲哀的现实 2020-11-21 22:11

What is the best way to copy the contents of one stream to another? Is there a standard utility method for this?

相关标签:
13条回答
  • 2020-11-21 22:36

    I use the following extension methods. They have optimized overloads for when one stream is a MemoryStream.

        public static void CopyTo(this Stream src, Stream dest)
        {
            int size = (src.CanSeek) ? Math.Min((int)(src.Length - src.Position), 0x2000) : 0x2000;
            byte[] buffer = new byte[size];
            int n;
            do
            {
                n = src.Read(buffer, 0, buffer.Length);
                dest.Write(buffer, 0, n);
            } while (n != 0);           
        }
    
        public static void CopyTo(this MemoryStream src, Stream dest)
        {
            dest.Write(src.GetBuffer(), (int)src.Position, (int)(src.Length - src.Position));
        }
    
        public static void CopyTo(this Stream src, MemoryStream dest)
        {
            if (src.CanSeek)
            {
                int pos = (int)dest.Position;
                int length = (int)(src.Length - src.Position) + pos;
                dest.SetLength(length); 
    
                while(pos < length)                
                    pos += src.Read(dest.GetBuffer(), pos, length - pos);
            }
            else
                src.CopyTo((Stream)dest);
        }
    
    0 讨论(0)
  • 2020-11-21 22:36

    if you want a procdure to copy a stream to other the one that nick posted is fine but it is missing the position reset, it should be

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        long TempPos = input.Position;
        while (true)    
        {
            int read = input.Read (buffer, 0, buffer.Length);
            if (read <= 0)
                return;
            output.Write (buffer, 0, read);
        }
        input.Position = TempPos;// or you make Position = 0 to set it at the start
    }
    

    but if it is in runtime not using a procedure you shpuld use memory stream

    Stream output = new MemoryStream();
    byte[] buffer = new byte[32768]; // or you specify the size you want of your buffer
    long TempPos = input.Position;
    while (true)    
    {
        int read = input.Read (buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write (buffer, 0, read);
     }
        input.Position = TempPos;// or you make Position = 0 to set it at the start
    
    0 讨论(0)
  • 2020-11-21 22:36

    For .NET 3.5 and before try :

    MemoryStream1.WriteTo(MemoryStream2);
    
    0 讨论(0)
  • 2020-11-21 22:41

    The following code to solve the issue copy the Stream to MemoryStream using CopyTo

    Stream stream = new MemoryStream();
    

    //any function require input the stream. In mycase to save the PDF file as stream document.Save(stream);

    MemoryStream newMs = (MemoryStream)stream;
    
    byte[] getByte = newMs.ToArray();
    

    //Note - please dispose the stream in the finally block instead of inside using block as it will throw an error 'Access denied as the stream is closed'

    0 讨论(0)
  • 2020-11-21 22:43

    From .NET 4.5 on, there is the Stream.CopyToAsync method

    input.CopyToAsync(output);
    

    This will return a Task that can be continued on when completed, like so:

    await input.CopyToAsync(output)
    
    // Code from here on will be run in a continuation.
    

    Note that depending on where the call to CopyToAsync is made, the code that follows may or may not continue on the same thread that called it.

    The SynchronizationContext that was captured when calling await will determine what thread the continuation will be executed on.

    Additionally, this call (and this is an implementation detail subject to change) still sequences reads and writes (it just doesn't waste a threads blocking on I/O completion).

    From .NET 4.0 on, there's is the Stream.CopyTo method

    input.CopyTo(output);
    

    For .NET 3.5 and before

    There isn't anything baked into the framework to assist with this; you have to copy the content manually, like so:

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            output.Write (buffer, 0, read);
        }
    }
    

    Note 1: This method will allow you to report on progress (x bytes read so far ...)
    Note 2: Why use a fixed buffer size and not input.Length? Because that Length may not be available! From the docs:

    If a class derived from Stream does not support seeking, calls to Length, SetLength, Position, and Seek throw a NotSupportedException.

    0 讨论(0)
  • 2020-11-21 22:43

    Easy and safe - make new stream from original source:

        MemoryStream source = new MemoryStream(byteArray);
        MemoryStream copy = new MemoryStream(byteArray);
    
    0 讨论(0)
提交回复
热议问题