【问题标题】:How to best detect encoding in XML file?如何最好地检测 XML 文件中的编码?
【发布时间】:2010-10-12 21:04:28
【问题描述】:

要加载具有任意编码的 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. 打开文件
  2. 检测编码
  3. 将 XML 读入 XElement
  4. 关闭文件

【问题讨论】:

    标签: encoding linq-to-xml xmlreader xelement


    【解决方案1】:

    另一个非常简单的选择是使用 Linq to 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);
    

    虽然这可能不符合原始发布者的要求,因为他必须重构大量代码,但对于必须为他们的项目编写新代码的人,或者如果他们认为重构是值得的,这很有用。

    【讨论】:

      【解决方案2】:

      好的,我应该早点想到这一点。 XmlTextReader(它为我们提供编码)和 XmlReader.Create(它允许我们指定编码)都接受一个 Stream。那么如何首先打开一个 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 文件应该更优雅,但至少我只打开了一个文件。

      【讨论】:

      • 在检测编码方面,调用 XmlReaderCreate(Stream) 重载是否会以相同的方式工作?
      • @petrk。 - 我明确使用 XmlTextReader,因为这是提供 Encoding 属性的类。不知道你还有什么想法?
      • 好吧,让我解释一下。似乎XElement.Load(XmlReader.Create(new FileStream(filepath, FileMode.Open))) 应该做一些事情(为简洁起见省略了处理资源)。 XmlReader.Create(Stream) 的文档说:XmlReader 扫描流的第一个字节以查找字节顺序标记或其他编码符号。确定编码后,编码用于继续读取流,并且处理继续将输入解析为(Unicode)字符流。我想知道您是否显式
      • 编码检测与 XmlReader.Create(Stream) 重载所做的有任何不同。
      • @petrk。有趣...我确定我当时遇到了 XmlReader 单独不起作用的情况,我必须通过解析器上下文明确指定编码才能使其工作。我应该在这里记录更多我的场景,因为现在我不记得所有的细节了:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      • 1970-01-01
      • 2010-09-05
      相关资源
      最近更新 更多