Pregunta ¿Cómo guardo una secuencia en un archivo en C #?


tengo un StreamReader objeto que inicié con una secuencia, ahora quiero guardar esta secuencia en el disco (la transmisión puede ser una .gif o .jpg o .pdf)

Código existente:

StreamReader sr = new StreamReader(myOtherObject.InputStream);
  1. Necesito guardar esto en el disco (tengo el nombre del archivo).
  2. En el futuro, es posible que desee almacenar esto en SQL Server.

También tengo el tipo de codificación, que necesitaré si lo almaceno en SQL Server, ¿correcto?


587
2018-01-04 20:04


origen


Respuestas:


Como destacó Tilendor en la respuesta de Jon Skeet, las transmisiones tienen una CopyTo método desde .NET 4.

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

O con el using sintaxis:

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

761
2018-04-01 16:01



no debe utilizar StreamReader para archivos binarios (como gifs o jpgs). StreamReader es para texto datos. Usted casi ciertamente perder datos si lo usa para datos binarios arbitrarios. (Si usa Encoding.GetEncoding (28591) probablemente estará bien, pero ¿cuál es el punto?)

¿Por qué necesitas usar un StreamReader ¿en absoluto? ¿Por qué no mantener los datos binarios? como datos binarios y escribirlo de nuevo en el disco (o SQL) como datos binarios?

EDITAR: como esto parece ser algo que la gente quiere ver ... si hacer solo quiere copiar una secuencia a otra (por ejemplo, a un archivo) use algo como esto:

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

Para usarlo para volcar una secuencia a un archivo, por ejemplo:

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

Tenga en cuenta que Stream.CopyTo fue introducido en .NET 4, que básicamente tiene el mismo propósito.


474
2018-01-04 20:08



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

57
2017-08-01 20:25



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

18
2017-12-11 14:38



//If you don't have .Net 4.0  :)

public void SaveStreamToFile(Stream stream, string filename)
{  
   using(Stream destination = File.Create(filename))
      Write(stream, destination);
}

//Typically I implement this Write method as a Stream extension method. 
//The framework handles buffering.

public void Write(Stream from, Stream to)
{
   for(int a = from.ReadByte(); a != -1; a = from.ReadByte())
      to.WriteByte( (byte) a );
}

/*
Note, StreamReader is an IEnumerable<Char> while Stream is an IEnumbable<byte>.
The distinction is significant such as in multiple byte character encodings 
like Unicode used in .Net where Char is one or more bytes (byte[n]). Also, the
resulting translation from IEnumerable<byte> to IEnumerable<Char> can loose bytes
or insert them (for example, "\n" vs. "\r\n") depending on the StreamReader instance
CurrentEncoding.
*/

9
2017-07-07 14:30



¿Por qué no usar un objeto 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);
     }
}

7
2018-04-23 22:49



public void testdownload(stream input)
{
    byte[] buffer = new byte[16345];
    using (FileStream fs = new FileStream(this.FullLocalFilePath,
                        FileMode.Create, FileAccess.Write, FileShare.None))
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
             fs.Write(buffer, 0, read);
        }
    }
}

5
2017-07-16 06:47



No consigo todas las respuestas usando CopyTo, donde quizás los sistemas que usan la aplicación no se hayan actualizado a .NET 4.0+. Sé que a algunos les gustaría obligar a las personas a actualizarse, pero la compatibilidad también es agradable.

Otra cosa, en primer lugar, no consigo usar una secuencia para copiar desde otra secuencia. Por qué no solo hacer:

byte[] bytes = myOtherObject.InputStream.ToArray();

Una vez que tenga los bytes, puede escribirlos fácilmente en un archivo:

public static void WriteFile(string fileName, byte[] bytes)
{
    string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    if (!path.EndsWith(@"\")) path += @"\";

    if (File.Exists(Path.Combine(path, fileName)))
        File.Delete(Path.Combine(path, fileName));

    using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
    {
        fs.Write(bytes, 0, (int)bytes.Length);
        fs.Close();
    }
}

Este código funciona como lo he probado con un .jpg archivo, aunque admito que solo lo he usado con archivos pequeños (menos de 1 MB). Una secuencia, sin copia entre las secuencias, sin codificación, ¡simplemente escriba los bytes! No hay necesidad de complicar demasiado las cosas con StreamReader si ya tiene una transmisión, puede convertir a bytes directamente con .ToArray()!

Solo las posibles desventajas que puedo ver al hacerlo de esta manera es si hay un archivo grande que tiene, lo tiene como una secuencia y está usando .CopyTo() o equivalente permite FileStream para transmitirlo en lugar de utilizar una matriz de bytes y leer los bytes uno por uno. Puede ser más lento hacerlo de esta manera, como resultado. Pero no debería ahogarse ya que .Write() método de la FileStream maneja la escritura de los bytes, y solo lo hace un byte a la vez, por lo que no obstruirá la memoria, excepto que tendrá que tener suficiente memoria para mantener la transmisión como una byte[] objeto. En mi situación en que usé esto, obtener un OracleBlob, Tuve que ir a un byte[], era lo suficientemente pequeño, y además, no había transmisión disponible para mí, de todos modos, así que acabo de enviar mis bytes a mi función, arriba.

Otra opción, usar una secuencia, sería usarla con Jon Skeet's CopyStreamfunción que estaba en otra publicación - esto solo usa FileStream tomar la secuencia de entrada y crear el archivo directamente desde allí. No usa File.Create, como lo hizo él (que inicialmente parecía ser problemático para mí, pero luego descubrí que probablemente solo era un error de VS ...).

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

public static void WriteFile(string fileName, Stream inputStream)
{
    string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    if (!path.EndsWith(@"\")) path += @"\";

    if (File.Exists(Path.Combine(path, fileName)))
        File.Delete(Path.Combine(path, fileName));

    using (FileStream fs = new FileStream(Path.Combine(path, fileName), FileMode.CreateNew, FileAccess.Write)
    {
        CopyStream(inputStream, fs);
    }

    inputStream.Close();
    inputStream.Flush();
}

5
2017-10-12 13:57



Otra opción es llevar la transmisión a un byte[] y use File.WriteAllBytes. Esto debería hacer:

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

Envolverlo en un método de extensión le da un mejor nombre:

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.
}

4
2018-02-13 11:04