我有一个将对象序列化为字符串的方法,展示了:
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
答案 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