2009-03-12 20 views
7

Para cargar archivos XML con la codificación arbitraria tengo el siguiente código:¿Cómo detectar mejor la codificación en un archivo 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); 
} 

Esto funciona, pero parece un poco ineficiente para abrir el archivo dos veces. ¿Hay una mejor manera de detectar la codificación de tal manera que puedo hacer:

1. Open file 
2. Detect encoding 
3. Read XML into an XElement 
4. Close file 

Respuesta

8

Ok, yo debería haber pensado en esto antes. Tanto XmlTextReader (que nos da la codificación) como XmlReader.Create (que nos permite especificar la codificación) aceptan una transmisión. Entonces, ¿cómo trata de abrir por primera vez un FileStream y luego usar esto con tanto XMLTextReader y XmlReader, así:

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

Esto funciona como un encanto. Leer archivos XML de una manera independiente de la codificación debería haber sido más elegante, pero al menos me estoy saliendo con un solo archivo abierto.

+0

Llamar a la sobrecarga [XmlReaderCreate (Stream)] (http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.create.aspx) funciona de la misma manera en términos de detección de la codificación? –

+0

@petrk. - Estoy usando XmlTextReader explícitamente ya que esa es la clase que proporciona la propiedad 'Encoding'. ¿No estás seguro de qué más tienes en mente? –

+0

Bien, déjame explicarte. Parece que 'XElement.Load (XmlReader.Create (new FileStream (filepath, FileMode.Open)))' debería hacer algo (eliminando recursos por brevedad). La documentación de [XmlReader.Create (Stream)] (http://msdn.microsoft.com/en-us/library/756wd7zs.aspx) dice: _El XmlReader escanea los primeros bytes de la secuencia en busca de una marca de orden de bytes o otro signo de codificación. Cuando se determina la codificación, la codificación se utiliza para seguir leyendo la secuencia, y el procesamiento continúa analizando la entrada como una secuencia de caracteres (Unicode). Me preguntaba si su detección de codificación –

0

Otra opción, bastante simple, es usar Linq en XML. El método Load lee automáticamente la codificación del archivo xml. A continuación, puede obtener el valor del codificador utilizando la propiedad XDeclaration.Encoding. Un ejemplo de 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); 

bien esto puede no servidor de su creador original, ya que tendría que refactorizar mucho código, es útil para alguien que tiene que escribir código nuevo para su proyecto, o si ellos piensan que la refactorización vale la pena.

Cuestiones relacionadas