StringWriter或StringBuilder
StringWriter
和StringBuilder
什么区别,什么时候应该使用一个或另一个?
我不认为任何现有的答案真的回答了这个问题。 这两个类之间的实际关系就是适配器模式的一个例子。
StringWriter
通过转发到存储在字段中的StringBuilder
实例来实现其所有Write...
方法。 这不仅仅是一个内部细节,因为StringWriter
有一个公共方法GetStringBuilder ,它返回内部的string生成器,也是一个构造函数 ,允许你传入一个现有的StringBuilder
。
所以StringWriter
是一个适配器,它允许StringBuilder
作为一个代码来使用TextWriter
。 就基本行为而言,他们之间显然没有什么可以select的……除非你能测量转发调用的开销,在这种情况下, StringWriter
稍微慢一些,但这似乎不太可能是重要的。
那么为什么他们不让StringBuilder
直接实现TextWriter
呢? 这是一个灰色地带,因为界面背后的意图乍一看并不一定总是清晰的。
TextWriter
几乎是接受字符stream的接口。 但它有一个额外的皱纹:一个称为Encoding的属性。 这意味着TextWriter
是一个接受一个字符stream并将它们转换为字节的接口 。
在StringWriter
这是一个无用的痕迹,因为它不执行编码。 该文件说:
此属性对于某些必须写入包含StringWriter使用的编码的XML场景是必需的。 这允许XML代码使用任意的StringWriter并生成正确的XML标题。
但是这是不对的,因为我们没有办法指定StringWriter
的Encoding
值。 该属性的值始终为UnicodeEncoding
。 因此,任何检查这个属性来构build一个XML头的代码总是会说utf-16
。 例如:
var stringWriter = new StringWriter(); using (var xmlWriter = XmlWriter.Create(stringWriter)) xDocument.WriteTo(xmlWriter);
这会产生标题:
<?xml version="1.0" encoding="utf-16"?>
如果使用File.WriteAllText将XMLstring写入文件会怎么样? 默认情况下,你会有一个utf-8
文件的utf-8
文件。
在这种情况下,使用StreamWriter
会比较安全,并使用文件path或FileStream
构造它,或者如果要检查数据,则使用MemoryStream
并获取字节数组 。 所有这些组合都将确保编码字节和标题生成在StreamWriter
由相同的Encoding
值引导。
Encoding
属性的目的是允许字符stream生成器将关于编码的准确信息包含到字符stream本身中(例如在XML示例中;其他示例包括电子邮件标题等)。
但是,通过引入StringWriter
,内容生成和编码之间的链接被破坏,所以这种自动机制停止工作,并可能出错。
不过,如果你小心, StringWriter
是一个有用的适配器,也就是说你明白你的内容生成代码不应该依赖Encoding
属性的无意义的值。 但是这种警告通常与适配器模式有关。 这通常是一种方法,可以让你将一个几乎是圆形的钉子装进一个圆孔中。
StringWriter
派生自TextWriter
,它允许不同的类写文本,而不必关心它发生的地方。 在StringWriter
的情况下,输出只是进入内存。 如果您要调用需要TextWriter
的API,但只想在内存中创build结果,则可以使用此方法。
StringBuilder
本质上是一个缓冲区,它允许你执行多个操作(通常追加)到一个“逻辑string”,而不是每次创build一个新的string对象。 你可以用这个在多个操作中构造一个string。
StringBuilder
类基本上是一个可变string,一个帮助类来构造一个不可变的string。 StringWriter
构build在顶部,为string格式添加更多便利function。
一个StringWriter
被用来写文本 一份文件 内存和一个StringBuilder
被用来以一种有效的方式将string追加到一起。
基于以前的(良好)答案,StringWriter实际上比StringBuilderfunction更多,提供了很多重载。
例如:
虽然Stringbuilder只接受一个string或没有任何附录
StringBuilder sb = new StringBuilder(); sb.AppendLine("A string");
StringWriter可以直接使用string格式
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();
不做或死的东西,但仍然是一个区别
StringBuilder
用于批量string连接。 对于超过5个string更有效,据我所知,然后String.Concat()
。 也可以使用特定的格式( .AppendFormat()
)
StringBuilder
和StringReader
用于改善不同情况下的性能。
使用 StringBuilder
来提高string操作的性能,例如连接,重复修改string。
Random rnd = new Random(); StringBuilder sb = new StringBuilder(); // Generate 10 random numbers and store in sb. for (int i = 0; i < 10; i++) { sb.Append(rnd.Next().ToString("N5")); } Console.WriteLine("The original string:"); Console.WriteLine(sb.ToString()); // Decrease each number by one. for (int ctr = 0; ctr < sb.Length; ctr++) { if (Char.GetUnicodeCategory(sb[ctr]) == System.Globalization.UnicodeCategory.DecimalDigitNumber) { int number = (int)Char.GetNumericValue(sb[ctr]); number--; if (number < 0) number = 9; sb[ctr] = number.ToString()[0]; } } Console.WriteLine("\nThe new string:"); Console.WriteLine(sb.ToString());
使用 StringReader
分析大量的文本,并在处理数据时尽量减less内存占用。 查看下一个示例,其中StringReader上的ReadLine方法只是扫描从当前位置开始的下一个换行符,然后根据字段string返回一个sbstring。
using (StringReader sr = new StringReader("input.txt")) { // Loop over the lines in the string or txt file. int count = 0; string line; while((line = sr.ReadLine()) != null) { count++; Console.WriteLine("Line {0}: {1}", count, line); } }