【问题标题】:Strange problem with Streams流的奇怪问题
【发布时间】:2010-06-28 14:47:07
【问题描述】:

我通过 HttpPost 接收到我的服务的 XML,并且我想记录接收到的值以用于调试目的。

首先我将它反序列化成这样的实体:

XmlSerializer s = new XmlSerializer(typeof(TransactionResults));
TransactionResults t = (TransactionResults)s.Deserialize(stream);

当然,这会将流移动到末尾,因此我无法记录原始值。

我尝试从头开始,然后用StreamReader 阅读它,但它抛出了NotSupportedException

作为测试,我尝试重新序列化它(我再次创建了所有对象以避免重新使用它们来查看是否有问题)

private static string GetContents(TransactionResults t)
{
    XmlSerializer s = new XmlSerializer(typeof(TransactionResults));
    MemoryStream stream = new MemoryStream();
    s.Serialize(stream, t);
    return new StreamReader(stream).ReadToEnd();
}

此方法返回一个空字符串。

(显然,如果我反转逻辑,值会被记录,但我无法获取对象)

我做错了什么?将值反序列化为对象将其记录为字符串的最佳方法是什么?

【问题讨论】:

    标签: c# stream serialization


    【解决方案1】:

    您应该能够毫无问题地找到MemoryStream 的开头:

    private static string GetContents(TransactionResults t)
    {
        XmlSerializer s = new XmlSerializer(typeof(TransactionResults));
        MemoryStream stream = new MemoryStream();
        s.Serialize(stream, t);
        stream.Position = 0; // Rewind to the beginning of the stream
        return new StreamReader(stream).ReadToEnd();
    }
    

    如果您想记录原始数据,实际上需要将其复制到 MemoryStream 中开始 - 然后您可以随意倒带它。

    我发现使用这样的方法来耗尽一个流并写入另一个流是很有用的:

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[8 * 1024];
        int len;
        while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            output.Write(buffer, 0, len);
        }    
    }
    

    您可以将传入服务的输入流称为输入,并将新的MemoryStream 作为输出。

    【讨论】:

    • 这可能是要走的路,但只是提出了另一种方式;您还可以用另一个流包装任何流,并在底层流被消耗时定位/记录值(如果内存是一个问题)
    • @Marc,那样我需要手动反序列化它而不是使用 XmlSerializer (同时做这两件事)。但我同意保存另一个流的创建是可行的。在我的情况下,内存不是问题
    • 使用MemoryStream 来获取字符串似乎过于复杂,而BCL 提供了一个StringWriter 类来获取该庄园中的字符串。如果您已经反序列化了该对象,那么您可以轻松地从中获取 XML。
    • @Juan:不,先生,您只需将创建的流传递给 XmlSerializer,他就会使用它。他只知道他得到了一个流,不知道当他从中拉出流时它还能做什么;)
    • @Creepy:如果您要反序列化然后重新序列化数据,您很可能不会得到相同的结果。将数据直接复制到 MemoryStream 意味着您将能够确切地查看您的服务收到的内容,包括任何无效数据等。
    【解决方案2】:

    将流读入内存流并对其进行操作,支持查找。

    【讨论】:

      【解决方案3】:

      这是我需要从 XML 可序列化对象中获取 Xml 字符串时使用的方法。因此,您首先像以前一样反序列化对象,然后从对象中获取字符串,您现在将拥有字符串和原始对象。

      public static string ToXmlString(object xmlObject)
      {
          if (xmlObject == null)
              throw new NullReferenceException("xmlObject cannot be null.");
      
          String xmlResult = null;
      
          XmlSerializer serializer = new XmlSerializer(xmlObject.GetType());
          using (StringWriter writer = new StringWriter())
          {
              serializer.Serialize(writer, xmlObject);
              xmlResult = writer.ToString();
          }
      
          return xmlResult;
      }
      

      【讨论】:

      • 但是,您不一定会收到客户端发送的 original 字符串。例如,这将默认为 UTF-16 编码。它还将使用 当前 版本的代码进行序列化,这可能不是客户端使用的。如果您想查看原始数据,最好尽可能以原始形式登录,IMO。
      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2015-02-27
      • 2018-06-26
      • 2011-08-13
      • 2011-08-17
      • 2011-02-02
      • 2021-10-10
      相关资源
      最近更新 更多