我有这种扩展方法
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var stringWriter = new StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
但每当我调用它时,它指定的编码为utf-16
,即<?xml version="1.0" encoding="utf-16"?>
。我做错了什么?
答案 0 :(得分:16)
字符串是UTF-16,因此写入StringWriter将始终使用UTF-16。如果那不是您想要的,那么使用其他TextWriter
派生类,使用您喜欢的编码。
答案 1 :(得分:15)
据我所知,StringWriter类在序列化为字符串时将始终使用UTF 16编码。您可以编写自己的覆盖类,接受不同的编码:
public class StringWriterWithEncoding : StringWriter
{
private readonly Encoding _encoding;
public StringWriterWithEncoding()
{
}
public StringWriterWithEncoding(IFormatProvider formatProvider)
: base(formatProvider)
{
}
public StringWriterWithEncoding(StringBuilder sb)
: base(sb)
{
}
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider)
: base(sb, formatProvider)
{
}
public StringWriterWithEncoding(Encoding encoding)
{
_encoding = encoding;
}
public StringWriterWithEncoding(IFormatProvider formatProvider, Encoding encoding)
: base(formatProvider)
{
_encoding = encoding;
}
public StringWriterWithEncoding(StringBuilder sb, Encoding encoding)
: base(sb)
{
_encoding = encoding;
}
public StringWriterWithEncoding(StringBuilder sb, IFormatProvider formatProvider, Encoding encoding)
: base(sb, formatProvider)
{
_encoding = encoding;
}
public override Encoding Encoding
{
get { return (null == _encoding) ? base.Encoding : _encoding; }
}
}
所以你可以改用它:
using(var stringWriter = new StringWriterWithEncoding( Encoding.UTF8))
{
...
}
答案 2 :(得分:1)
您应该从StringWriter派生一个具有覆盖编码属性的新类。
答案 3 :(得分:0)
正如接受的答案所说,StringWriter
默认为UTF-16(Unicode)设计。如果你想通过最终得到一个UTF-8字符串来实现它,我有两种方法可以帮你完成它:
解决方案#1(效率不高,做法不好,但完成工作):将其转储到文本文件并重新读取,删除文件(可能只适合对于小文件,如果你甚至想要这样做 - 只是想表明它可以完成!)
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var xmlWriter = XmlWriter.Create("MyFile.xml", settings))
{
serializer.Serialize(xmlWriter, value);
}
XmlDocument xml = new XmlDocument();
xml.Load("MyFile.xml");
byte[] bytes = Encoding.UTF8.GetBytes(xml.OuterXml);
File.Delete("MyFile.xml");
return Encoding.UTF8.GetString(bytes);
}
解决方案#2(更好,更简单,更优雅的解决方案!):使用StringWriter
执行此操作,但使用其Encoding
属性进行设置到UTF-8:
public static string SerializeObject<T>(this T value)
{
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(true),
Indent = false,
OmitXmlDeclaration = false,
NewLineHandling = NewLineHandling.None
};
using(var stringWriter = new UTF8StringWriter())
{
using(var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return stringWriter.ToString();
}
}
public class UTF8StringWriter : StringWriter
{
public override Encoding Encoding
{
get
{
return Encoding.UTF8;
}
}
}
答案 4 :(得分:0)
如果您不想使用从StringWriter
派生的类,那么您可以将OmitXmlDeclaration
设置为false
并声明自己的类,就像我请执行以下操作:
public static string Serialize<T>(this T value, string xmlDeclaration = "<?xml version=\"1.0\"?>") where T : class, new()
{
if (value == null) return string.Empty;
using (var stringWriter = new StringWriter())
{
var settings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = xmlDeclaration != null,
};
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
var xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(xmlWriter, value);
var sb = new StringBuilder($"{Environment.NewLine}{stringWriter}");
sb.Insert(0, xmlDeclaration);
return sb.ToString();
}
}
答案 5 :(得分:0)
@ john-saunders在回答中提到:
StringWriter将始终使用UTF-16
因此我为此目的使用了MemoryStream。
在我的情况下,我使用Windows-1251编码。
var xmlSstring = "";
using (var ms = new MemoryStream())
{
var encoding = Encoding.GetEncoding(1251);
var settings = new XmlWriterSettings
{
Indent = true,
Encoding = encoding
};
using (var xmlTextWriter = XmlWriter.Create(ms, settings))
{
doc.Save(xmlTextWriter);
xmlString = encoding.GetString(ms.ToArray());
}
}