Вопрос

Для загрузки файлов XML с произвольной кодировкой у меня есть следующий код:

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);
}

Это работает, но кажется немного неэффективным, чтобы открыть файл дважды. Есть ли лучший способ обнаружить кодировку, чтобы я мог сделать:

 1. Open file
 2. Detect encoding
 3. Read XML into an XElement
 4. Close file
Это было полезно?

Решение

Хорошо, я должен был подумать об этом раньше. И XmlTextReader (который дает нам кодировку), и XmlReader.Create (который позволяет нам указать кодировку) принимают поток. Итак, как насчет того, чтобы сначала открыть FileStream, а затем использовать его с XmlTextReader и XmlReader, например, так:

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);
        }
    }
}

Это работает как шарм. Чтение файлов XML независимым от кодировки способом должно быть более элегантным, но, по крайней мере, я открываю только один открытый файл.

Другие советы

Другой простой способ - использовать Linq для XML. Метод Load автоматически читает кодировку из файла xml. Затем вы можете получить значение кодировщика, используя XDeclaration Свойство .Encoding . Пример из 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);

Несмотря на то, что он может не обслуживать оригинальный постер, так как ему придется рефакторинг большого количества кода, это полезно для тех, кто должен написать новый код для своего проекта, или если они думают, что рефакторинг того стоит.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top