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:
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 copiar entre secuencias, sin codificación, ¡solo escriba los bytes! ¡No es necesario complicar demasiado las cosas StreamReader
si ya tiene una transmisión a la que puede convertir bytes
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 permite FileStream
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 los FileStream
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 como byte[]
objeto . En mi situación en la que usé esto, obteniendo 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 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 usa FileStream
para tomar el flujo de entrada y crear el archivo directamente. No se usa File.Create
, como lo hizo (lo que inicialmente parecía ser problemático para mí, pero luego descubrí que probablemente era solo un error 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();
}