我想将一个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的字节。
答案 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 Blog,String 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