是什么区别StringWriter
和StringBuilder
,当我应该使用一个或其他?
Answers:
我认为现有的答案都无法真正回答问题。这两个类之间的实际关系是适配器模式的一个示例。
StringWriter
Write...
通过转发到StringBuilder
存储在字段中的实例来实现其所有方法。这不仅是内部细节,因为StringWriter
有一个公共方法GetStringBuilder返回内部字符串构建器,还有一个构造函数,该构造函数允许您传入一个现存的StringBuilder
。
所以StringWriter
是允许适配器StringBuilder
用作目标的代码,希望与合作TextWriter
。就基本行为而言,显然它们之间没有任何选择……除非您可以衡量转发呼叫的开销,否则这种情况StringWriter
会稍慢一些,但这似乎不太可能。
那么为什么他们不直接制作StringBuilder
工具TextWriter
呢?这是一个灰色区域,因为乍一看,界面背后的意图不一定总是清楚的。
TextWriter
是非常接近的,接受的字符流的东西接口。但是它还有一个额外的缺点:称为Encoding的属性。这意味着这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);
产生标题:
<?xml version="1.0" encoding="utf-16"?>
如果使用File.WriteAllText将XML字符串写入文件怎么办?默认情况下,您将拥有一个utf-8
带有utf-16
标题的文件。
在这种情况下,使用StreamWriter
它并使用文件路径或a构造它会更安全FileStream
,或者如果您想检查数据,则使用aMemoryStream
并获得一个字节数组。所有这些组合将确保字节中的相同Encoding
值指导字节编码和标头生成StreamWriter
。
该Encoding
属性的目的是允许字符流生成器将有关编码的准确信息包括在字符流本身中(例如XML示例;其他示例包括电子邮件标头,等等)。
但是,通过引入StringWriter
,内容生成和编码之间的链接被打破了,因此,这种自动机制停止工作并可能容易出错。
但是,StringWriter
如果您小心一点,它是一个有用的适配器,也就是说,您了解内容生成代码不应依赖于Encoding
属性的无意义的值。但是这种警告通常与适配器模式有关。通常,这是一种技巧,可让您将方形但几乎是方形的圆钉插入圆孔中。
StringWriter
从派生TextWriter
,它允许各种类编写文本而无需关心其去向。对于StringWriter
,输出仅存入内存。如果要调用需要a的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();
没有做或死的东西,但还是有区别
AStringWriter
用于将文本写入一份文件memory和aStringBuilder
用于以节省内存的方式将字符串附加在一起。
StringBuilder
并StringReader
用于提高不同情况下的性能。
使用 StringBuilder
以提高字符串操作的性能,如串联,反复修改字符串。
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
在单独的行中解析大量文本,并在处理数据时最大程度地减少内存使用。请参见下一个示例,其中StringReader上的ReadLine方法仅扫描从当前位置开始的下一个换行符,然后根据字段字符串返回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);
}
}
StringWriter
不是StringReader
。