views:

7348

answers:

3

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 or .pdf).

Existing Code:

StreamReader sr = new StreamReader(myOtherObject.InputStream);
  1. I need to save this to disk (I have the filename).
  2. In the future I may want to store this to SQL Server.

I have the encoding type also, which I will need if I store it to SQL Server, correct?

+16  A: 

You must not use StreamReader for binary files (like gifs or jpgs). StreamReader is for text data. You will almost certainly lose data if you use it for arbitrary binary data. (If you use Encoding.GetEncoding(28591) you will probably be okay, but what's the point?)

Why do you need to use a StreamReader at all? Why not just keep the binary data as binary data and write it back to disk (or SQL) as binary data?

EDIT: As this seems to be something people want to see... if you do just want to copy one stream to another (e.g. to a file) use something like this:

/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8 * 1024];
    int len;
    while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, len);
    }    
}

To use it to dump a stream to a file, for example:

using (Stream file = File.OpenWrite(filename))
{
    CopyStream(input, file);
}
Jon Skeet
John, the API I am using returns a Stream object of an attachment (pop3 component) so I want to have the option of saving to file or sqlserver. So if I call myAPI.SomeStream how would I store that do disk?? (thanks)
Loadman
A: 

I'm just best guessing here because I've never tried to push a stream to file, but I'm guessing that you can use a similar process as other data:

public void SaveFile(string fileName, Stream data) 
{
    using (BinaryWriter writer = new BinaryWriter(fileName)) {
        writer.Write(data);
    }      
}

Assuming the StreamWriter can handle a stream (can't imagine why it wouldn't be able to) then that's all you need.

EDIT - It turns out that StreamWriter handles text only and I'm not as smart as I thought.

thaBadDawg
StreamWriter can't handle a stream, because it's designed for *text* data, not binary data. If the above code were valid, however, it should use a "using" statement anyway to close the writer in case of exceptions.
Jon Skeet
Switched it over to the binary writer because as soon as read your comment I was reminded about how smart I really am :p
thaBadDawg
BinaryWriter.Write(Stream) doesn't exist either - but there's no real reason to use BinaryWriter here. I've updated my answer with a simple stream copier.
Jon Skeet
@Jon: I could never understand why the framework doesn't contain a Pump static method to copy one stream to another. As soon as you do anything with streams that quickly becomes a function you need to write. Have I said this before?
AnthonyWJones
Anthony: I'm not sure you've said it before, but it's been part of MiscUtil for quite a long time :) (That has more sophisticated overloads as well, to allow the buffer size to be specified etc.) MemoryStream has a WriteTo method though - handy and not well known IMO.
Jon Skeet
+3  A: 

Hello,

Why not use a FileStream object?

public void SaveStreamToFile(string fileFullPath, Stream stream)
{
    if (stream.Length == 0) return;

    // Create a FileStream object to write a stream to a file
    using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
    {
        // Fill the bytes[] array with the stream data
        byte[] bytesInStream = new byte[stream.Length];
        stream.Read(bytesInStream, 0, (int)bytesInStream.Length);

        // Use FileStream object to write to the specified file
        fileStream.Write(bytesInStream, 0, bytesInStream.Length);
     }
}
Adrian