Escrevendo arquivos XML usando XMLTextWriter com codificação ISO-8859-1
-
02-07-2019 - |
Pergunta
Estou tendo problemas para escrever caracteres noruegueses em um arquivo XML usando C#. Eu tenho uma variável de string contendo algum texto norueguês (com letras como æøå).
Estou escrevendo o XML usando um XMLTextWriter, escrevendo o conteúdo em um Memorystream como este:
MemoryStream stream = new MemoryStream();
XmlTextWriter xmlTextWriter = new XmlTextWriter(stream, Encoding.GetEncoding("ISO-8859-1"));
xmlTextWriter.Formatting = Formatting.Indented;
xmlTextWriter.WriteStartDocument(); //Start doc
Então eu adiciono meu texto norueguês como este:
xmlTextWriter.WriteCData(myNorwegianText);
Então escrevo o arquivo para disco assim:
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();
Agora, o problema é que, no arquivo, todos os personagens noruegueses parecem engraçados.
Provavelmente estou fazendo da maneira mais estúpida. Alguma sugestão em como consertar?
Solução
Por que você está escrevendo o XML primeiro em um MemoryStream e depois escrevendo isso no fluxo de arquivos real? Isso é bastante ineficiente. Se você escrever diretamente para o Filestream, ele deve funcionar.
Se você ainda quiser escrever duplo, por qualquer motivo, faça uma de duas coisas. Qualquer
Certifique -se de que os objetos StreamReader e Streamwriter que você usa tudo use o mesmo codificação como o que você usou com o XMLWriter (não apenas o streamwriter, como alguém sugeriu), ou
Não use StreamReader/StreamWriter. Em vez disso, basta copiar o fluxo no nível de bytes usando um byte simples [] e stream.read/write. De qualquer maneira, isso vai ser, btw, muito mais eficiente.
Outras dicas
O seu streamwriter e o streamreader estão usando o UTF-8, porque você não está especificando a codificação. É por isso que as coisas estão ficando corrompidas.
Como Tomasr disse, o uso de um FileStream para começar seria mais simples - mas também a MemoryStream possui o método útil "WritEto", que permite copiá -lo para um Filestream com muita facilidade.
Espero que você tenha uma declaração de uso em seu código real, a propósito - você não deseja deixar o identificador de arquivo aberto se algo der errado enquanto estiver escrevendo para ele.
Jon
Você precisa definir a codificação sempre que escrever uma string ou ler dados binários como uma string.
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();
Como mencionado nas respostas acima, o maior problema aqui é o Encoding
, que está sendo padronizado devido a não ser especificado.
Quando você não especifica um Encoding
Para esse tipo de conversão, o padrão de UTF-8
é usado - que pode ou não corresponder ao seu cenário. Você também está convertendo os dados desnecessariamente empurrando -os para um MemoryStream
e depois para um FileStream
.
Se seus dados originais não forem UTF-8
, o que acontecerá aqui é que a primeira transição para o MemoryStream
tentará decodificar usando o padrão Encoding
do UTF-8
- e corrompe seus dados como resultado. Quando você então escreve para o FileStream
, que também está usando UTF-8
Como codificação por padrão, você simplesmente persiste essa corrupção no arquivo.
Para corrigir o problema, você provavelmente precisa especificar Encoding
dentro de voce Stream
objetos.
Você pode realmente pular o MemoryStream
Processo inteiramente, também - que será mais rápido e mais eficiente. Seu código atualizado pode parecer algo mais como:
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();
Qual codificação você usa para exibir o arquivo de resultado? Se não estiver no ISO-8859-1, não será exibido corretamente.
Existe uma razão para usar essa codificação específica, em vez de, por exemplo, UTF8?
Depois de investigar, isso funcionou melhor para mim:
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");