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 .jpgarchivo, 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 StreamReadersi ya tiene una transmisión a la que puede convertir bytesdirectamente .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 FileStreamtransmitirlo 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 FileStreammanejadores 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 CopyStreamfunción de Jon Skeet que estaba en otra publicación; esto solo se usa FileStreampara 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();
}