Tengo un StreamReader
objeto que inicialicé con una secuencia, ahora quiero guardar esta secuencia en el disco (la secuencia puede ser una .gif
o .jpg
o .pdf
).
Código existente:
StreamReader sr = new StreamReader(myOtherObject.InputStream);
- Necesito guardar esto en el disco (tengo el nombre del archivo).
- 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?
Respuestas:
Como lo destacó Tilendor en la respuesta de Jon Skeet, las transmisiones tienen un
CopyTo
método desde .NET 4.O con la
using
sintaxis:fuente
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
si aún no está al principio o si no copiará toda la transmisión.No debe usar
StreamReader
archivos binarios (como gifs o jpgs).StreamReader
es para datos de texto . Es casi ciertamente pérdidas de 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
? ¿Por qué no simplemente mantener los datos binarios como datos binarios y volver a escribirlos en el disco (o SQL) como datos binarios?EDIT: Como esto parece ser algo que la gente quiere ver ... si usted no sólo quiere copiar una secuencia a otra (por ejemplo, a un archivo) usar algo como esto:
Para usarlo para volcar una secuencia en un archivo, por ejemplo:
Tenga en cuenta que
Stream.CopyTo
se introdujo en .NET 4, que sirve básicamente para el mismo propósito.fuente
fuente
stream
objeto entreusing(){}
corchetes. Su método no creó la secuencia, por lo que no debería deshacerse de ella.FileStream
lugar, debe utilizarlo, de lo contrario, se mantendrá abierto hasta que se recolecte la basura.File.WriteAllBytes(destinationFilePath, input.ToArray());
. En mi caso,input
es unaMemoryStream
que viene de dentro de unaZipArchive
.fuente
File.WriteAllBytes(destinationFilePath, input.ToArray());
. En mi caso,input
es unaMemoryStream
que viene de dentro de unaZipArchive
.stream.Seek(0, SeekOrigin.Begin);
No obtengo todas las respuestas usando
CopyTo
, donde quizás los sistemas que usan la aplicación podrían no haberse actualizado a .NET 4.0+. Sé que a algunos les gustaría obligar a las personas a actualizar, pero la compatibilidad también es agradable.Otra cosa, no consigo usar una secuencia para copiar desde otra secuencia en primer lugar. ¿Por qué no simplemente hacer:
Una vez que tenga los bytes, puede escribirlos fácilmente en un archivo:
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 copiar entre secuencias, sin codificación, ¡solo escriba los bytes! ¡No es necesario complicar demasiado las cosasStreamReader
si ya tiene una transmisión a la que puede convertirbytes
directamente.ToArray()
!Las únicas desventajas potenciales que puedo ver al hacerlo de esta manera es si hay un archivo grande que tiene, tenerlo como una secuencia y usar
.CopyTo()
o equivalente permiteFileStream
transmitirlo en lugar de usar 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 el.Write()
método de losFileStream
manejadores escribe 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 secuencia comobyte[]
objeto . En mi situación en la que usé esto, obteniendo unOracleBlob
, tuve que ir a unbyte[]
, era lo suficientemente pequeño, y además, no había transmisión disponible para mí, de todos modos, así que simplemente envié mis bytes a mi función, arriba.Otra opción, usar un flujo, sería usarlo con la
CopyStream
función de Jon Skeet que estaba en otra publicación; esto solo se usaFileStream
para tomar el flujo de entrada y crear el archivo directamente. No se usaFile.Create
, como lo hizo (lo que inicialmente parecía ser problemático para mí, pero luego descubrí que probablemente era solo un error VS ...).fuente
Close
porusing()
inputStream.Close()
, mire de nuevo:inputStream
se envía como una variable. Elusing
está en lapath+filename
secuencia de salida. Si estabas hablandofs.Close()
en medio deusing
, lo siento, estabas en lo correcto y lo eliminé.fuente
¿Por qué no usar un objeto FileStream?
fuente
byte[]
, creo que sería raro que transmitieras un blob de 1 GB + a un archivo ... a menos que tengas un sitio que mantenga torrents de DVD ... Además , la mayoría de las computadoras tienen al menos 2 GB de RAM disponibles en estos días, de todos modos ... La advertencia es válida, pero creo que este es un caso en el que probablemente sea "lo suficientemente bueno" para la mayoría de los trabajos.Otra opción es llevar la transmisión a ay
byte[]
usarlaFile.WriteAllBytes
. Esto debería hacer:Envolverlo en un método de extensión le da un mejor nombre:
fuente
fuente
FileStream
- ¡bien!Aquí hay un ejemplo que usa los usos adecuados y la implementación de idisposable:
... y también hay esto
La clave es comprender el uso adecuado del uso (que debe implementarse en la creación de instancias del objeto que implementa idisposable como se muestra arriba) y tener una buena idea de cómo funcionan las propiedades para las secuencias. La posición es literalmente el índice dentro de la secuencia (que comienza en 0) que se sigue a medida que se lee cada byte utilizando el método readbyte. En este caso, esencialmente lo uso en lugar de una variable de bucle for y simplemente dejo que siga hasta la longitud que es LITERALMENTE el final de toda la secuencia (en bytes). Ignora en bytes porque es prácticamente lo mismo y tendrás algo simple y elegante como este que resuelve todo limpiamente.
Tenga en cuenta también que el método ReadByte simplemente convierte el byte a un int en el proceso y simplemente puede volver a convertirlo.
Agregaré otra implementación que escribí recientemente para crear una especie de búfer dinámico que garantice la escritura secuencial de datos para evitar una sobrecarga masiva
La explicación es bastante simple: sabemos que debemos tener en cuenta todo el conjunto de datos que deseamos escribir y también que solo queremos escribir ciertas cantidades, por lo que queremos que el primer bucle con el último parámetro esté vacío (igual que while ) A continuación, inicializamos un búfer de matriz de bytes que se establece en el tamaño de lo que se pasa, y con el segundo bucle comparamos j con el tamaño del búfer y el tamaño del original, y si es mayor que el tamaño del original conjunto de bytes, finaliza la ejecución.
fuente