2013-08-27 7 views
2

내가 문자열로 객체를 직렬화하는 방법을 가지고하는 전시 :이 직렬화 된 데이터를 사용하여XmlSerializer를 추가하는 추가 문자

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에서

너의,

+0

을 어디 당신은'Encoding' 객체를 인스턴스화합니까? 그 코드를 게시하십시오. –

+0

@KarlAnderson에게 감사드립니다. 아뇨, 전혀 그 코드를 인스턴스화하지 않습니다. – ewitkows

+0

@KarlAnderson, 인코딩은 클래스 이름 (예 :'System.Text.Encoding')입니다. 'UTF8'은 클래스의 공유 속성이므로 인스턴스화를 사용하지 않아도됩니다. –

답변

4

이 문제는 당신이 MemoryStream.GetBuffer을 요구하고있다 ewitkows MSDN article에 따르면 :.. 버퍼는 사용하지 못할 수 있습니다 할당 된 바이트를 포함

참고 예를 들어, 문자열 "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 

은 그러나, 여전히 정말 비효율적입니다. 스트림에 많은 양의 데이터가 포함되어 있다면 아무 이유없이 모든 것을 새로운 배열로 복사 할 것입니다. 마음의 평화를 위해, 나는 MemoryStream을 읽을 StreamReader를 사용하기보다는 스스로를 해독하려고 추천 할 것입니다 (그러나 그것을 읽기 전에 다시 스트림의 시작을 추구하는 것을 잊지 마세요) :

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 
+1

그 트릭을 했어! 감사합니다 @Steven, 내가 확장 된 버퍼 크기와 관련이 있다면 궁금 해서요.하지만 이전에이 동일한 직렬화 코드를 다른 객체와 함께 사용했기 때문에 왜 전에 실행하지 않았는지 알 수 없습니다. 도움을 주신 모든 분들께 감사드립니다. – ewitkows