Написание 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");