Eu tenho um StreamReader
objeto que eu inicializei com um fluxo, agora quero salvar esse fluxo no disco (o fluxo pode ser um .gif
ou .jpg
ou.pdf
).
Código existente:
StreamReader sr = new StreamReader(myOtherObject.InputStream);
- Eu preciso salvar isso em disco (eu tenho o nome do arquivo).
- No futuro, talvez eu queira armazenar isso no SQL Server.
Também tenho o tipo de codificação, necessário para armazená-lo no SQL Server, correto?
Respostas:
Conforme destacado por Tilendor na resposta de Jon Skeet, os fluxos têm um
CopyTo
método desde o .NET 4.Ou com a
using
sintaxe:fonte
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
se ainda não estiver no início ou se não copiará o fluxo inteiro.Você não deve usar
StreamReader
para arquivos binários (como gifs ou jpgs).StreamReader
é para dados de texto . Você quase certamente perderá dados se usá-los para dados binários arbitrários. (Se você usar Encoding.GetEncoding (28591), provavelmente ficará bem, mas qual é o objetivo?Por que você precisa usar um
StreamReader
? Por que não apenas manter os dados binários como dados binários e gravá-los no disco (ou SQL) como dados binários?EDIT: Como este parece ser algo que as pessoas querem ver ... se você não apenas quer copiar um fluxo para outro (por exemplo, para um arquivo) usar algo como isto:
Para usá-lo para despejar um fluxo em um arquivo, por exemplo:
Observe que
Stream.CopyTo
foi introduzido no .NET 4, atendendo basicamente ao mesmo objetivo.fonte
fonte
stream
objeto nousing(){}
suporte. Seu método não criou o fluxo, portanto não deve descartá-lo.FileStream
usar, caso contrário, ele será mantido aberto até que seja coletado o lixo.File.WriteAllBytes(destinationFilePath, input.ToArray());
. No meu caso,input
é umaMemoryStream
vinda de dentro de umZipArchive
.fonte
File.WriteAllBytes(destinationFilePath, input.ToArray());
. No meu caso,input
é umaMemoryStream
vinda de dentro de umZipArchive
.stream.Seek(0, SeekOrigin.Begin);
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:
Depois de ter os bytes, você pode gravá-los facilmente em um arquivo:
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 coisasStreamReader
se você já tiver um fluxo com o qual possa converterbytes
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 permiteFileStream
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 dosFileStream
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 umbyte[]
objeto . Na minha situação em que usei isso, obtendo umOracleBlob
, tive que ir para umbyte[]
, 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 usaFileStream
o fluxo de entrada e cria o arquivo diretamente dele. Ele não usaFile.Create
, como ele fez (o que inicialmente parecia problemático para mim, mas depois descobriu que provavelmente era apenas um bug do VS ...).fonte
Close
por causa de #using()
inputStream.Close()
, olhe novamente -inputStream
é enviado como uma variável. Ousing
está nopath+filename
fluxo de saída. Se você estava falandofs.Close()
no meiousing
, desculpe, você estava certo sobre isso e eu removi isso.fonte
Por que não usar um objeto FileStream?
fonte
byte[]
, acho que seria raro que você estivesse transmitindo um blob de 1 GB + para um arquivo ... a menos que você tenha um site que mantenha torrents em DVD ... , a maioria dos computadores tem pelo menos 2 GB de RAM disponível atualmente, de qualquer maneira ... A ressalva é válida, mas acho que esse é um caso em que provavelmente é "bom o suficiente" para a maioria dos trabalhos.Outra opção é obter o fluxo para um
byte[]
e usarFile.WriteAllBytes
. Isso deve fazer:O agrupamento em um método de extensão fornece uma melhor nomeação:
fonte
fonte
FileStream
- bom!Aqui está um exemplo que usa usos adequados e implementação de idisposable:
... e há também isso
A chave é entender o uso adequado do uso (que deve ser implementado na instanciação do objeto que implementa o idisposable, como mostrado acima), e ter uma boa idéia de como as propriedades funcionam para fluxos. Posição é literalmente o índice dentro do fluxo (que começa em 0) que é seguido à medida que cada byte é lido usando o método readbyte. Neste caso, eu estou essencialmente usando-o no lugar de uma variável de loop for e simplesmente deixando-o seguir até o comprimento que é literalmente o fim de todo o fluxo (em bytes). Ignore em bytes, porque é praticamente o mesmo e você terá algo simples e elegante como esse que resolve tudo de forma limpa.
Lembre-se também de que o método ReadByte simplesmente converte o byte para um int no processo e pode simplesmente ser convertido novamente.
Vou adicionar outra implementação que escrevi recentemente para criar um tipo de buffer dinâmico para garantir gravações seqüenciais de dados para evitar sobrecarga maciça
A explicação é bastante simples: sabemos que precisamos ter em mente todo o conjunto de dados que desejamos escrever e também que queremos apenas escrever certas quantidades; portanto, queremos que o primeiro loop com o último parâmetro esteja vazio (o mesmo que enquanto ) Em seguida, inicializamos um buffer de matriz de bytes definido como o tamanho do que é passado e, com o segundo loop, comparamos j com o tamanho do buffer e o tamanho do original, e se for maior que o tamanho do original matriz de bytes, finalize a execução.
fonte