J'ai un StreamReader
objet que j'ai initialisé avec un flux, maintenant je veux enregistrer ce flux sur le disque (le flux peut être un .gif
ou .jpg
ou .pdf
).
Code existant:
StreamReader sr = new StreamReader(myOtherObject.InputStream);
- J'ai besoin de l'enregistrer sur le disque (j'ai le nom du fichier).
- À l'avenir, je voudrai peut-être stocker cela sur SQL Server.
J'ai également le type d'encodage, dont j'aurai besoin si je le stocke sur SQL Server, correct?
Réponses:
Comme l'a souligné Tilendor dans la réponse de Jon Skeet, les flux ont une
CopyTo
méthode depuis .NET 4.Ou avec la
using
syntaxe:la source
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
si vous n'êtes pas déjà au début ou si vous ne copiez pas le flux entier.Vous ne devez pas utiliser
StreamReader
pour les fichiers binaires (comme les gifs ou jpgs).StreamReader
est pour les données texte . Vous perdrez presque certainement des données si vous les utilisez pour des données binaires arbitraires. (Si vous utilisez Encoding.GetEncoding (28591), vous serez probablement d'accord, mais à quoi ça sert?)Pourquoi avez-vous besoin d'utiliser un
StreamReader
? Pourquoi ne pas simplement conserver les données binaires comme binaires et les réécrire sur le disque (ou SQL) en tant que données binaires?EDIT: Comme cela semble être quelque chose les gens veulent voir ... si vous ne voulez juste copier un flux à un autre (par exemple dans un fichier) utiliser quelque chose comme ceci:
Pour l'utiliser pour vider un flux dans un fichier, par exemple:
Notez que cela a
Stream.CopyTo
été introduit dans .NET 4, servant essentiellement le même objectif.la source
la source
stream
objetusing(){}
entre crochets. Votre méthode n'a pas créé le flux, elle ne doit donc pas en disposer.FileStream
place, sinon il restera ouvert jusqu'à ce qu'il soit récupéré.File.WriteAllBytes(destinationFilePath, input.ToArray());
. Dans mon cas,input
est unMemoryStream
venant de l'intérieur d'unZipArchive
.la source
File.WriteAllBytes(destinationFilePath, input.ToArray());
. Dans mon cas,input
est unMemoryStream
venant de l'intérieur d'unZipArchive
.stream.Seek(0, SeekOrigin.Begin);
Je n'obtiens pas toutes les réponses en utilisant
CopyTo
, où peut-être que les systèmes utilisant l'application n'ont peut-être pas été mis à niveau vers .NET 4.0+. Je sais que certains voudraient forcer les gens à mettre à niveau, mais la compatibilité est également très bien aussi.Une autre chose, je n'utilise pas un flux pour copier à partir d'un autre flux en premier lieu. Pourquoi ne pas simplement faire:
Une fois que vous avez les octets, vous pouvez facilement les écrire dans un fichier:
Ce code fonctionne comme je l'ai testé avec un
.jpg
fichier, mais j'avoue ne l'avoir utilisé qu'avec de petits fichiers (moins de 1 Mo). Un flux, pas de copie entre les flux, aucun encodage nécessaire, il suffit d'écrire les octets! Pas besoin de trop compliquer les chosesStreamReader
si vous avez déjà un flux avec lequel vous pouvez convertirbytes
directement.ToArray()
!Seuls les inconvénients potentiels que je peux voir en procédant de cette façon sont s'il y a un gros fichier que vous possédez, l'avoir comme flux et utiliser
.CopyTo()
ou équivalent permetFileStream
de le diffuser au lieu d'utiliser un tableau d'octets et de lire les octets un par un. En conséquence, cela pourrait être plus lent à faire de cette façon. Mais il ne devrait pas s'étouffer puisque la.Write()
méthode desFileStream
poignées écrivant les octets, et il ne le fait qu'un octet à la fois, donc il n'encombrera pas la mémoire, sauf que vous devrez avoir suffisamment de mémoire pour contenir le flux en tant quebyte[]
objet . Dans ma situation où j'utilisais cela, obtenir unOracleBlob
, je devais aller à unbyte[]
, c'était assez petit, et en plus, il n'y avait pas de streaming disponible pour moi, de toute façon, alors j'ai juste envoyé mes octets à ma fonction, ci-dessus.Une autre option, en utilisant un flux, serait de l'utiliser avec la
CopyStream
fonction de Jon Skeet qui était dans un autre post - cela permet simplementFileStream
de prendre le flux d'entrée et de créer le fichier directement à partir de celui-ci. Il n'utilise pasFile.Create
, comme il l'a fait (ce qui au départ semblait être problématique pour moi, mais a trouvé plus tard que c'était probablement juste un bug VS ...).la source
Close
cause deusing()
inputStream.Close()
, regardez à nouveau -inputStream
est envoyé en tant que variable. Leusing
est sur lepath+filename
flux de sortie. Si vous parliezfs.Close()
au milieu de lausing
, désolé, vous aviez raison à ce sujet et je l'ai supprimé.la source
Pourquoi ne pas utiliser un objet FileStream?
la source
byte[]
, je pense qu'il serait rare que vous diffusiez un blob de 1 Go + dans un fichier ... à moins que vous n'ayez un site qui conserve les torrents DVD ... Plus , la plupart des ordinateurs ont au moins 2 Go de RAM disponibles de nos jours, de toute façon .... La mise en garde est valide, mais je pense que c'est un cas où c'est probablement "assez bon" pour la plupart des travaux.Une autre option consiste à obtenir le flux
byte[]
et à l'utiliserFile.WriteAllBytes
. Cela devrait faire:L'encapsuler dans une méthode d'extension lui donne un meilleur nom:
la source
la source
FileStream
- sympa!Voici un exemple qui utilise les utilisations appropriées et l'implémentation de idisposable:
... et il y a aussi ça
La clé est de comprendre la bonne utilisation de l'utilisation (qui doit être implémentée lors de l'instanciation de l'objet qui implémente idisposable comme indiqué ci-dessus), et d'avoir une bonne idée de la façon dont les propriétés fonctionnent pour les flux. La position est littéralement l'index dans le flux (qui commence à 0) qui est suivi lorsque chaque octet est lu à l'aide de la méthode readbyte. Dans ce cas, je l'utilise essentiellement à la place d'une variable de boucle for et je la laisse simplement suivre jusqu'à la longueur qui est LITTÉRALEMENT la fin de l'ensemble du flux (en octets). Ignorez-le en octets car il est pratiquement le même et vous aurez quelque chose de simple et d'élégant comme celui-ci qui résout tout proprement.
Gardez également à l'esprit que la méthode ReadByte convertit simplement l'octet en entier dans le processus et peut simplement être reconvertie.
Je vais ajouter une autre implémentation que j'ai récemment écrite pour créer une sorte de tampon dynamique pour garantir l'écriture séquentielle des données afin d'éviter une surcharge massive
L'explication est assez simple: nous savons que nous devons garder à l'esprit l'ensemble des données que nous souhaitons écrire et aussi que nous ne voulons écrire que certains montants, nous voulons donc que la première boucle avec le dernier paramètre vide (identique à while ). Ensuite, nous initialisons un tampon de tableau d'octets qui est défini à la taille de ce qui est passé, et avec la deuxième boucle, nous comparons j à la taille du tampon et à la taille de l'original, et s'il est supérieur à la taille de l'original tableau d'octets, terminer l'analyse.
la source