Ich habe ein StreamReader
Objekt, das ich mit einem Stream initialisiert habe. Jetzt möchte ich diesen Stream auf der Festplatte speichern (der Stream kann ein .gif
oder .jpg
oder sein .pdf
).
Bestehender Code:
StreamReader sr = new StreamReader(myOtherObject.InputStream);
- Ich muss dies auf der Festplatte speichern (ich habe den Dateinamen).
- In Zukunft möchte ich dies möglicherweise in SQL Server speichern.
Ich habe auch den Codierungstyp, den ich benötige, wenn ich ihn auf SQL Server speichere, richtig?
Antworten:
Wie Tilendor in Jon Skeets Antwort hervorgehoben hat, haben Streams
CopyTo
seit .NET 4 eine Methode.Oder mit der
using
Syntax:quelle
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
wenn Sie noch nicht am Anfang stehen oder nicht den gesamten Stream kopieren möchten.Sie müssen nicht verwenden
StreamReader
für binäre Dateien (wie GIF oder JPG - Dateien).StreamReader
ist für Textdaten . Sie werden mit ziemlicher Sicherheit Daten verlieren, wenn Sie sie für beliebige Binärdaten verwenden. (Wenn Sie Encoding.GetEncoding (28591) verwenden, sind Sie wahrscheinlich in Ordnung, aber worum geht es?)Warum brauchen Sie
StreamReader
überhaupt eine? Warum nicht einfach die Binärdaten als Binärdaten behalten und als Binärdaten auf die Festplatte (oder SQL) zurückschreiben?EDIT: Da dies scheint etwas die Leute sehen wollen sein ... , wenn Sie es nur einen Stream in einen anderen kopieren möchten (zB in einer Datei) Verwendung etwas wie folgt aus :
So verwenden Sie es zum Speichern eines Streams in eine Datei, zum Beispiel:
Beachten Sie, dass dies
Stream.CopyTo
in .NET 4 eingeführt wurde und im Wesentlichen demselben Zweck dient.quelle
quelle
stream
Objekt wahrscheinlich nicht in dieusing(){}
Klammer setzen. Ihre Methode hat den Stream nicht erstellt, daher sollte er nicht entsorgt werden.FileStream
stattdessen verwenden, sonst bleibt es offen, bis der Müll gesammelt wird.File.WriteAllBytes(destinationFilePath, input.ToArray());
. In meinem Fallinput
kommt einMemoryStream
aus einemZipArchive
.quelle
File.WriteAllBytes(destinationFilePath, input.ToArray());
. In meinem Fallinput
kommt einMemoryStream
aus einemZipArchive
.stream.Seek(0, SeekOrigin.Begin);
Ich erhalte nicht alle Antworten mit
CopyTo
, wobei die Systeme, die die App verwenden, möglicherweise nicht auf .NET 4.0+ aktualisiert wurden. Ich weiß, einige möchten die Leute zum Upgrade zwingen, aber die Kompatibilität ist auch gut.Eine andere Sache ist, dass ich überhaupt keinen Stream verwende, um von einem anderen Stream zu kopieren. Warum nicht einfach machen:
Sobald Sie die Bytes haben, können Sie sie einfach in eine Datei schreiben:
Dieser Code funktioniert so, wie ich ihn mit einer
.jpg
Datei getestet habe , obwohl ich zugeben muss, dass ich ihn nur mit kleinen Dateien (weniger als 1 MB) verwendet habe. Ein Stream, kein Kopieren zwischen Streams, keine Codierung erforderlich, schreiben Sie einfach die Bytes! Sie müssen die Dinge nicht zu kompliziert machen,StreamReader
wenn Sie bereits einen Stream haben, in den Siebytes
direkt konvertieren können.ToArray()
!Die einzigen möglichen Nachteile, die ich auf diese Weise erkennen kann, sind, wenn Sie eine große Datei haben. Wenn Sie sie als Stream haben und sie verwenden
.CopyTo()
oder gleichwertig verwenden, können SieFileStream
sie streamen, anstatt ein Byte-Array zu verwenden und die Bytes einzeln zu lesen. Infolgedessen könnte es auf diese Weise langsamer sein. Es sollte jedoch nicht ersticken, da die.Write()
Methode derFileStream
Handles die Bytes schreibt, und es wird jeweils nur ein Byte ausgeführt, sodass der Speicher nicht verstopft wird, außer dass Sie über genügend Speicher verfügen müssen, um den Stream als zu speichernbyte[]
Objekt . In meiner Situation, in der ich dies verwendet habe,OracleBlob
musste ich zu einem gehenbyte[]
, es war klein genug, und außerdem stand mir sowieso kein Streaming zur Verfügung, also habe ich meine Bytes einfach an meine Funktion oben gesendet.Eine andere Möglichkeit, einen Stream zu verwenden, besteht darin, ihn mit Jon Skeets
CopyStream
Funktion zu verwenden, die sich in einem anderen Beitrag befand. Hiermit wird lediglichFileStream
der Eingabestream verwendet und die Datei direkt daraus erstellt. Es wird nicht verwendetFile.Create
, wie er es tat (was anfangs für mich problematisch schien, aber später feststellte, dass es wahrscheinlich nur ein VS-Fehler war ...).quelle
Close
wegenusing()
inputStream.Close()
, schauen Sie noch einmal -inputStream
wird als Variable gesendet. Dasusing
ist impath+filename
Ausgabestream. Wenn Siefs.Close()
mitten im gesprochen habenusing
, tut mir leid, Sie hatten Recht damit, und ich habe das entfernt.quelle
Warum nicht ein FileStream-Objekt verwenden?
quelle
byte[]
, aber ich denke, es ist selten, dass Sie einen 1 GB + Blob in eine Datei streamen ... es sei denn, Sie haben eine Site, auf der DVD-Torrents gespeichert sind ... Plus Die meisten Computer verfügen heutzutage sowieso über mindestens 2 GB RAM. Vorbehalt ist gültig, aber ich denke, dies ist ein Fall, in dem es wahrscheinlich "gut genug" für die meisten Jobs ist.Eine andere Möglichkeit ist, den Stream zu einem zu bringen
byte[]
und zu verwendenFile.WriteAllBytes
. Dies sollte tun:Wenn Sie es in eine Erweiterungsmethode einschließen, erhalten Sie eine bessere Benennung:
quelle
quelle
FileStream
- nice!Hier ist ein Beispiel, das die ordnungsgemäße Verwendung und Implementierung von idisposable verwendet:
... und da ist auch das
Der Schlüssel besteht darin, die ordnungsgemäße Verwendung von using zu verstehen (die bei der Instanziierung des Objekts implementiert werden sollte, das wie oben gezeigt idisposable implementiert), und eine gute Vorstellung davon zu haben, wie die Eigenschaften für Streams funktionieren. Die Position ist buchstäblich der Index innerhalb des Streams (der bei 0 beginnt), dem gefolgt wird, wenn jedes Byte mit der Readbyte-Methode gelesen wird. In diesem Fall verwende ich es im Wesentlichen anstelle einer for-Schleifenvariablen und lasse es einfach bis zu der Länge durchlaufen, die buchstäblich das Ende des gesamten Streams ist (in Bytes). Ignorieren Sie in Bytes, da es praktisch dasselbe ist und Sie etwas Einfaches und Elegantes wie dieses haben, das alles sauber auflöst.
Beachten Sie auch, dass die ReadByte-Methode das Byte dabei einfach in ein int umwandelt und einfach zurückkonvertiert werden kann.
Ich werde eine weitere Implementierung hinzufügen, die ich kürzlich geschrieben habe, um eine Art dynamischen Puffer zu erstellen, um sequentielle Datenschreibvorgänge sicherzustellen und eine massive Überlastung zu verhindern
Die Erklärung ist ziemlich einfach: Wir wissen, dass wir den gesamten Datensatz berücksichtigen müssen, den wir schreiben möchten, und dass wir nur bestimmte Mengen schreiben möchten. Daher möchten wir, dass die erste Schleife mit dem letzten Parameter leer ist (wie während) ). Als nächstes initialisieren wir einen Byte-Array-Puffer, der auf die Größe des übergebenen Objekts eingestellt ist, und vergleichen mit der zweiten Schleife j mit der Größe des Puffers und der Größe des Originals, und wenn er größer als die Größe des Originals ist Byte-Array, beenden Sie den Lauf.
quelle