Написание XML файлов с использованием XmlTextWriter с кодировкой ISO-8859-1
У меня возникла проблема с написанием норвежских символов в XML файл с использованием С#. У меня есть строковая переменная, содержащая некоторый норвежский текст (с буквами, такими как æøå).
Я пишу XML, используя XmlTextWriter, записывая содержимое в MemoryStream следующим образом:
MemoryStream stream = new MemoryStream();
XmlTextWriter xmlTextWriter = new XmlTextWriter(stream, Encoding.GetEncoding("ISO-8859-1"));
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.WriteStartDocument(); //Start doc
Затем я добавляю свой норвежский текст следующим образом:
xmlTextWriter.WriteCData(myNorwegianText);
Затем я пишу файл на диск следующим образом:
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();
Теперь проблема в том, что в файле по этому поводу все норвежские символы выглядят забавно.
Я, наверное, делаю это выше, глупо. Любые предложения по его исправлению?
Ответы
Ответ 1
Почему вы сначала пишете XML в MemoryStream, а затем записываете его в фактический поток файлов? Это довольно неэффективно. Если вы пишете напрямую в FileStream, он должен работать.
Если вы все еще хотите сделать двойную запись, по какой-то причине, выполните одно из двух действий. Либо
-
Убедитесь, что все объекты StreamReader и StreamWriter, которые вы используете, используют ту же самую кодировку, что и тот, который вы использовали с XmlWriter (а не только StreamWriter, как и кто-то другой), или
-
Не используйте StreamReader/StreamWriter. Вместо этого просто скопируйте поток на уровне байта, используя простой байт [] и Stream.Read/Write. Это будет, кстати, намного более эффективно.
Ответ 2
Как ваш StreamWriter, так и ваш StreamReader используют UTF-8, потому что вы не указываете кодировку. Вот почему все становится поврежденным.
Как сказал Томаср, использование FileStream для начала было бы проще - но также MemoryStream имеет удобный метод "WriteTo", который позволяет легко скопировать его в FileStream.
Я надеюсь, что у вас есть действующий оператор в вашем реальном коде, кстати - вы не хотите оставить свой дескриптор файла открытым, если что-то пойдет не так, когда вы его пишете.
Джон
Ответ 3
Вам нужно установить кодировку каждый раз, когда вы пишете строку или читаете двоичные данные в виде строки.
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();
Ответ 4
Как уже упоминалось в приведенных выше ответах, самая большая проблема здесь - это Encoding
, который по умолчанию считается неуказанным.
Если вы не укажете Encoding
для такого преобразования, используется значение по умолчанию UTF-8
, которое может или не может соответствовать вашему сценарию. Вы также произвольно конвертируете данные, нажимая их на MemoryStream
, а затем на FileStream
.
Если ваши исходные данные не являются UTF-8
, здесь будет происходить то, что первый переход в MemoryStream
будет пытаться декодировать с использованием по умолчанию Encoding
of UTF-8
- и приведет к повреждению ваших данных. Когда вы затем записываете в FileStream
, который по умолчанию использует UTF-8
как кодировку, вы просто сохраняете это повреждение в файле.
Чтобы исправить эту проблему, вам, вероятно, нужно указать Encoding
в ваши объекты Stream
.
Фактически вы можете вообще пропустить процесс MemoryStream
, который будет быстрее и эффективнее. Ваш обновленный код может выглядеть примерно так:
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();
Ответ 5
Какую кодировку вы используете для отображения файла результатов? Если он не находится в ISO-8859-1, он будет отображаться неправильно.
Есть ли причина использовать эту конкретную кодировку, а не, например, UTF8?
Ответ 6
После исследования, это то, что сработало лучше всего для меня:
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");