195

我想将对象序列化为字符串,然后返回。

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

但是,Stream to string and back... 不是那么成功。经过StreamToStringand之后StringToStream,新Stream的没有被 protobuf-net 反序列化;它引发了一个Arithmetic Operation resulted in an Overflow例外。如果我们反序列化原始流,它就可以工作。

我们的方法:

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

8 回答 8

275

我刚刚对此进行了测试并且工作正常。

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

于 2013-07-23T05:03:10.300 回答
62

这是很常见的,但却是非常错误的。Protobuf 数据不是字符串数据。它当然不是ASCII。您正在使用反向编码。文本编码传输:

  • 格式化字节的任意字符串
  • 格式化字节到原始字符串

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

  • 格式化字符串的任意字节
  • 原始字节的格式化字符串

看看 Convert.ToBase64String 和 Convert。FromBase64String

于 2013-07-24T09:32:29.483 回答
12

UTF8 MemoryStream 到字符串的转换:

var res = Encoding.UTF8.GetString(stream.GetBuffer(), 0 , (int)stream.Length)
于 2016-07-06T07:37:21.580 回答
6

试试这个。

string output1 = Encoding.ASCII.GetString(byteArray, 0, byteArray.Length)
于 2014-04-30T07:59:35.690 回答
5

当您测试尝试使用UTF8如下编码流时

var stream = new MemoryStream();
var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8);
Serializer.Serialize<SuperExample>(streamWriter, test);
于 2013-07-23T05:24:33.043 回答
2

我编写了一个有用的方法来调用任何需要 a 的操作StreamWriter并将其写入字符串。方法是这样的;

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

我知道使用 a 可以更轻松地完成此操作StringBuilder,关键是您可以调用任何采用 a 的方法StreamWriter

于 2017-01-08T13:00:33.610 回答
1

我想将对象序列化为字符串,然后返回。

与其他答案不同,但对于大多数对象类型来说,最直接的方法是 XmlSerializer:

        Subject subject = new Subject();
        XmlSerializer serializer = new XmlSerializer(typeof(Subject));
        using (Stream stream = new MemoryStream())
        {
            serializer.Serialize(stream, subject);
            // do something with stream
            Subject subject2 = (Subject)serializer.Deserialize(stream);
            // do something with subject2
        }

所有受支持类型的公共属性都将被序列化。甚至某些集合结构也受支持,并且会向下延伸到子对象属性。您可以控制序列化如何与您的属性上的属性一起工作。

这不适用于所有对象类型,某些数据类型不支持序列化,但总的来说它非常强大,您不必担心编码。

于 2019-01-10T20:02:39.500 回答
0

在您想要序列化/反序列化 POCO 的用例中,Newtonsoft 的 JSON 库非常好。我用它在 SQL Server 中将 POCO 持久化为 nvarchar 字段中的 JSON 字符串。需要注意的是,由于它不是真正的反/序列化,它不会保留私有/受保护的成员和类层次结构。

于 2015-09-10T03:10:25.547 回答