将Stream转换为String并返回…我们缺less什么?

我想序列化对象到string,并返回。

我们使用protobuf-net将一个对象转换成Stream并返回,成功。

但是,串stream和返回…不是那么成功。 在通过StreamToStringStringToStream ,新的Stream不会被protobuf-net反序列化; 它会引发一个Arithmetic Operation resulted in an Overflowexception的Arithmetic Operation resulted in an Overflow 。 如果我们反序列化原始stream,它就可以工作。

我们的方法:

 public static string StreamToString(Stream stream) { stream.Position = 0; using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { return reader.ReadToEnd(); } } public static Stream StringToStream(string src) { byte[] byteArray = Encoding.UTF8.GetBytes(src); return new MemoryStream(byteArray); } 

我们的示例代码使用这两个:

 MemoryStream stream = new MemoryStream(); Serializer.Serialize<SuperExample>(stream, test); stream.Position = 0; string strout = StreamToString(stream); MemoryStream result = (MemoryStream)StringToStream(strout); var other = Serializer.Deserialize<SuperExample>(result); 

这是如此普遍,但却是如此深刻的错误。 Protobuf数据不是string数据。 它当然不是ASCII。 您正在使用编码向后 。 文本编码传输:

  • 一个任意string来格式化字节
  • 格式化的字节为原始string

你没有“格式化的字节”。 你有任意的字节 。 你需要使用像base-n(通常是base-64)编码的东西。 这转移

  • 任意字节格式化的string
  • 一个格式化的string到原始字节

看看Convert.ToBase64String和转换。 FromBase64String

我刚刚testing过这一点,工作正常。

 string test = "Testing 1-2-3"; // convert string to stream byte[] byteArray = Encoding.ASCII.GetBytes(test); MemoryStream stream = new MemoryStream(byteArray); // convert stream to string StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); 

如果stream已经被写入,那么在读出文本之前,您可能需要在开始之前寻找开头: stream.Seek(0, SeekOrigin.Begin);

当你testing使用UTF8编码stream如下

 var stream = new MemoryStream(); var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8); Serializer.Serialize<SuperExample>(streamWriter, test); 

尝试这个。

 string output1 = Encoding.ASCII.GetString(byteArray, 0, byteArray.Length) 

一个UTF8 MemoryStream转换string:

 var res = Encoding.UTF8.GetString(stream.GetBuffer(),0 , stream.GetBuffer().Length) 

在您想要序列化/反序列化POCO的用例中,Newtonsoft的JSON库非常好。 我使用它在SQL Server中将POCO作为JSONstring保存在nvarchar字段中。 警告是因为它不是真正的de /序列化,它不会保留私有/受保护的成员和类层次结构。

我写了一个有用的方法来调用需要StreamWriter任何操作,然后将其写出到string中。 方法就是这样;

 static void SendStreamToString(Action<StreamWriter> action, out string destination) { using (var stream = new MemoryStream()) using (var writer = new StreamWriter(stream, Encoding.Unicode)) { action(writer); writer.Flush(); stream.Position = 0; destination = Encoding.Unicode.GetString(stream.GetBuffer(), 0, (int)stream.Length); } } 

你可以像这样使用它;

 string myString; SendStreamToString(writer => { var ints = new List<int> {1, 2, 3}; writer.WriteLine("My ints"); foreach (var integer in ints) { writer.WriteLine(integer); } }, out myString); 

我知道用StringBuilder可以简单得多,关键是你可以调用任何需要StreamWriter方法。