2009-03-12 11 views
7

Để tải file XML với mã hóa tùy ý Tôi có đoạn mã sau:Cách phát hiện mã hóa tốt nhất trong tệp 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); 
} 

này hoạt động, nhưng nó có vẻ hơi kém hiệu quả để mở tập tin hai lần. Có cách nào tốt hơn để phát hiện mã hóa như vậy mà tôi có thể thực hiện:

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

Trả lời

8

Ok, tôi nên nghĩ về điều này trước đó. Cả XmlTextReader (cung cấp cho chúng tôi Mã hóa) và XmlReader.Create (cho phép chúng tôi chỉ định mã hóa) chấp nhận Luồng. Vì vậy, làm thế nào về lần đầu tiên mở một FileStream và sau đó sử dụng này với cả XmlTextReader và XmlReader, như thế này:

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

Điều này làm việc như một say mê. Đọc các tập tin XML một cách độc lập mã hóa nên đã được thanh lịch hơn nhưng ít nhất tôi đang nhận được đi với chỉ có một tập tin mở.

+0

Chỉ cần gọi [XmlReaderCreate (Stream)] (http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.create.aspx) quá tải hoạt động giống như cách phát hiện mã hóa? –

+0

@petrk. - Tôi đang sử dụng XmlTextReader một cách rõ ràng vì đó là lớp cung cấp thuộc tính 'Encoding'. Bạn không chắc chắn những gì khác bạn đã có trong tâm trí? –

+0

Phải, hãy để tôi giải thích. Có vẻ như 'XElement.Load (XmlReader.Create (FileStream mới (filepath, FileMode.Open)))' nên làm điều gì đó (vứt bỏ các tài nguyên bị bỏ qua cho ngắn gọn). Tài liệu cho [XmlReader.Create (Stream)] (http://msdn.microsoft.com/en-us/library/756wd7zs.aspx) nói: _The XmlReader quét các byte đầu tiên của luồng tìm kiếm một dấu thứ tự byte hoặc dấu hiệu khác của mã hóa. Khi mã hóa được xác định, mã hóa được sử dụng để tiếp tục đọc luồng và xử lý tiếp tục phân tích cú pháp đầu vào dưới dạng luồng (Unicode) characters._ Tôi đã tự hỏi liệu phát hiện mã hóa –

0

Một tùy chọn khác, khá đơn giản, là sử dụng LINQ to XML. Phương thức tải tự động đọc mã hóa từ tệp xml. Sau đó, bạn có thể nhận được giá trị bộ mã hóa bằng cách sử dụng thuộc tính XDeclaration.Encoding. Một ví dụ từ 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); 

Trong khi điều này có thể không phải máy chủ các poster ban đầu, như ông sẽ phải cấu trúc lại rất nhiều mã, nó rất hữu ích đối với những người phải viết mã mới cho dự án của họ, hoặc nếu họ nghĩ rằng tái cấu trúc là giá trị nó.