2010-04-13 18 views
28

Ich möchte einen String in einen Stream schreiben (in diesem Fall ein MemoryStream) und die Bytes nacheinander lesen.String zum Streamen schreiben und zurücklesen funktioniert nicht

stringAsStream = new MemoryStream(); 
UnicodeEncoding uniEncoding = new UnicodeEncoding(); 
String message = "Message"; 

stringAsStream.Write(uniEncoding.GetBytes(message), 0, message.Length); 

Console.WriteLine("This:\t\t" + (char)uniEncoding.GetBytes(message)[0]); 
Console.WriteLine("Differs from:\t" + (char)stringAsStream.ReadByte()); 

Das (unerwünschte) Ergebnis, das ich bekommen ist:

This:   M 
Differs from: ? 

Es sieht wie es ist nicht richtig, als das erste Zeichen von „Message“ gelesen wird, ‚M‘, das funktioniert, wenn Abrufen der Bytes von der UnicodeEncoding-Instanz, aber nicht beim Zurücklesen aus dem Stream.

Was mache ich falsch?


Das größere Bild: Ich habe einen Algorithmus, der auf den Bytes eines Strom funktionieren, würde Ich mag so allgemein wie möglich sein und mit jedem Stream zu arbeiten. Ich möchte einen ASCII-String in einen MemoryStream konvertieren oder eine andere Methode verwenden, um mit dem String als Stream arbeiten zu können. Der fragliche Algorithmus wird an den Bytes des Streams arbeiten.

+3

Möchten Sie die Bytes oder die Zeichen einzeln aus dem Stream lesen? Beachten Sie, dass Byte! = Char, da Ihre Codierung Unicode ist. –

+0

Ja, das tue ich. Und Byte wird char sein, da ich ASCII-Dokumente lesen werde. Wäre es besser, in meinem Fall etwas anderes als uniEncoding zu verwenden? – Deleted

+0

Ich habe ein größeres Bild hinzugefügt, wie gewünscht. – Deleted

Antwort

47

Nachdem Sie auf die MemoryStream schreiben und bevor Sie es zurück lesen, müssen Sie Seek zurück an den Anfang der MemoryStream, so dass Sie nicht vom Ende lesen.

UPDATE

nach dem Update zu sehen, denke ich, eine zuverlässigere Art und Weise gibt es den Strom zu bauen:

UnicodeEncoding uniEncoding = new UnicodeEncoding(); 
String message = "Message"; 

// You might not want to use the outer using statement that I have 
// I wasn't sure how long you would need the MemoryStream object  
using(MemoryStream ms = new MemoryStream()) 
{ 
    var sw = new StreamWriter(ms, uniEncoding); 
    try 
    { 
     sw.Write(message); 
     sw.Flush();//otherwise you are risking empty stream 
     ms.Seek(0, SeekOrigin.Begin); 

     // Test and work with the stream here. 
     // If you need to start back at the beginning, be sure to Seek again. 
    } 
    finally 
    { 
     sw.Dispose(); 
    } 
} 

Wie Sie sehen können, dieser Code verwendet eine Stream die gesamte Zeichenfolge zu schreiben (mit richtiger Kodierung) aus dem MemoryStream. Dadurch wird sichergestellt, dass das gesamte Byte-Array für die Zeichenfolge geschrieben wird.

Update: Ich trat mehrere Male mit leeren Strom in Frage. Es genügt, Flush direkt nach dem Schreiben zu nennen.

+9

Dieser Code wird bei 'ms.Seek (0, SeekOrigin.Begin)' fehlschlagen, da das Einfügen einer Verwendung in StreamWriter seinen Stream schließt, der in diesem Fall der MemoryStream ist. Wenn Sie dann versuchen, zu suchen, erhalten Sie die Ausnahme "Kann nicht auf einen geschlossenen Stream zugreifen". –

+0

