Não recebo todas as respostas usando CopyTo
, onde talvez os sistemas que usam o aplicativo talvez não tenham sido atualizados para o .NET 4.0+. Sei que alguns gostariam de forçar as pessoas a atualizar, mas a compatibilidade também é boa.
Outra coisa, eu não uso um fluxo para copiar de outro fluxo em primeiro lugar. Por que não fazer:
byte[] bytes = myOtherObject.InputStream.ToArray();
Depois de ter os bytes, você pode gravá-los facilmente em um arquivo:
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();
}
}
Esse código funciona como eu testei com um .jpg
arquivo, embora admita que o usei apenas com arquivos pequenos (menos de 1 MB). Um fluxo, sem copiar entre fluxos, sem necessidade de codificação, basta escrever os bytes! Não há necessidade de complicar demais as coisas StreamReader
se você já tiver um fluxo com o qual possa converter bytes
diretamente .ToArray()
!
Somente possíveis desvantagens que posso ver dessa maneira é que se você tiver um arquivo grande, tê-lo como um fluxo e usar .CopyTo()
ou equivalente permite FileStream
transmiti-lo em vez de usar uma matriz de bytes e ler os bytes um a um. Como resultado, pode ser mais lento fazê-lo dessa maneira. Mas não deve engasgar, já que o .Write()
método dos FileStream
manipuladores escreve os bytes e apenas o executa um byte de cada vez, para que não obstrua a memória, exceto que você terá que ter memória suficiente para manter o fluxo como um byte[]
objeto . Na minha situação em que usei isso, obtendo um OracleBlob
, tive que ir para um byte[]
, era pequeno o suficiente e, além disso, não havia streaming disponível para mim, de qualquer maneira, então acabei de enviar meus bytes para minha função acima.
Outra opção, usando um fluxo, seria usá-lo com a CopyStream
função de Jon Skeet que estava em outro post - isso apenas usa FileStream
o fluxo de entrada e cria o arquivo diretamente dele. Ele não usa File.Create
, como ele fez (o que inicialmente parecia problemático para mim, mas depois descobriu que provavelmente era apenas um bug do 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();
}