2

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

    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!?!

所以我对你们所有人的问题是,额外的“到底是从哪里来的,为什么当我在我的快速手表中检查琴弦时看不到它们,以及我如何首先防止它们。

你在 ASP.NET 中,ewitkows

4

1 回答 1

5

问题是你在打电话MemoryStream.GetBuffer。根据MSDN 文章

请注意,缓冲区包含可能未使用的已分配字节。例如,如果将字符串“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
于 2013-08-27T19:09:43.393 回答