How do I save a stream to a file in C#?

后端 未结 10 2402
我寻月下人不归
我寻月下人不归 2020-11-22 03:06

I have a StreamReader object that I initialized with a stream, now I want to save this stream to disk (the stream may be a .gif or .jpg

10条回答
  •  醉梦人生
    2020-11-22 03:53

    Here's an example that uses proper usings and implementation of idisposable:

    static void WriteToFile(string sourceFile, string destinationfile, bool append = true, int bufferSize = 4096)
    {
        using (var sourceFileStream = new FileStream(sourceFile, FileMode.OpenOrCreate))
        {
            using (var destinationFileStream = new FileStream(destinationfile, FileMode.OpenOrCreate))
            {
                while (sourceFileStream.Position < sourceFileStream.Length)
                {
                    destinationFileStream.WriteByte((byte)sourceFileStream.ReadByte());
                }
            }
        }
    }
    

    ...and there's also this

        public static void WriteToFile(FileStream stream, string destinationFile, int bufferSize = 4096, FileMode mode = FileMode.OpenOrCreate, FileAccess access = FileAccess.ReadWrite, FileShare share = FileShare.ReadWrite)
        {
            using (var destinationFileStream = new FileStream(destinationFile, mode, access, share))
            {
                while (stream.Position < stream.Length) 
                {
                    destinationFileStream.WriteByte((byte)stream.ReadByte());
                }
            }
        }
    

    The key is understanding the proper use of using (which should be implemented on the instantiation of the object that implements idisposable as shown above), and having a good idea as to how the properties work for streams. Position is literally the index within the stream (which starts at 0) that is followed as each byte is read using the readbyte method. In this case I am essentially using it in place of a for loop variable and simply letting it follow through all the way up to the length which is LITERALLY the end of the entire stream (in bytes). Ignore in bytes because it is practically the same and you will have something simple and elegant like this that resolves everything cleanly.

    Keep in mind, too, that the ReadByte method simply casts the byte to an int in the process and can simply be converted back.

    I'm gonna add another implementation I recently wrote to create a dynamic buffer of sorts to ensure sequential data writes to prevent massive overload

    private void StreamBuffer(Stream stream, int buffer)
    {
        using (var memoryStream = new MemoryStream())
        {
            stream.CopyTo(memoryStream);
            var memoryBuffer = memoryStream.GetBuffer();
    
            for (int i = 0; i < memoryBuffer.Length;)
            {
                var networkBuffer = new byte[buffer];
                for (int j = 0; j < networkBuffer.Length && i < memoryBuffer.Length; j++)
                {
                    networkBuffer[j] = memoryBuffer[i];
                    i++;
                }
                //Assuming destination file
                destinationFileStream.Write(networkBuffer, 0, networkBuffer.Length);
            }
        }
    }
    

    The explanation is fairly simple: we know that we need to keep in mind the entire set of data we wish to write and also that we only want to write certain amounts, so we want the first loop with the last parameter empty (same as while). Next, we initialize a byte array buffer that is set to the size of what's passed, and with the second loop we compare j to the size of the buffer and the size of the original one, and if it's greater than the size of the original byte array, end the run.

提交回复
热议问题