Pergunta

Para carregar arquivos XML com codificação arbitrária Eu tenho o seguinte código:

Encoding encoding;
using (var reader = new XmlTextReader(filepath))
{
    reader.MoveToContent();
encoding = reader.Encoding;
}

var settings = new XmlReaderSettings { NameTable = new NameTable() };
var xmlns = new XmlNamespaceManager(settings.NameTable);
var context = new XmlParserContext(null, xmlns, "", XmlSpace.Default, 
    encoding);
using (var reader = XmlReader.Create(filepath, settings, context))
{
    return XElement.Load(reader);
}

Isso funciona, mas parece um pouco ineficiente para abrir o arquivo duas vezes. Existe uma maneira melhor para detectar a codificação de tal forma que posso fazer:

 1. Open file
 2. Detect encoding
 3. Read XML into an XElement
 4. Close file
Foi útil?

Solução

Ok, eu deveria ter pensado nisso antes. Ambos XmlTextReader (que nos dá a Encoding) e XmlReader.Create (o que nos permite especificar a codificação) aceita um Stream. Assim como sobre a primeira abertura de um FileStream e depois usar isso com tanto XmlTextReader e XmlReader, como este:

using (var txtreader = new FileStream(filepath, FileMode.Open))
{
    using (var xmlreader = new XmlTextReader(txtreader))
    {
        // Read in the encoding info
        xmlreader.MoveToContent();
        var encoding = xmlreader.Encoding;

        // Rewind to the beginning
        txtreader.Seek(0, SeekOrigin.Begin);

        var settings = new XmlReaderSettings { NameTable = new NameTable() };
        var xmlns = new XmlNamespaceManager(settings.NameTable);
        var context = new XmlParserContext(null, xmlns, "", XmlSpace.Default,
                 encoding);

        using (var reader = XmlReader.Create(txtreader, settings, context))
        {
            return XElement.Load(reader);
        }
    }
}

Isso funciona como um encanto. Lendo arquivos XML de forma independente codificação deveria ter sido mais elegante, mas pelo menos eu estou fugindo com apenas uma abertura de arquivo.

Outras dicas

Outra opção, muito simples, é usar Linq para XML. O método de carga lê automaticamente a codificação do arquivo xml. Você pode, então, obter o valor codificador usando a XDeclaration .Encoding propriedade . Um exemplo da MSDN:

// Create the document
XDocument encodedDoc16 = new XDocument(
new XDeclaration("1.0", "utf-16", "yes"),
new XElement("Root", "Content")
);
encodedDoc16.Save("EncodedUtf16.xml");
Console.WriteLine("Encoding is:{0}", encodedDoc16.Declaration.Encoding);
Console.WriteLine();

// Read the document
XDocument newDoc16 = XDocument.Load("EncodedUtf16.xml");
Console.WriteLine("Encoded document:");
Console.WriteLine(File.ReadAllText("EncodedUtf16.xml"));
Console.WriteLine();
Console.WriteLine("Encoding of loaded document is:{0}", newDoc16.Declaration.Encoding);

Enquanto isso não pode servidor o cartaz original, como ele teria que refazer um monte de código, é útil para alguém que tem que escrever um novo código para o seu projecto, ou se eles pensam que refactoring vale a pena.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top