Sie können diese Methode verwenden, wenn Sie den Stream in einer Klasse umbrechen, die die Verfügbarkeit des zugrunde liegenden Streams überschreibt. [Diese Antwort] (http://stackoverflow.com/questions/4465824/is-it-okay-to-not-close-streamreader-streamwriter-to-keep-the-underlying-stream-o/4466519#4466519) zu Eine verwandte Frage verweist auf [eine Implementierung] (http://csharptest.net/browse/src/Library/IO/NonClosingStream.cs). –

+3

Wie bereits erwähnt, kompiliert dieser Code nicht. Die Antwort von Joel Purra ist ein One-Liner und funktioniert viel besser. – Slaggg

13

Sie message.Length verwenden, die die Anzahl von Zeichen in der Zeichenfolge zurück, aber Sie sollten die nubmer von Bytes gelesen werden. Sie sollten so etwas wie verwenden:

byte[] messageBytes = uniEncoding.GetBytes(message); 
stringAsStream.Write(messageBytes, 0, messageBytes.Length); 

Sie dann ein einzelnes Byte Lesen und ein Zeichen von ihm nur durch Gießen zu char erhalten erwarten. UnicodeEncoding verwendet zwei Bytes pro Zeichen.

Wie Justin sagt, du bist auch nicht zurück zum Anfang des Streams suchen.

Grundsätzlich habe ich Angst, so ziemlich alles ist hier falsch. Bitte geben Sie uns das größere Bild und wir können Ihnen helfen, herauszufinden, was Sie tun sollten wirklich tun. Verwenden Sie eine StreamWriter zu schreiben und dann eine StreamReader zu lesen ist möglicherweise was Sie wollen, aber wir können nicht wirklich aus dem kurzen Stück Code, den Sie gezeigt haben.

+0

Nachdem Sie in einen MemoryStream geschrieben haben, müssen Sie nicht erneut an den Anfang suchen, um mit dem Lesen zu beginnen? –

+0

@Justin: Ja, das ist ein anderes Problem :) –

+0

Ich habe ein größeres Bild hinzugefügt, wie gewünscht. Vielleicht ist es einfacher zu verstehen, was ich jetzt machen möchte. – Deleted

1

Sie müssen den Strom an den Anfang zurück:

stringAsStream.Position = 0 
4

ich denke, es wäre viel produktiver sein:

stringAsStream.Seek(0, SeekOrigin.Begin); 
Console.WriteLine("Differs from:\t" + (char)stringAsStream.ReadByte()); 

Dies kann auch durch Einstellung der Position Eigenschaft auf 0 durchgeführt werden Verwenden Sie eine TextWriter, in diesem Fall eine StreamWriter in den MemoryStream schreiben. Danach, wie andere gesagt haben, müssen Sie den MemoryStream mit etwas wie "stringAsStream.Position = 0L;" zurückspulen.

stringAsStream = new MemoryStream(); 

// create stream writer with UTF-16 (Unicode) encoding to write to the memory stream 
using(StreamWriter sWriter = new StreamWriter(stringAsStream, UnicodeEncoding.Unicode)) 
{ 
    sWriter.Write("Lorem ipsum."); 
} 
stringAsStream.Position = 0L; // rewind 

Beachten Sie, dass:

Streamstandardwerte eine Instanz von UTF8Encoding zu verwenden, sofern nicht anders angegeben. Diese Instanz von UTF8Encoding wird ohne Bytereihenfolgemarkierung (BOM)

auch konstruiert, Sie kein new UnicodeEncoding() in der Regel erstellen müssen, da es bereits ein als statisches Mitglied der Klasse ist für Sie in bequem zu bedienen utf-8, utf-16 und utf-32 Geschmacksrichtungen.

Und dann, endlich (wie andere gesagt haben) Sie versuchen, die byte s direkt in char s konvertieren, die sie nicht sind. Wenn ich einen Speicherstream hätte und wüsste, dass es eine Zeichenfolge ist, würde ich eine TextReader verwenden, um die Zeichenfolge aus den Bytes zurückzuholen. Es scheint mir "gefährlich" zu sein, mit den rohen Bytes herumzuspielen.

+0

Mein Hauptziel ist es, mit Streams zu arbeiten. Da ich an den Bytes von ASCII-Text und Binärdateien arbeiten werde. – Deleted

+0

Ah, ich verstehe. In diesem Fall müssen Sie mit den Bytes umgehen. ;) –

31

Versuchen Sie diese "Einliner" von Delta's Blog, String To MemoryStream (C#).

MemoryStream stringInMemoryStream = 
    new MemoryStream(ASCIIEncoding.Default.GetBytes("Your string here")); 

Der String wird in die MemoryStream geladen werden, und man kann von ihr lesen. Siehe Encoding.GetBytes(...), die auch implemented for a few other encodings war.

+0

Und um die Daten zurück zu bekommen, ['Encoding.ASCII.GetString (ms.ToArray());'] (http://stackoverflow.com/a/234262/). –

+3

Ich fordere jeden, der dieses Beispiel verwendet, dringend auf, Encoding.UTF8 über ASCII - oder eine andere Codierung mit breiterem Umfang zu verwenden. Die Chancen stehen gut, jeder Text, der von Nicht-Amerikanern, Engländern, ... geschrieben wird, wird in ASCII schlecht wiedergegeben. – Cornelius

Verwandte Themen