将String写入Stream并将其读回不起作用

时间:2010-04-13 12:53:25

标签: c# stream

我想将一个String写入一个Stream(本例中是一个MemoryStream)并逐个读取这些字节。

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());

我得到的(不受欢迎的)结果是:

This:         M
Differs from: ?

看起来就好像没有被正确读取一样,因为“Message”的第一个字符是'M',它在从UnicodeEncoding实例获取字节时起作用,但在从它读取它们时不起作用流。

我做错了什么?


更大的图片:我有一个算法可以处理Stream的字节,我希望尽可能通用并使用任何Stream。我想将ASCII-String转换为MemoryStream,或者使用另一种方法将String作为Stream处理。有问题的算法将处理Stream的字节。

5 个答案:

答案 0 :(得分:60)

在您写完MemoryStream之后,在您回读之前,您需要Seek回到MemoryStream的开头,这样您就不会从最后阅读。< / p>

<强>更新

在看到您的更新后,我认为有一种更可靠的方法来构建流:

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();
    }
}

如您所见,此代码使用StreamWriter将整个字符串(具有正确的编码)写入MemoryStream。这样可以避免确保写入字符串的整个字节数组。

更新:我几次遇到空流问题。在写完之后立即调用 Flush 就足够了。

答案 1 :(得分:34)

Delta's BlogString To MemoryStream (C#)尝试此“单行”。

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

该字符串将加载到MemoryStream,您可以从中读取。请参阅Encoding.GetBytes(...),其中也是implemented for a few other encodings

答案 2 :(得分:14)

您正在使用message.Length返回字符串中字符的数量,但您应该使用 bytes 的nubmer进行读取。你应该使用类似的东西:

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

然后你正在阅读一个字节并期望通过转换为char从中获取一个字符。 UnicodeEncoding每个字符将使用两个字节。

Justin说你没有回到流的开头。

基本上我担心这里的一切都是错的。请给我们更大的图片,我们可以帮助您找出真正正在做的事情。使用StreamWriter进行编写然后使用StreamReader进行读取很可能是您想要的,但我们无法从您显示的简短代码中真正说出来。

答案 3 :(得分:5)

我认为使用TextWriter,在这种情况下StreamWriter写入MemoryStream会更高效。之后,正如其他人所说,你需要使用像stringAsStream.Position = 0L;这样的东西来“回放”MemoryStream。

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

请注意:

  

除非另有说明,否则StreamWriter默认使用UTF8Encoding实例。这个UTF8Encoding实例的构造没有字节顺序标记(BOM)

此外,您通常不必创建new UnicodeEncoding(),因为已经有一个作为类的静态成员,您可以使用方便的utf-8,utf-16和utf-32风格

然后,最后(正如其他人所说),你试图将byte直接转换为char s,而不是TextReader s。如果我有一个内存流并且知道它是一个字符串,我会使用{{1}}从字节中获取字符串。对于我来说,弄乱原始字节似乎是“危险的”。

答案 4 :(得分:1)

您需要将流重置为开头:

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

这也可以通过将Position属性设置为0:

来完成
stringAsStream.Position = 0