是什么区别StringWriter
和StringBuilder
,当我应该使用一个或其他?
我认为任何现有的答案都不能真正回答这个问题.两个类之间的实际关系是适配器模式的一个示例.
StringWriter
Write...
通过转发到StringBuilder
它存储在字段中的实例来实现其所有方法.这不仅仅是一个内部细节,因为它StringWriter
有一个返回内部字符串构建器的公共方法GetStringBuilder,以及一个允许您传入现有的构造函数StringBuilder
.
所以StringWriter
是允许适配器StringBuilder
被用来作为代码的目标是希望与合作TextWriter
.在基本行为方面,显然没有什么可以在它们之间做出选择...除非你可以衡量转发呼叫的开销,在这种情况下StringWriter
稍微慢一点,但这似乎不太可能是重要的.
那么,为什么他们不把StringBuilder
实现TextWriter
直接?这是一个灰色区域,因为界面背后的意图乍一看并不总是清晰.
TextWriter
是非常接近的,接受的字符流的东西接口.但它有一个额外的皱纹:一个名为编码的属性.这意味着它TextWriter
是接受字符流并且还将它们转换为字节的接口.
这是一个无用的遗迹,StringWriter
因为它不执行编码.该文件说:
对于某些XML方案,此属性是必需的,其中必须编写包含StringWriter使用的编码的标头.这允许XML代码使用任意StringWriter并生成正确的XML头.
但这不可能是正确的,因为我们无法指定Encoding
for 的值StringWriter
.该物业总是有价值UnicodeEncoding
.因此,任何检查此属性以构建XML头的代码总是会说utf-16
.例如:
var stringWriter = new StringWriter(); using (var xmlWriter = XmlWriter.Create(stringWriter)) xDocument.WriteTo(xmlWriter);
这会产生标题:
如果您使用File.WriteAllText将XML字符串写入文件,该怎么办?默认情况下,您将拥有一个utf-8
带utf-16
标题的文件.
在这种情况下,使用它会更安全StreamWriter
,并使用文件路径或a来构造它FileStream
,或者如果要检查数据然后使用a MemoryStream
,那么获取一个字节数组.所有这些组合将确保编码到字节和标题生成由您的相同Encoding
值引导StreamWriter
.
该Encoding
属性的目的是允许字符流的生成器将关于编码的准确信息包括在字符流本身中(例如在XML示例中;其他示例包括电子邮件头等等).
但是通过引入StringWriter
,内容生成和编码之间的链接被破坏,因此这种自动机制停止工作并且可能容易出错.
不过,StringWriter
如果您小心谨慎,它是一个有用的适配器,即您了解您的内容生成代码不应该依赖于Encoding
属性的无意义值.但是这种警告通常与适配器模式有关.这通常是一种破坏,允许你将一个方形但几乎圆形的钉子装入一个圆孔.
StringWriter
派生自TextWriter
,允许各种类写文本而不关心它的发展方向.在这种情况下StringWriter
,输出只是内存.如果您正在调用需要的API TextWriter
但您只想在内存中构建结果,则可以使用此方法.
StringBuilder
本质上是一个缓冲区,它允许您执行多个操作(通常是附加)到"逻辑字符串",而不是每次都创建一个新的字符串对象.您可以使用它在多个操作中构造一个字符串.
在以前的(好的)答案的基础上,StringWriter实际上比StringBuilder具有更多的功能,并提供许多重载。
例如:
虽然Stringbuilder仅接受字符串,否则不接受附录
StringBuilder sb = new StringBuilder(); sb.AppendLine("A string");
StringWriter可以直接采用字符串格式
StringWriter sw = new StringWriter(); sw.WriteLine("A formatted string {0}", DateTime.Now);
使用StringBuilder必须做到这一点(或使用string.Format或$“”)
sb.AppendFormat("A formatted string {0}", DateTime.Now); sb.AppendLine();
没有做或死的东西,但还是有区别