2009-08-23 197 views
2

我们使用DataContractSerializer将我们的数据序列化为XML。最近我们发现了一个错误,说明字符串"\r\n"被保存并回读 - 它变成了"\n"。很显然,是什么原因导致这是使用XmlWriterIndent = true集:如何正确地将只包含“ r n”的字符串序列化为XML?

// public class Test { public string Line; } 

var serializer = new DataContractSerializer(typeof(Test)); 

using (var fs = File.Open("C:/test.xml", FileMode.Create)) 
using (var wr = XmlWriter.Create(fs, new XmlWriterSettings() { Indent = true })) 
    serializer.WriteObject(wr, new Test() { Line = "\r\n" }); 

Test test; 
using (var fs = File.Open("C:/test.xml", FileMode.Open)) 
    test = (Test) serializer.ReadObject(fs); 

最明显的解决方法是停止缩进XML,并确实移除“XmlWriter.Create”行使得Line值往返正确,无论是"\n""\r\n"或还要别的吗。

然而,这样DataContractSerializer写它似乎仍不是完全安全的或者甚至是正确的 - 例如,只是读与XML记事本生成的文件,并重新保存它会破坏双方"\n""\r\n"值完全。

这里的正确方法是什么?使用XML作为序列化二进制数据的一种有缺陷的概念?我们错误地期望像XML记事本这样的工具不会破坏我们的数据吗?我们是否需要增加每个可能包含具有某些特殊属性的文本的每个string字段,可能是强制CDATA的内容?

回答

3

可能您可以使用CDATA,但我同意您的总结,即使用XML来串行化二进制数据只是错误的。你能否以另一种方式传达数据?

+0

所以,你会说使用DataContractSerializer并期望获得与您保存的完全相同的数据是一个错误? – 2009-08-23 11:52:48

+0

我怀疑它不能被称为错误,直到您检查CDATA节是否处理它。换行符是一个边缘情况,因为显然系统中的换行符不一定与我的相同,所以我可以原谅这样的实现。我会尝试强制使用CDATA方法。 – 2009-08-23 11:56:59

+0

找不到任何告诉DataContractSerializer使用CDATA的方法... – 2009-08-23 14:04:28

1

为什么区分包含'\ r \ n'的字符串和空字符串很重要?一般来说,在使用数据合约序列化时,只要“正确地往返”,您不关心XML格式/结构或数据如何存储数据。

这是我们如何使用它:

DataContractSerializer serializer = CreateSerializer(this.GetType()); 
XmlWriterSettings settings = new XmlWriterSettings(); 
settings.Indent = true; 
using (XmlWriter writer = XmlTextWriter.Create(sb, settings)) 
{ 
    serializer.WriteObject(writer, this); 
    writer.Flush(); 
} 


internal static T Deserialize<T>(Stream stream) 
{ 
    DataContractSerializer serializer = CreateSerializer(typeof(T)); 
    return (T)serializer.ReadObject(stream); 
} 

public static DataContractSerializer CreateSerializer(Type type) 
{ 
    DataContractSerializer serializer = new DataContractSerializer(); 
    return serializer; 
} 

如果我没有记错的话,好像换行字符是一个XML值中允许使用的字符,并会需要作编码或CDATA节contrained。数据协定序列化程序既不做这些。像XML记事本这样的工具正在改变数据,因为他们意识到这些不是合法的字符,并将其删除以创建符合标准的XML。

字符串数据在二进制序列化程序和XML序列化程序之间可以以不同的方式返回,这并不奇怪。二进制串行器将串行化数据位的确切二进制表示,并且对合法字符等没有“规则”。

+0

>>>“为什么区分重要” - 有时不是,有时候是。从BinaryFormatter迁移,意识到字符串现在可以回到与保存方式不同的状态,这是一个惊喜。 >>>“你不关心XML格式/结构” - 的确如此;然而,看到XML记事本改变我们的数据令人担忧,让我想知道我们做错了什么。 – 2009-08-23 12:20:56

+1

@romkyns:更新我的答案以解决您的疑虑。总的来说,只要你的对象反序列化正确,我认为你没有做任何“错误”的事情。我仍然不明白为什么需要区分空行('\ r \ n')和空字符串。 – 2009-08-23 12:35:41

+0

我也了解这个问题。如果你通过其中有CRLF的线串行化一个字符串,接收者将得到LF。它不会往返! – 2009-08-27 16:52:46

相关问题