XmlSerializer添加额外的字符

时间:2013-08-27 17:49:47

标签: asp.net vb.net xml-serialization

我有一个将对象序列化为字符串的方法,展示了:

    Shared Function Serialize(ByVal o As Object) As String
        Dim rtnVal As String = ""
        Dim x As New System.Xml.Serialization.XmlSerializer(o.GetType())

        Using memStream As New MemoryStream
            Dim stWriter As New System.IO.StreamWriter(memStream)
            x.Serialize(stWriter, o)
            rtnVal = Encoding.UTF8.GetString(memStream.GetBuffer())
        End Using

        Return rtnVal
    End Function

使用此序列化数据,我现在将其插入到SQL 2012数据库的XML类型字段中。大多数情况下,这段代码效果很好,但是对于一个特定的对象,我得到的是“无效”字符,即错误“解析第5行17字符非法xml字符”。我看了一下我的数据,它很干净,你可以在这里看到:

<?xml version="1.0" encoding="utf-8"?>
    <RatingDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <LenderName>dsfg</LenderName>
    <VehiclePrice>345</VehiclePrice>
</RatingDetails>

一些窥探让我做了IsXMLChar方法 - http://msdn.microsoft.com/en-us/library/system.xml.xmlconvert.isxmlchar%28v=vs.100%29.aspx - 并且使用它我能够循环遍历序列化XML字符串中的每个字符。低,看,我有无效的数据。我的字符串末尾有15“”字符 - WTF!?!

所以我对你们所有的问题都是,那些额外的“来自哪里,为什么我在快速观察时检查字符串时看不到它们,以及如何在一开始就预防它们。” / p>

您的ASP.NET,ewitkows

1 个答案:

答案 0 :(得分:4)

问题是你在呼叫MemoryStream.GetBuffer。根据{{​​3}}:

  

请注意,缓冲区包含可能未使用的已分配字节。例如,如果将字符串“test”写入MemoryStream对象,则从GetBuffer返回的缓冲区长度为256而不是4,未使用252个字节。要仅获取缓冲区中的数据,请使用ToArray方法;但是,ToArray会在内存中创建数据副本。

要解决此问题,您可以改为呼叫ToArray

Shared Function Serialize(ByVal o As Object) As String
    Dim rtnVal As String = ""
    Dim x As New System.Xml.Serialization.XmlSerializer(o.GetType())
    Using memStream As New MemoryStream
        Dim stWriter As New System.IO.StreamWriter(memStream)
        x.Serialize(stWriter, o)
        rtnVal = Encoding.UTF8.GetString(memStream.ToArray())
    End Using
    Return rtnVal
End Function

然而,这仍然不是很有效。如果流包含大量数据,它将无缘无故地将整个数据复制到一个新数组中。为了安心,我建议使用StreamReader来阅读MemoryStream而不是尝试自己解码(但不要忘记在阅读之前回到流的开头):

Public Function Serialize(ByVal o As Object) As String
    Dim rtnVal As String = ""
    Dim x As New System.Xml.Serialization.XmlSerializer(o.GetType())
    Using memStream As New MemoryStream
        Dim stWriter As New System.IO.StreamWriter(memStream)
        x.Serialize(stWriter, o)
        Dim reader As New StreamReader(memStream)
        memStream.Position = 0  ' Seek to start of stream
        rtnVal = reader.ReadToEnd()
    End Using
    Return rtnVal
End Function