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 から返されるバッファーの長さは 4 ではなく 256 で、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 に答える