Написание файлов XML с использованием XmlTextWriter с кодировкой ISO-8859-1 - PullRequest
17 голосов
/ 26 сентября 2008

У меня проблема с записью норвежских символов в файл XML с использованием C #. У меня есть строковая переменная, содержащая некоторый норвежский текст (с такими буквами, как )øå).

Я пишу 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();

Теперь проблема в том, что в этом файле все норвежские символы выглядят забавно.

Я, вероятно, делаю вышеупомянутое каким-то глупым способом. Любые предложения о том, как это исправить?

Ответы [ 6 ]

13 голосов
/ 26 сентября 2008

И ваш StreamWriter, и ваш StreamReader используют UTF-8, потому что вы не указываете кодировку. Вот почему вещи портятся.

Как сказал Томаср, использовать FileStream для начала было бы проще - но также в MemoryStream есть удобный метод "WriteTo", который позволяет очень легко скопировать его в FileStream.

Между прочим, я надеюсь, что в вашем реальном коде есть оператор использования - вы не хотите оставлять дескриптор файла открытым, если что-то идет не так, когда вы пишете в него.

Jon

13 голосов
/ 26 сентября 2008

Почему вы сначала записываете XML в MemoryStream, а затем записываете его в текущий файловый поток? Это довольно неэффективно. Если вы пишете напрямую в FileStream, он должен работать.

Если вы все еще хотите сделать двойную запись, по любой причине, сделайте одно из двух. Или

  1. Убедитесь, что используемые вами объекты StreamReader и StreamWriter все используют такую ​​же кодировку, как и та, которую вы использовали с XmlWriter (не только StreamWriter, как кто-либо другой предлагается), или

  2. Не используйте StreamReader / StreamWriter. Вместо этого просто скопируйте поток на уровне байтов, используя простые byte [] и Stream.Read/Write. В любом случае, это будет намного эффективнее.

8 голосов
/ 26 сентября 2008

Вы должны устанавливать кодировку каждый раз, когда пишете строку или считываете двоичные данные как строку.

    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 голосов
/ 24 ноября 2012

Как уже упоминалось в ответах выше, самая большая проблема здесь - это Encoding, который по умолчанию не указан.

Если вы не указываете Encoding для этого вида конверсии, используется значение по умолчанию UTF-8, которое может соответствовать или не соответствовать вашему сценарию. Вы также без необходимости конвертируете данные, помещая их в MemoryStream, а затем в FileStream.

Если ваши исходные данные не UTF-8, то здесь произойдет следующее: первый переход в MemoryStream попытается декодировать, используя значение по умолчанию Encoding из 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();
3 голосов
/ 26 сентября 2008

Какую кодировку вы используете для отображения файла результатов? Если его нет в ISO-8859-1, он не будет отображаться правильно.

Есть ли причина использовать эту конкретную кодировку вместо, например, UTF8?

0 голосов
/ 18 февраля 2016

После расследования это лучше всего сработало для меня:

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");
...