【问题标题】:XML deserialize from stream with multiple objects从具有多个对象的流中反序列化 XML
【发布时间】:2016-09-13 14:33:40
【问题描述】:

我使用 TcpClient 和 TcpListener 类在两个应用程序之间交换一些对象。我使用 XML 序列化(见下面的代码)。基本上一切正常。问题是当一个应用程序在短时间内发送多个对象时,我在接收端的 MemoryStream 中有多个对象(多个根元素,也带有 XML 版本标记)。我如何处理所有对象,最好的方法是什么?我可以将对象分组到一个列表中并对整个列表进行反序列化,但迟早我会面临同样的问题。 我认为这似乎是一个常见问题,但我还没有找到解决方案。

要序列化的对象:

public class DataModel
{
    public string Command { get; set; }
    public string Value { get; set; }

    // ctor etc
}

接收方:

private void onRead(IAsyncResult ar)
    {    

        int nBytes = _client.GetStream().EndRead(ar);

        XmlSerializer serializer = new XmlSerializer(typeof(DataModel));
        MemoryStream memStream = new MemoryStream(buffer);
        DataModel dmo = (DataModel)serializer.Deserialize(memStream);
        buffer = new byte[1024];
        _client.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(onRead), null);

        // read on if more available...

    }

流内容示例:

<?xml version="1.0"?>
<DataModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Command>XXX</Command>
  <Value>1.0</Value>
</DataModel><?xml version="1.0"?>
<DataModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Command>XXX</Command>
  <Value>5</Value>
</DataModel><?xml version="1.0"?>
<DataModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Command>XXX</Command>
  <Value>YYY</Value>
</DataModel>

我删除了 try/catch、调试和所有不必要的东西

【问题讨论】:

  • 无论何时发送数据,您都需要使用以下一种或多种技术终止每条消息 1) ASCII:使用消息中未使用的已知字符终止每条消息 2) ASCII 或二进制:添加前缀带有字节数的消息。 3) Ascii 或 Binary:发送固定长度的消息。在您的情况下,我将使用 ETX (0x03) 或 EOT (0x04) 之类的字符终止每个 DataModel 元素。然后在保存 xml 之前删除字符。分别处理每个元素。

标签: c# xml serialization tcp memorystream


【解决方案1】:

首先,您同意这种模式吗?也许另一个应用程序有错误,应该分别发送每个 Xml 文档。在哪个演员阵容中,这不是你要解决的问题。

但是,如果您确实同意这一点,或者正在使用持久连接:

您的问题与 Xml 无关。对于通过开放连接传输的任何类型的内容,您都可能遇到同样的问题。

问题在于您没有正确“构建”传入流。

您已分别从流中读取每个单独的 XmlDocument,并将每个 XmlDocument 读取到它自己的内部流中。然后你可以做任何你想做的事情,因为它现在是有效的 Xml。

您可以逐字节读取,查找声明以指示下一个文档,也可以使用 XmlReader,同时测试下一个声明,否则会引发异常。

【讨论】:

    猜你喜欢
    • 2014-05-04
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 2023-03-05
    • 2021-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多