2008-09-26 68 views
16

Tôi đang gặp sự cố khi viết các ký tự Na Uy vào một tệp XML bằng C#. Tôi có một biến chuỗi có chứa một số văn bản Na Uy (với các chữ cái như æøå).Viết các tệp XML bằng cách sử dụng XmlTextWriter với mã hóa ISO-8859-1

Tôi đang viết XML sử dụng một XmlTextWriter, viết nội dung vào một MemoryStream như thế này:

MemoryStream stream = new MemoryStream(); 
XmlTextWriter xmlTextWriter = new XmlTextWriter(stream, Encoding.GetEncoding("ISO-8859-1")); 
xmlTextWriter.Formatting = Formatting.Indented; 
xmlTextWriter.WriteStartDocument(); //Start doc 

Sau đó, tôi thêm văn bản Na Uy của tôi như thế này:

xmlTextWriter.WriteCData(myNorwegianText); 

Sau đó, tôi viết tập tin vào đĩa như thế này:

FileStream myFile = new FileStream(myPath, FileMode.Create); 
StreamWriter sw = new StreamWriter(myFile); 

stream.Position = 0; 
StreamReader sr = new StreamReader(stream); 
string content = sr.ReadToEnd(); 

sw.Write(content); 
sw.Flush(); 

myFile.Flush(); 
myFile.Close(); 

Bây giờ vấn đề là trong tập tin này, tất cả các Norw nhân vật egian trông buồn cười.

Tôi có thể đang làm việc trên theo một số cách ngu ngốc. Bất kỳ đề xuất về cách sửa chữa nó?

+0

Hãy nhớ rằng, bạn cũng có thể sử dụng bảng mã UTF-16 chung chung hơn để viết các ký tự Na Uy . –

Trả lời

13

Tại sao bạn viết XML trước tiên vào MemoryStream và sau đó ghi nó vào luồng tệp thực? Điều đó khá không hiệu quả. Nếu bạn viết trực tiếp vào FileStream thì nó sẽ hoạt động.

Nếu bạn vẫn muốn viết hai lần, vì bất kỳ lý do gì, hãy làm một trong hai điều. Hoặc

  1. Hãy chắc chắn rằng StreamReader và StreamWriter đối tượng bạn sử dụng tất cả sử dụng cùng một mã hóa như một trong những bạn sử dụng với các XmlWriter (không chỉ là StreamWriter, giống như ai đó gợi ý), hoặc

  2. Không sử dụng StreamReader/StreamWriter. Thay vào đó, chỉ cần sao chép luồng ở cấp byte bằng cách sử dụng một byte đơn giản [] và Stream.Read/Write. Điều này sẽ được, btw, rất nhiều hiệu quả hơn anyway.

+3

Một lý do để ghi vào luồng bộ nhớ là vì làm như vậy sẽ tạo ra một hành động nguyên tử. Hãy xem bài viết này để biết thêm chi tiết: http://aspalliance.com/1012_how_to_write_atomic_transactions_in_net – Dscoduc

3

Bạn sử dụng mã hóa nào để hiển thị tệp kết quả? Nếu nó không nằm trong ISO-8859-1, nó sẽ không hiển thị chính xác.

Có lý do nào để sử dụng mã hóa cụ thể này, thay vì ví dụ UTF8 không?

13

Cả StreamWriter và Trình quản lý luồng của bạn đều đang sử dụng UTF-8, vì bạn không chỉ định mã hóa. Đó là lý do tại sao mọi thứ đang bị hỏng.

Như tomasr đã nói, sử dụng một FileStream để bắt đầu sẽ đơn giản hơn - nhưng MemoryStream có phương thức "WriteTo" tiện dụng cho phép bạn sao chép nó vào một FileStream rất dễ dàng.

Tôi hy vọng bạn đã có một tuyên bố sử dụng trong mã thực của bạn, nhân tiện - bạn không muốn để mở tệp của bạn xử lý mở nếu có gì đó không ổn trong khi bạn đang viết thư cho nó.

Jon

7

Bạn cần đặt mã hóa mọi lúc bạn viết chuỗi hoặc đọc dữ liệu nhị phân dưới dạng chuỗi.

Encoding encoding = Encoding.GetEncoding("ISO-8859-1"); 

    FileStream myFile = new FileStream(myPath, FileMode.Create); 
    StreamWriter sw = new StreamWriter(myFile, encoding); 

    stream.Position = 0; 
    StreamReader sr = new StreamReader(stream, encoding); 
    string content = sr.ReadToEnd(); 

    sw.Write(content); 
    sw.Flush(); 

    myFile.Flush(); 
    myFile.Close(); 
5

Như đã đề cập trong câu trả lời ở trên, vấn đề lớn nhất ở đây là Encoding, hiện đang được mặc định do không được chỉ định.

Khi bạn không chỉ định Encoding cho loại chuyển đổi này, mặc định là UTF-8 được sử dụng - có thể có hoặc không phù hợp với kịch bản của bạn. Bạn cũng đang chuyển đổi dữ liệu không cần thiết bằng cách đẩy nó vào một MemoryStream và sau đó ra thành một FileStream.

Nếu dữ liệu gốc của bạn không phải là UTF-8, điều sẽ xảy ra ở đây là chuyển đổi đầu tiên vào MemoryStream sẽ cố gắng giải mã bằng cách sử dụng mặc định Encoding của UTF-8 - và làm hỏng dữ liệu của bạn. Sau đó, khi bạn ghi vào FileStream, cũng đang sử dụng UTF-8 làm mã hóa theo mặc định, bạn chỉ cần duy trì tham nhũng đó vào tệp.

Để khắc phục vấn đề, bạn có thể cần phải chỉ định Encoding vào các đối tượng Stream của mình.

Bạn thực sự có thể bỏ qua toàn bộ quá trình MemoryStream - cũng sẽ nhanh hơn và hiệu quả hơn. đang cập nhật của bạn có thể trông giống như hơn:

FileStream fs = new FileStream(myPath, FileMode.Create); 

XmlTextWriter xmlTextWriter = 
    new XmlTextWriter(fs, Encoding.GetEncoding("ISO-8859-1")); 

xmlTextWriter.Formatting = Formatting.Indented; 
xmlTextWriter.WriteStartDocument(); //Start doc 

xmlTextWriter.WriteCData(myNorwegianText); 

StreamWriter sw = new StreamWriter(fs); 

fs.Position = 0; 
StreamReader sr = new StreamReader(fs); 
string content = sr.ReadToEnd(); 

sw.Write(content); 
sw.Flush(); 

fs.Flush(); 
fs.Close(); 
+0

Mặc dù bạn đã sửa lỗi theo cách bạn đã nói nhưng nó hơi khó hiểu vì anh ta chỉ định mã hóa trong xmltextwriter. nhưng khi bạn nói rằng anh ấy đã không đặt nó trong luồng mới mà anh ấy đã tạo sau này và với điều này, nó không đọc từ luồng nguồn nhưng sẽ hoàn nguyên mặc định – MikeT

0

Sau khi điều tra, đây là làm việc tốt nhất cho tôi:

var doc = new XDocument(new XDeclaration("1.0", "ISO-8859-1", "")); 
     using (XmlWriter writer = doc.CreateWriter()){ 
      writer.WriteStartDocument(); 
      writer.WriteStartElement("Root"); 
      writer.WriteElementString("Foo", "value"); 
      writer.WriteEndElement(); 
      writer.WriteEndDocument(); 
     } 
     doc.Save("dte.xml"); 
Các vấn đề liên quan