SpeicherStream.WriteTo (Stream destinationStream) versus Stream.CopyTo (Stream destinationStream)

7

Welche ist besser: MemoryStream.WriteTo(Stream destinationStream) oder Stream.CopyTo(Stream destinationStream) ??

Ich spreche über den Vergleich dieser beiden Methoden ohne Buffer, da ich so vorgehe:

%Vor%

Aktualisieren

Hier ist, was ich tun möchte:

  • Datei öffnen [Sagen Sie "X" Type File]
  • Parsen Sie den Inhalt
  • Von hier bekomme ich eine Menge neuer Streams [3 ~ 4 Dateien]
  • Parsen Sie einen Stream
  • Tausende von Dateien extrahieren [Der Stream ist eine Bilddatei]
  • Speichern Sie die anderen Streams in Dateien
  • Bearbeiten aller Dateien
  • Erstellen Sie eine neue Datei vom Typ "X".

Ich habe jedes Bit Code geschrieben, der tatsächlich korrekt funktioniert.

Aber jetzt optimiere ich den Code, um den effizientesten zu machen.

    
Writwick 19.05.2012, 10:42
quelle

6 Antworten

15

Es ist ein historischer Zufall, dass es zwei Möglichkeiten gibt, dasselbe zu tun. MemoryStream hatte immer die WriteTo () Methode, Stream erlangte die CopyTo () Methode erst ab .NET 4.

Die MemoryStream.WriteTo () Version sieht wie folgt aus:

%Vor%

Die Stream.CopyTo () Implementierung wie folgt:

%Vor%

Stream.CopyTo () ist universeller, es funktioniert für jeden Stream. Und hilft Programmierern, die Daten von beispielsweise einem NetworkStream kopieren. Vergessen, den Rückgabewert von Read () zu beachten, war ein sehr häufiger Fehler. Aber es kopiert natürlich die Bytes zweimal und vergibt das temporäre buffer , MemoryStream benötigt es nicht, da es direkt aus seinem eigenen Puffer schreiben kann. Sie würden also WriteTo () immer noch bevorzugen. Den Unterschied zu bemerken ist nicht sehr wahrscheinlich.

    
Hans Passant 19.05.2012, 13:14
quelle
6

MemoryStream.WriteTo : Schreibt den gesamten Inhalt dieses Speichers Stream zu einem anderen Stream.

Stream.CopyTo : Liest die Bytes aus dem aktuellen Stream und schreibt sie an das Ziel Strom. Das Kopieren beginnt an der aktuellen Position im aktuellen Stream. Sie müssen zurück auf 0 suchen, um den gesamten Quelldatenstrom zu kopieren.

Also ich denke, MemoryStream.WriteTo bessere Option für diese Situation

    
Damith 19.05.2012 10:51
quelle
4

Wenn Sie Stream.CopyTo verwenden, müssen Sie nicht alle Bytes im Speicher lesen, um damit zu beginnen. Jedoch:

  • Dieser Code wäre einfacher, wenn Sie nur File.Copy
  • Wenn Sie alle Daten in den Speicher laden, können Sie einfach Folgendes verwenden:

    %Vor%
  • Sie sollten eine using -Anweisung für die Eingabe sowie für den Ausgabestream

  • haben

Wenn Sie wirklich eine Verarbeitung benötigen und File.Copy nicht verwenden können, wird Stream.CopyTo mit größeren Dateien zurechtkommen, als alles in den Speicher zu laden. Sie brauchen das natürlich nicht, oder Sie müssen die gesamte Datei aus anderen Gründen in den Speicher laden.

Wenn Sie ein MemoryStream erhalten haben, würde ich wahrscheinlich MemoryStream.WriteTo anstelle von Stream.CopyTo verwenden, aber es wird wahrscheinlich keinen großen Unterschied machen, was Sie verwenden, außer , dass Sie sicherstellen müssen, dass Sie am Anfang des Streams sind, wenn Sie CopyTo verwenden.

    
Jon Skeet 19.05.2012 10:53
quelle
1

Ich denke, dass Hans Passants Behauptung eines Fehlers in MemoryStream.WriteTo () falsch ist; Es ignoriert den Rückgabewert von Write () nicht. Stream.Write () gibt void zurück, was bedeutet, dass die gesamten Zählbytes geschrieben werden, was bedeutet, dass Stream.Write () blockieren wird, um den Vorgang zum Beispiel zu einem NetworkStream zu vervollständigen oder zu werfen, wenn es letztendlich fehlschlägt.

Das unterscheidet sich tatsächlich von dem write () - Systemaufruf in? nix und seinen vielen Emulationen in libc usw., die ein "short write" zurückgeben können. Ich vermute, Hans sprang zu dem Schluss, dass Stream.Write () dem folgte, was ich auch erwartet hätte, aber anscheinend nicht.

Es ist vorstellbar, dass Stream.Write () einen "kurzen Schreibvorgang" ausführen könnte, ohne dass dies angezeigt wird. Der Aufrufer muss also überprüfen, ob die Position-Eigenschaft des Streams tatsächlich um count erhöht wurde. Das wäre ein sehr fehleranfälliges API, und ich bezweifle, dass es das tut, aber ich habe es nicht gründlich getestet. (Testen wäre ein bisschen knifflig: Ich denke, Sie müssten einen TCP NetworkStream mit einem Lesegerät am anderen Ende verbinden, das für immer blockiert ist, und genug schreiben, um die Drahtpuffer zu füllen. Oder so ähnlich ...)

Die Kommentare für Stream.Write () sind nicht ganz eindeutig:

Zusammenfassung:   Überschreibt in einer abgeleiteten Klasse eine Bytefolge in den aktuellen Wert streamen und verschiebt die aktuelle Position innerhalb dieses Streams um die Nummer von Bytes geschrieben.   Parameter: Puffer: Ein Array von Bytes. Diese Methode kopiert die Anzahl der Bytes aus dem Puffer in den aktuellen Stream.

Vergleichen Sie das mit der Linux-Manpage für write (2):

write () schreibt Bytes in die Datei, auf die der Dateideskriptor fd verweist.

Beachten Sie die entscheidenden "bis zu". Diesem Satz folgt eine Erklärung einiger Bedingungen, unter denen ein "kurzes Schreiben" auftreten könnte, was sehr deutlich macht, dass es auftreten kann.

Das ist wirklich ein kritisches Problem: Wir müssen wissen, wie sich Stream.Write () unzweifelhaft verhält.

    
Kafka 10.06.2013 13:51
quelle
0

Die CopyTo-Methode erstellt einen Puffer, füllt ihn mit Daten aus dem ursprünglichen Datenstrom und ruft dann die Write-Methode auf, wobei der erstellte Puffer als Parameter übergeben wird. Das WriteTo verwendet den internen Puffer des MemoryStream, um zu schreiben. Das ist der Unterschied. Was ist besser - es liegt an Ihnen zu entscheiden, welche Methode Sie bevorzugen.

    
platon 19.05.2012 11:04
quelle
0

Erstellen eines MemoryStream von einem HttpInputStream in Vb.Net:

%Vor%     
user3219140 21.01.2014 12:19
quelle

Tags und Links