【问题标题】:Writing String to Stream and reading it back does not work将字符串写入 Stream 并将其读回不起作用
【发布时间】:2011-02-07 10:43:49
【问题描述】:

我想将一个字符串写入流(本例中为 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: ?

看起来好像没有被正确读取,因为“消息”的第一个字符是“M”,它在从 UnicodeEncoding 实例获取字节时有效,但在从流。

我做错了什么?


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

【问题讨论】:

  • 您要从流中一一读取字节或字符吗?请注意 byte != char 作为您的编码是 Unicode。
  • 是的,我愿意。字节将是 char,因为我将阅读 ASCII 文档。在我的情况下使用 uniEncoding 以外的东西会更好吗?
  • 我按要求添加了更大的图片。
  • 我用一个代码示例更新了我的答案,它可能对你更有效。
  • 谢谢大家的帮助!很抱歉从一开始就没有包括更大的图景,因为在这种情况下这是必要的。所有答案都提供了价值,所以至少你们都得到了我的支持。 :)

标签: c# stream


【解决方案1】:

在你写到MemoryStream之后,在你回读之前,你需要Seek回到MemoryStream的开头,这样你就不会从结尾读了。

更新

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

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 就足够了。

【讨论】:

  • 该代码将在ms.Seek(0, SeekOrigin.Begin) 处失败,因为在 StreamWriter 上使用 using 将关闭其流,在本例中为 MemoryStream。然后当你尝试寻找时,它会给你一个Cannot access a closed Stream 异常。
  • 如果您将流包装在一个覆盖底层流处理的类中,您可以使用这种方法。 This response 的相关问题指向an implementation
  • 如前所述,此代码无法编译。 Joel Purra 的答案是单行的,效果更好。
【解决方案2】:

试试这个来自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

【讨论】:

  • 我强烈敦促任何使用此示例的人使用 Encoding.UTF8 而非 ASCII 或任何其他范围更广的编码。由非{美国人、英语、...} 人编写的任何文本很有可能在 ASCII 中呈现不佳。
【解决方案3】:

我认为使用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 风格中使用。

然后,最后(正如其他人所说)您尝试将bytes 直接转换为chars,但事实并非如此。如果我有一个内存流并且知道它是一个字符串,我会使用TextReader 从字节中取回字符串。乱搞原始字节对我来说似乎是“危险的”。

【讨论】:

  • 我的主要目标是使用 Streams。因为我将处理 ASCII 文本和二进制文件的字节。
  • 啊,我明白了。在那种情况下,我想你将不得不把它们弄乱。 ;)
  • 倒带部分的一件事,我得到Cannot access a closed Stream.
【解决方案4】:

您使用的是message.Length,它返回字符串中字符的数量,但您应该使用字节的数字来读取。你应该使用类似的东西:

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

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

正如贾斯汀所说,您没有回到流的开头。

基本上,我担心这里几乎所有事情都是错误的。请给我们更大的图景,我们可以帮助您确定您应该真正做什么。使用StreamWriter 写入,然后使用StreamReader 读取很可能是您想要的,但我们无法仅从您显示的简短代码中判断。

【讨论】:

  • 写到MemoryStream后,是不是需要回到开头重新开始阅读?
  • @Justin:是的,这是另一个问题 :)
  • 我已按要求添加了更大的图片。也许更容易理解我现在想做什么。
【解决方案5】:

您需要将流重置为开头:

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

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

stringAsStream.Position = 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    相关资源
    最近更新 更多