programing

.NET에서 개체를 UTF-8 XML로 직렬화

newsource 2023. 10. 2. 15:03

.NET에서 개체를 UTF-8 XML로 직렬화

간단한 설명을 위해 적절한 객체 폐기를 제거했지만 이것이 메모리에서 객체를 UTF-8로 인코딩하는 가장 간단한 방법이라면 충격입니다.더 쉬운 방법이 있을 겁니다, 그렇죠?

var serializer = new XmlSerializer(typeof(SomeSerializableObject));

var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);

serializer.Serialize(streamWriter, entry);

memoryStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(memoryStream, System.Text.Encoding.UTF8);
var utf8EncodedXml = streamReader.ReadToEnd();

아니요, 당신은 a를 사용할 수 있습니다.StringWriter중간자를 없애다MemoryStream. 그러나 XML에 강제로 적용하려면StringWriter이것이 우선입니다.Encoding속성:

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding => Encoding.UTF8;
}

아직 C# 6을 사용하지 않는 경우:

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding { get { return Encoding.UTF8; } }
}

그러면:

var serializer = new XmlSerializer(typeof(SomeSerializableObject));
string utf8;
using (StringWriter writer = new Utf8StringWriter())
{
    serializer.Serialize(writer, entry);
    utf8 = writer.ToString();
}

분명히 당신은 만들 수 있습니다.Utf8StringWriter그것의 컨스트럭터에서 어떤 인코딩도 받아들이는 더 일반적인 클래스로 - 그러나 내 경험에서 UTF-8은 단연코 가장 일반적으로 요구되는 "맞춤형" 인코딩입니다.StringWriter:)

존 한나의 말에 따르면 이건 내부적으로 UTF-16이 될 겁니다 하지만 아마도 언젠가는 다른 것으로 전달해서 이진 데이터로 변환할 겁니다시점에서 위 문자열을 사용하여 UTF-8 바이트로 변환하면 됩니다. XML 선언에서 "utf-8"을 인코딩으로 지정할 것이기 때문입니다.

EDIT: 다음과 같이 작동하는 것을 보여주는 짧지만 완전한 예입니다.

using System;
using System.Text;
using System.IO;
using System.Xml.Serialization;

public class Test
{    
    public int X { get; set; }

    static void Main()
    {
        Test t = new Test();
        var serializer = new XmlSerializer(typeof(Test));
        string utf8;
        using (StringWriter writer = new Utf8StringWriter())
        {
            serializer.Serialize(writer, t);
            utf8 = writer.ToString();
        }
        Console.WriteLine(utf8);
    }


    public class Utf8StringWriter : StringWriter
    {
        public override Encoding Encoding => Encoding.UTF8;
    }
}

결과:

<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <X>0</X>
</Test>

우리가 원했던 "utf-8"의 암호화를 주목하세요.

코드를 다시 문자열로 읽을 때 UTF-8이 메모리에 저장되지 않으므로 UTF-8이 더 이상 UTF-8이 아니라 UTF-16으로 다시 저장됩니다(그러나 가장 이상적인 것은 강제적인 경우를 제외하고는 어떤 인코딩보다 높은 수준의 문자열을 고려하는 것이 최선입니다).

실제 UTF-8 옥텟을 얻으려면 다음을 사용할 수 있습니다.

var serializer = new XmlSerializer(typeof(SomeSerializableObject));

var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);

serializer.Serialize(streamWriter, entry);

byte[] utf8EncodedXml = memoryStream.ToArray();

당신이 남긴 것과 같은 처분을 빼놓았습니다.저는 다음 사항을 약간 선호합니다(정상적인 폐기가 남음).

var serializer = new XmlSerializer(typeof(SomeSerializableObject));
using(var memStm = new MemoryStream())
using(var  xw = XmlWriter.Create(memStm))
{
  serializer.Serialize(xw, entry);
  var utf8 = memStm.ToArray();
}

복잡성은 거의 동일하지만 모든 단계에서 다른 작업을 수행할 수 있는 합리적인 선택이 가능하다는 것을 알 수 있습니다. 그 중 가장 시급한 것은 파일, TCP/IP 스트림, 데이터베이스 등 메모리가 아닌 다른 곳으로 직렬화하는 것입니다.대체로 그렇게 장황하지는 않습니다.

상속을 사용한 매우 좋은 답변입니다. 이니셜라이저를 재정의하는 것만 기억하십시오.

public class Utf8StringWriter : StringWriter
{
    public Utf8StringWriter(StringBuilder sb) : base (sb)
    {
    }
    public override Encoding Encoding { get { return Encoding.UTF8; } }
}

문제를 잘 설명하고 몇 가지 해결책을 정의하는 이 블로그 게시물을 찾았습니다.

(dead link 제거)

가장 좋은 방법은 기억에 남을 때 XML 선언을 완전히 생략하는 것이라고 생각했습니다.어쨌든 그 시점에서는 UTF-16이지만 XML 선언은 특정 인코딩을 가진 파일에 기록되기 전에는 의미가 없어 보입니다. 그리고 선언이 필요하지도 않습니다.적어도 역직렬화는 깨지지 않는 것 같습니다.

@JonHanna가 언급한 바와 같이, 이는 다음과 같이 작성된 XmlWriter로 수행할 수 있습니다.

XmlWriter writer = XmlWriter.Create (output, new XmlWriterSettings() { OmitXmlDeclaration = true });

언급URL : https://stackoverflow.com/questions/3862063/serializing-an-object-as-utf-8-xml-in-net