c# - savefiledialog1 - visual studio 2010 open file dialog




Come posso salvare un flusso su un file in C#? (6)

Ho un oggetto StreamReader che ho inizializzato con uno stream, ora voglio salvare questo flusso su disco (lo stream può essere un .gif o .jpg o .pdf ).

Codice esistente:

StreamReader sr = new StreamReader(myOtherObject.InputStream);
  1. Ho bisogno di salvare questo su disco (ho il nome del file).
  2. In futuro potrei voler memorizzare questo su SQL Server.

Ho anche il tipo di codifica, che mi servirà se lo memorizzo su SQL Server, corretto?


Come evidenziato da Tilendor nella risposta di Jon Skeet, gli stream hanno un metodo CopyTo da .NET 4.

var fileStream = File.Create("C:\\Path\\To\\File");
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin);
myOtherObject.InputStream.CopyTo(fileStream);
fileStream.Close();

O con la sintassi using :

using (var fileStream = File.Create("C:\\Path\\To\\File"))
{
    myOtherObject.InputStream.Seek(0, SeekOrigin.Begin);
    myOtherObject.InputStream.CopyTo(fileStream);
}

Non devi usare StreamReader per i file binari (come gif o jpg). StreamReader è per dati di testo . Quasi certamente perderete i dati se lo usate per dati binari arbitrari. (Se usi Encoding.GetEncoding (28591) probabilmente starai bene, ma qual è il punto?)

Perché hai bisogno di usare uno StreamReader ? Perché non mantenere solo i dati binari come dati binari e scriverli su disco (o SQL) come dati binari?

EDIT: Poiché sembra essere qualcosa che le persone vogliono vedere ... se vuoi semplicemente copiare uno stream in un altro (ad esempio in un file) usa qualcosa di simile:

/// <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);
    }    
}

Per usarlo per scaricare un flusso su un file, ad esempio:

using (Stream file = File.Create(filename))
{
    CopyStream(input, file);
}

Si noti che Stream.CopyTo stato introdotto in .NET 4, che ha sostanzialmente lo stesso scopo.


Perché non utilizzare un oggetto FileStream?

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);
     }
}

Un'altra opzione è quella di ottenere lo stream su un byte[] e utilizzare File.WriteAllBytes . Questo dovrebbe fare:

using (var stream = new MemoryStream())
{
    input.CopyTo(stream);
    File.WriteAllBytes(file, stream.ToArray());
}

Il suo avvolgimento in un metodo di estensione dà una migliore denominazione:

public void WriteTo(this Stream input, string file)
{
    //your fav write method:

    using (var stream = File.Create(file))
    {
        input.CopyTo(stream);
    }

    //or

    using (var stream = new MemoryStream())
    {
        input.CopyTo(stream);
        File.WriteAllBytes(file, stream.ToArray());
    }

    //whatever that fits.
}

private void SaveFileStream(String path, Stream stream)
{
    var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
    stream.CopyTo(fileStream);
    fileStream.Dispose();
}

public void CopyStream(Stream stream, string destPath)
{
  using (var fileStream = new FileStream(destPath, FileMode.Create, FileAccess.Write))
  {
    stream.CopyTo(fileStream);
  }
}




stream