C# 课程 - 第2课:在 C# 中处理文本:char, string, StringBuilder, SecureString






4.77/5 (55投票s)
这是我系列讲座的第二讲。它与处理文本数据相关,重点介绍了 char、string、SrtingBuilder 和 SecureString 等类型。
全部课程集
- C#Lectures - 第 1 讲:
原始类型 - C# 课程 - 第2课:在 C# 中处理文本:char, string, StringBuilder, SecureString
- C# 课程 - 第3课:C# 类型设计。你必须知道的类基础知识
- C# 课程 - 第4课:面向对象编程基础:C# 示例中的抽象、封装、继承、多态
- C# 课程 - 第5课:C# 示例中的事件、委托、委托链
- C# 课程 - 第6课:C# 中的特性和自定义特性
- C# 讲座 - 第 7 讲:
反射( 通过 C# 示例) - C# 课程 - 第8课:灾难恢复。C# 示例中的异常和错误处理
- C# 讲座 - 第 9 讲:
Lambda 表达式 - C# 课程 - 第10课:LINQ 简介,LINQ to Objects 第一部分
- C# 讲座 - 第 11 讲:LINQ to 0bjects 第二部分:非延迟运算符
引言
在本文中,我想重点介绍 C# 中的文本处理。我将介绍 C# 中表示文本数据的最常见方式,并研究用于处理文本数据的类型。
char
存储文本(甚至不是文本,而是一个符号数据)最简单的方法是使用 char 类型。Char 是原始类型(您可以在我的文章 这里 中了解更多关于原始类型的信息)。Char 变量可以保存一个符号。实际上,char 是一个 16 位数值,编译器将其转换为符号字面量。
//declare char value and assign to it value of character literal char cVar = 's'; Console.WriteLine("Code of character s = " + (int)cVar);//prints 115 //declare char value and assign to it value converted from integer char cVar1 = (char)115; //declare char value and assign to it value converted from hexadecimal sequence char cVar2 = '\x0073'; //declare char value and assign to it value converted from unicode sequence char cVar3 = '\u0073'; //in all cases the character literal is s Console.WriteLine("cVar=" + cVar + " cVar1=" + cVar1 + " cVar2=" + cVar2 + " cVar3=" + cVar3 +"\n");
所有 char 符号都分为几类,例如小写字母、大写字母、货币符号、标点符号、数学符号以及其他几类。要获取符号类别,char 类型具有静态方法 GetUnicodeCategory。以下是其用法及其结果的示例:
Console.WriteLine(char.GetUnicodeCategory('c')); //lower case letter Console.WriteLine(char.GetUnicodeCategory('C')); //upper case letter Console.WriteLine(char.GetUnicodeCategory('$')); //currency symbol Console.WriteLine(char.GetUnicodeCategory(',')); //punctuation symbol Console.WriteLine(char.GetUnicodeCategory('+') + "\n"); //math symbol
每个 Unicode 类别都有自己的两个字母代码。您可以在 这里 查看代码列表。您还可以在 unicode.org 上找到所有字符的列表,作为 txt 文件。在此文件中,第三列是类别 ID。有一组静态方法可以处理 char 并了解其与某个类别的关系。它们调用 GetUnicodeCategory 并返回 true 或 false。这些方法包括 IsDigit、IsLetter、IsWhiteSpace、IsUpper、IsLower、IsPunctuation、IsLetterOrDigit、IsControl、IsNumber 等。这些方法接收一个字符或一个字符串以及该字符串中特定字符的索引。
除了获取 char 类别,我们还有 char 类型重要且方便的静态函数用于转换字符。Functions ToUpperInvariant 和 ToLowerInvariant 在不考虑区域性标准(区域性)的情况下更改符号的大小写。要更改与调用线程关联的区域性的注册,您应该使用 ToUpper 和 ToLower 函数。如果输入符号已处于输出注册状态,则输出与输入相同。如果您想将特定的区域性信息放入转换函数,您需要将 CultureInfo 类型的对象作为输入放入这些函数。以下代码演示了上述函数的用法及其结果:
Console.WriteLine(char.ToUpperInvariant('s')); //gives S Console.WriteLine(char.ToLowerInvariant('P')); //gives p Console.WriteLine(char.ToLowerInvariant('p')); //gives p Console.WriteLine(char.ToLowerInvariant('Ф')); //gives ф Console.WriteLine(char.ToLower('Ф')); //gives ф
char 类型还有一些您应该知道并根据需要使用更重要的静态函数。GetNumericalValue 将输入字符转换为双精度浮点数。您可以使用此函数来了解特定的语言字符是否可以转换为十进制数字。
Equals 检查两个输入字符是否等效。
以下是它们用法和结果的示例:
Console.WriteLine(char.GetNumericValue('s')); //gives -1 Console.WriteLine(char.GetNumericValue('4')); //gives 4
Console.WriteLine(char.Equals('s','s')); //gives true Console.WriteLine(char.Equals('s', 'p')); //gives false Console.WriteLine(char.Equals('s', 'S') + "\n"); //gives false
您可以使用 char 数组进行文本操作。这是处理复杂文本的有效方法,它为开发人员提供了极大的灵活性。这并不是一种非常方便的方法,因为您需要自己控制一切并创建自己的文本处理算法。无需自己动手,C# 提供了可以帮助您提高效率的类型,并将 char 数组的处理封装到名为 string 的类型中,但您应该知道 char 数组是表示文本数据的广泛使用的方式。API 的集合以 char 数组的形式返回文本数据,您不应为此感到恐惧,而应知道如何处理它。
字符串
String 是 C# 中处理文本数据最知名、最常用的类型。String 是原始类型,它不是从 ValueType 派生的,而是直接从 Object 派生的。这意味着 string 始终存储在堆中,而从不在栈中。您应该知道的另一件事是,string 是有序且常量(不可更改)的符号集合。由于字符串是常量,因此在处理字符串时无需同步线程。除此之外,如果系统中存在两个相等的字符串,CLR 会知道这一点,并且两个指针都指向同一个位置。这意味着在 .NET 中处理字符串是经过优化且快速的。为了实现这种生产力,Microsoft 封锁了 string 类并将其设为 sealed,您不能从中派生。
声明
由于 string 是 C# 中的原始类型,因此它有更简洁的方式来声明 string 实例。您可以使用简化的方式声明它:string s = "String text"
您还可以使用 7 个重载的 string 构造函数来实例化 string。请注意,这些构造函数中没有任何一个接受字符串字面量作为输入。以下代码将无法成功编译:
string s = new string("dsfds");
您还可以通过调用 string.Copy 方法来实例化新的 string。它会创建输入字符串的副本并用它初始化输出字符串。String Clone 方法返回对调用它的同一个字符串对象的引用。
以下代码演示了不同的字符串声明和初始化方法:
//DEFINITION //simplest way of string instantiation string s = "This is the string"; //following definitions are equal s = @"C:\Windows\Sysem32\notepad.exe"; string s1 = "C:\\Windows\\Sysem32\\notepad.exe"; //alternative ways of instantiation by char array and char pointer char[] charArray = {'s','d','s','d','s','a'}; s1 = new string(charArray); Console.WriteLine(s1); string s2 = "dfdefsd"; unsafe { fixed (char* pChar = s2) { string s3 = new string(pChar); Console.WriteLine(s3); } } string s4 = string.Copy(s1);//instantiates s7 with s1 content Console.WriteLine(s4); //true s4 = (string)s1.Clone();//returns reference to s1 object Console.WriteLine(Object.ReferenceEquals(s4, s1)); //true s2 = s4.ToString();//returns reference to s4 object Console.WriteLine(Object.ReferenceEquals(s2, s1)); //true
由反斜杠 (\) 后跟一个字母或一组数字组成的字符组合称为“转义序列”。要在字符常量中表示换行符、单引号或某些其他字符,必须使用转义序列。(您可以在 这里 阅读更多关于它的信息)。在 C# 中,有一种声明字符串的方法,其中 "" 之间的所有符号都被视为字符串的一部分。这称为逐字字符串。要声明逐字字符串,您需要在字符串常量前使用 @ 符号。以下声明将产生相同的结果:
string s = @"C:\Windows\Sysem32\notepad.exe";
string s1 = "C:\\Windows\\Sysem32\\notepad.exe";
您可以对字符串执行一组操作。其中一些是 string 类型的静态成员,有些是通过运算符和其他类型完成的。
驻留(Interning)
如果您的应用程序使用大量字符串,并且这些字符串有可能重复出现,那么 .NET 会为您提供一个非常棒的机制来处理它。CLR 支持一种称为字符串驻留的机制。这是什么意思?当创建应用程序域时,CLR 会创建一个内部哈希表,其中字符串字面量作为键,值为字符串对象的引用。要使用此哈希表,您需要使用两个方法:Intern 和 IsInterned。通过调用 Intern,您会在哈希表中查找字符串,如果存在,您将收到保存它的字符串对象的引用,否则,会在哈希表中创建一个字符串的新副本并返回其引用。一旦字符串对象的引用不再被应用程序持有,垃圾回收器将清理该对象引用的文本数据。在驻留的情况下,这种情况不会发生。哈希表中的字符串在应用程序域加载之前一直保存在内存中。这意味着如果您处理重复的文本数据,它会非常快。
//INTERTING Console.WriteLine("--INTERNING"); s = string.Intern(s); Console.WriteLine("Is interned: " + string.IsInterned(s));//returns the string if it is there Console.WriteLine("Is interned: " + string.IsInterned(s1));//returns empty string string s5 = "Hello"; string s6 = new StringBuilder().Append("He").Append("llo").ToString(); Console.WriteLine(Object.ReferenceEquals(s5, s6)); //false s5 = string.Intern(s5); s6 = string.Intern(s6); Console.WriteLine(Object.ReferenceEquals(s5, s6)); //true
串联
让我们回顾一下您可以对字符串执行的第一个操作,即连接。
- 您可以使用“+”运算符来实现这一点。正如您所记得的,string 是字符的常量不可更改的集合,每次连接的结果都是在内存中完全重新分配。这就是为什么使用“+”运算符进行连接最好用于字面字符串。在这种情况下,连接在编译时完成,最终字符串会构建到您的模块的元数据中。对于变量使用“+”运算符是不好的,因为每次连接都会在内存中创建一个新字符串,这从应用程序使用的资源的角度来看是不好的。
- 您还可以使用静态类型 string string.Concat 方法来连接字符串。此方法非常方便地与容器配合使用,以连接它们的所有成员作为字符串。Concat 有许多重载,在手动实现连接之前,我建议检查其中一个是否适用于您的名称。
- 您可以使用 Join 方法连接输入数组或集合的对象,并在它们之间放置特定的分隔符。有几个重载,在使用此函数之前,您应该检查正确的重载。
以下是上面提到的不同连接方式的示例:
//CONCATENATION Console.WriteLine("--CONCATENATION"); //string concatenation using + operator done at literal strings //this is good we have the result added to module metadata while //compilation time s = "String1 " + "String2 "; Console.WriteLine(s);//prints "String1 String2 " //using this way of concatenation we will have the operation itself //done at runtime and it creates additional strings in memory s1 = "String3 "; s = s + s1; Console.WriteLine(s);//prints "String1 String2 String3" s = string.Concat("test1", " test2", " test3"); Console.WriteLine(s);//prints "test1 test2 test3" List<int> iList = new List<int>(); for(int i = 0; i< 10; i++) { iList.Add(i); } s = string.Concat(iList); Console.WriteLine(s);//prints "0123456789" //using Join we may group elements of array string[] array = { "one", "two", "three"}; s = string.Join("||", array); Console.WriteLine(s);//prints "one||two||three"
比较
有几种方法可以进行字符串比较。
- Compare 和 CompareTo - 这些函数可以根据字母顺序中的排序位置比较两个字符串对象或指定字符串对象的两个子字符串。通过向 Compare 函数传递不同的参数,您可以应用不同的规则。
- Equals - 确定当前实例和另一个实例是否具有相同的值。
比较字符串时,可以将 CultureInfo 结构传递给比较函数。通过传递区域性,您告诉编译器在比较时应用哪个区域性的词汇规则。这是一个单独的主题,我建议您阅读 Jeffre's Richter 的书《CLR via C#》有关此内容。在关于文本处理的部分,他完美地描述了这一点,在我看来,希望以不同语言比较字符串的开发人员必须熟悉此比较部分。以下代码演示了一些比较函数的示例:
//COMPARISION Console.WriteLine("--COMPARISION"); s = "String"; s1 = "String"; //the result will be 0, it means that first string is in the same sort position as //second in alphabetical sort order Console.WriteLine(string.Compare(s,s1)); Console.WriteLine(s.Equals(s1));//returns true; s = "A String"; s1 = "B String"; Console.WriteLine(string.Compare(s, s1).ToString() + s.CompareTo(s1).ToString());//returns -1 Console.WriteLine(s.Equals(s1));//returns false; s = "C String"; Console.WriteLine(string.Compare(s, s1).ToString() + s.CompareTo(s1).ToString());//returns 1 s1 = "c string"; Console.WriteLine(string.Compare(s, s1, true).ToString());//returns 0 Console.WriteLine(s.CompareTo(s1).ToString());//returns -1 Console.WriteLine(s.Equals(s1,StringComparison.Ordinal));//returns false; Console.WriteLine(s.Equals(s1,StringComparison.OrdinalIgnoreCase));//returns true;
您可以在 这里 找到有关字符串比较的更多详细信息。
字符和子字符串
String 包含一组函数,用于搜索字符串中的子字符串、搜索指定字符等。以下是关于每个特定函数的更多信息:
- Contains - 如果字符串中存在子字符串,则返回 true。
- CopyTo - 将指定数量的字符从特定位置复制到输出数组中的特定位置。
- EndsWith - 如果特定字符串以输入字符串结尾,则返回 true。有几种类型基于输入区域性和比较选项。
- StartsWith - 如果特定字符串以输入字符串开头,则返回 true。有几种类型基于输入区域性和比较选项。
- IndexOf - 根据不同的输入参数返回特定字符或字符串的第一个索引。有 9 个重载,提供各种选项。
- IndexOfAny - 返回字符串中输入数组中任何字符的第一个索引。
- LastIndexOf - 根据不同的输入参数返回特定字符或字符串的最后一个索引。有 9 个重载,提供各种选项。
- LastIndexOfAny - 返回字符串中输入数组中任何字符的最后一个索引。
- Split - 根据输入的字符或字符串数组将字符串拆分为子字符串。对于输入 char 和输入 string 数组有几种重载。
- Substring - 返回一个新的字符串,该字符串是源字符串的子字符串。此子字符串包含从特定位置到末尾的所有字符,或特定长度的字符。
- Remove - 返回一个新的字符串,该字符串是通过从特定位置到末尾删除所有字符,或删除特定数量的字符而从源字符串创建的。
下面的代码演示了指定功能的用法:
//CHARACTERS AND SUBSTRINGS Console.WriteLine("--CHARACTERS AND SUBSTRINGS"); s = "string that contains substring"; s1 = "substring"; Console.WriteLine(s.Contains(s1));//prints true Console.WriteLine(s.Contains("asdfds"));//prints false char[] destination = new char[6]; s.CopyTo(0, destination, 0, 6);//copies word "string" to output char array Console.WriteLine(destination); //prints "string" Console.WriteLine(s.EndsWith("dsas")); //prints false Console.WriteLine(s.EndsWith("ring")); //prints true Console.WriteLine(s.StartsWith("dsas")); //prints false Console.WriteLine(s.StartsWith("str")); //prints true Console.WriteLine(s.IndexOf("that")); //prints 7 Console.WriteLine(s.IndexOf("rerwe")); //prints -1 Console.WriteLine(s.LastIndexOf("in")); //prints 27 Console.WriteLine(s.LastIndexOf("qqq")); //prints -1 char[] search_chars = { 'i' }; Console.WriteLine(s.IndexOfAny(search_chars)); //prints 3 Console.WriteLine(s.LastIndexOfAny(search_chars)); //prints 27 char[] search_chars1 = { 'q' }; Console.WriteLine(s.IndexOfAny(search_chars1)); //prints -1 Console.WriteLine(s.LastIndexOfAny(search_chars1)); //prints -1 char[] split_char = { ' ' }; string[] out_strings = s.Split(split_char); foreach (string splitted in out_strings) //prints all the words from s separately { Console.WriteLine(splitted); } string[] split_string = { "in" }; out_strings = s.Split(split_string,StringSplitOptions.None); foreach (string splitted in out_strings) //prints all the words from s separately but without "in" { Console.WriteLine(splitted); } s = "very important string"; Console.WriteLine(s.Substring(5)); //prints "important string" Console.WriteLine(s.Substring(5,9)); //prints "important" Console.WriteLine(s.Remove(5)); //prints "very " Console.WriteLine(s.Remove(5, 2)); //prints "very portant string"
格式化
String 支持一组有助于格式化字符串和更改其内容的函数。注意:string 是不可更改的,每次进行格式化时,结果都是一个新的字符串对象。您可以将以下函数用于字符串格式化:
- Format - 使用此函数,您可以构建包含输入对象字符串表示形式的新字符串。它用这些字符串表示替换格式元素。有多种重载。
- ToLower, ToLowerInvariant - 返回一个所有字符都为小写的字符串。
- ToUpper, ToUpperInvariant - 返回一个所有字符都为大写的字符串。
- Insert - 在特定位置将新字符串添加到当前字符串中,并返回表示此操作的新对象。
- PadRigth, PadLeft - 将字符串对齐到左侧或右侧,并在需要时用空格扩展它以达到输入大小。
- Trim, TrimStart, TrimEnd - 从字符串中删除输入字符集的所有出现,如果没有输入字符,则删除字符串开头和/或结尾的空格。
- Replace - 返回一个新的字符串,其中特定字符或字符串的所有实例都已被另一个字符或字符串替换。
下面的代码显示了格式化函数的示例:
//FORMATTING Console.WriteLine("--FORMATTING"); //string.format builds output string from different objects s = string.Format("First argument is: {0} and second argument is {1}", 10, 11);//creates new string Console.WriteLine(s);//prints "First argument is 10 and second argument is 11" s = string.Format("Persents are: {0:0.0%}", 0.75);//creates new string Console.WriteLine(s);//prints "Persents are: 75.0%" DateTime date = new DateTime(2015, 10, 5); TimeSpan time = new TimeSpan(15, 15, 30); decimal temp = 10.5m; s = String.Format("Temperature on {0:d} at {1,10} is {2} degrees", date, time, temp); Console.WriteLine(s);//prints "Temperature on 10/5/2015 at 15:15:30 is 10.5 degrees" s = "one plus"; s = s.Insert(8, " one"); Console.WriteLine(s);//prints "one plus one" //returns new string which is build from input string but all letters are upper case //using casting rules of current culture s = "some string"; s1 = s.ToUpper(); Console.WriteLine(s1);//prints "SOME STRING" //returns new string which is build from input string but all letters are lower case //using casting rules of current culture s = s1.ToLower();//prints "some string" Console.WriteLine(s); //returns new string which is build from input string but all letters are upper case //using casting rules of invariant culture s1 = s.ToUpperInvariant(); Console.WriteLine(s1);//prints "SOME STRING" //returns new string which is build from input string but all letters are lower case //using casting rules of invariant culture s = s1.ToLower(); Console.WriteLine(s);//prints "some string" s = " string with extra whitespaces "; char[] split_chars = { 's', 't', 'r', 'c', 'e', ' ' }; Console.WriteLine(s.Trim()); //returns "string with extra whitespaces" Console.WriteLine(s.TrimStart()); //returns "string with extra whitespaces " Console.WriteLine(s.TrimEnd()); //returns " string with extra whitespaces" Console.WriteLine(s.Trim(split_chars)); //returns "ing with extra whitespa" s = "some string"; //returns new string that is left aligned and adds whitespaces if needed to achieve expected length Console.WriteLine(s.PadLeft(15)); Console.WriteLine(s.Replace('s','S')); //prints "Some String" Console.WriteLine(s.Replace("str", "STR")); //prints "some STRing"
其他
您可以使用一组其他函数和属性来处理字符串。以下是它们的简要描述:
- Length - 此属性返回字符串的字符长度。
- ToCharArray - 将完整字符串或字符串部分的内容复制到 char 数组。
- IsNullOrEmpty - 如果字符串对象为 null 或空字符串,则返回 true。非常方便用于检查字符串。
- IsNullOrWhiteSpace - 如果字符串对象为 null 或空字符串,或仅包含空格,则返回 true。
以下代码演示了它们的用法:
//OTHER Console.WriteLine("--OTHER"); Console.WriteLine(s.Length);//prints 11 char[] chArray = s4.ToCharArray();//initializes char array by string content s = null; Console.WriteLine(string.IsNullOrEmpty(s)); //true Console.WriteLine(string.IsNullOrWhiteSpace(s)); //true s = " "; Console.WriteLine(string.IsNullOrEmpty(s)); //false Console.WriteLine(string.IsNullOrWhiteSpace(s)); //true s = "sss"; Console.WriteLine(string.IsNullOrEmpty(s)); //false Console.WriteLine(string.IsNullOrWhiteSpace(s)); //false
StringBuilder
StringBuilder 是一个类,其对象用于创建和更改字符串,而不必每次都创建新实例。我读过的书籍不建议将 StringBuilder 作为 string 的替代品,例如,将其作为参数传递给函数。在这种情况下,您仍应依赖 string。StringBuilder 专为字符串格式化和操作而设计。StringBuilder 内部有一个 char 数组,如果您需要更多空间来存储新的字符串数据,它会扩展数组大小,创建一个新数组并将数据复制到其中进行操作。这种灵活的方式使 StringBuilder 能够有效地使用内存,并且不像 String 那样在每次操作后创建新结构。一旦您完成了 StringBuilder 中的字符串数据操作,就可以通过调用 ToString 方法将其作为 string 获取。ToString 每次被调用时都会返回一个新字符串。
您可以通过几种可能的方式创建 StringBuilder 对象:
StringBuilder sb = new StringBuilder(); //default constructor sb = new StringBuilder(25); //constructor with suggested capacity sb = new StringBuilder("input string"); //constructor with string sb = new StringBuilder(25, 225); //constructor with suggested and maximum capacity sb = new StringBuilder("some string",20); //constructor with string and suggested capacity sb = new StringBuilder("some string", 0, 4, 20);//constructor with string where we take its part from index and for specific length plus suggested capacity Console.WriteLine(sb.ToString());//prints "some"
StringBuilder 具有以下重要的属性和方法:
属性
- Capacity - 设置或返回 StringBuilder 存储其数据的 char 数组的大小。StringBuilder 的默认容量是 16 个字符。一旦字符串数据超出当前容量,CLR 就会将当前容量加倍。
- MaxCapacity - 只读属性,返回 StringBuilder 对象可以存储的最大符号数。
- Length - 获取或设置当前 StringBuilder 对象的长度。
以下代码演示了 StringBuilder 的属性:
sb = new StringBuilder("some string", 0, 4, 20);//constructor with string where we take its part from index and for specific length plus suggested capacity
Console.WriteLine(sb.Capacity); //prints 20
Console.WriteLine(sb.MaxCapacity); //prints 2147483647 Console.WriteLine(sb.Length); //prints 4
方法
- Append - 将输入数据类型的字符串表示形式附加到 StringBuilder 对象持有的字符串数据。有 20 个重载,适用于不同的输入参数。
- AppendFormat - 追加即时格式化的字符串。此字符串包含一个或多个格式项,其字符串表示形式已添加到字符串中。您可以使用特定的格式提供程序来格式化每个格式项。有多种重载,您应根据您的要求使用。
- Clear - 清除 StringBuilder 实例中的所有字符。
- AppendLine - 将行终止符附加到当前的 StringBuilder 实例。还有一个带有输入字符串的重载,在我看来,这更方便。
- CopyTo - 将当前 StringBuilder 实例中的字符串段的一部分复制到输出 Char 数组。
- EnsureCapacity - 如果 StringBuilder 实例的当前容量大于输入值,则返回其当前容量,否则将其设置为输入值。
- Insert - 类似于 append 函数,具有一组重载,并将不同数据类型的字符串表示插入到 StrtingBuilder 的 char 数组中的特定字符位置。
- Remove - 从特定索引和指定长度移除特定范围或字符。
- Replace - 将特定字符或特定字符串的所有出现替换为新的字符或字符串。
- ToString - 返回特定 StringBuilder 实例中保存的 char 数组的全部或部分数据,作为字符串。
下面的代码演示了方法的用法:
sb = new StringBuilder(); sb.Append(1); sb.Append('s'); sb.Append(" some string data "); sb.Append(true); sb.Append('\t'); Object o = new Object(); sb.Append(o); sb.Append('\t'); sb.Append(123.435345); Console.WriteLine(sb.ToString());//prints "1s some string data True System.Object 123,435345" sb.Clear(); sb.AppendFormat("Appends first digit: {0} and second bool: {1}", 123, false); Console.WriteLine(sb.ToString());// ptints "Appends first digit: 123 and second bool: False" sb.Clear(); sb.Append("first line"); sb.AppendLine(); sb.Append("second line"); Console.WriteLine(sb.ToString());//prints two strings in separate lines sb.Clear(); sb.AppendLine("first line"); sb.Append("second line"); Console.WriteLine(sb.ToString());//output and results is equal as for example above char[] cArray = new char[5]; sb.CopyTo(0, cArray, 0, 5); Console.WriteLine(cArray);//prints "first" Console.WriteLine(sb.EnsureCapacity(5));//prints 64 that is current capacity of the string Console.WriteLine(sb.EnsureCapacity(105));//prints 105 that is current capacity of the string try { sb.EnsureCapacity(int.MaxValue);//raises OutOfMemoryException } catch (System.OutOfMemoryException) { Console.WriteLine("We catch exception because tried to create StringBuilder object that exceeds maximum size"); } sb.Clear(); sb.Insert(0, "first "); sb.Insert(6, "second "); sb.Insert(13, true); sb.Insert(17, " "); sb.Insert(18, 123.2435d); Console.WriteLine(sb.ToString());//prints "first second True 123,2435" try { sb.Insert(121, "");//raises ArgumentOutOfRangeException } catch (System.ArgumentOutOfRangeException) { Console.WriteLine("We catch exception because tried to insert to StringBuilder object for a position that exceeds array size"); } sb.Remove(18, 7); Console.WriteLine(sb.ToString());//prints "first second True 5" sb.Replace('5', '!'); Console.WriteLine(sb.ToString());//prints "first second True !" sb.Replace("fir", "FIR"); Console.WriteLine(sb.ToString());//prints "FIRst second True !"
正如您所见,String 类比 StringBuilder 功能强大得多,但当您可以使用时,应尝试使用 StringBuilder 类进行字符串格式化,而不是 String,因为它在资源利用方面更有效率。
SecureString
所有字符串都存储在堆中,并且您的应用程序中使用的任何字符串都有很大可能通过分析进程分配的内存来识别。通过分析应用程序的内存转储(其中存储了用户密码或任何其他秘密或私人信息)可以进行许多黑客攻击。此外,政府或安全组织对其内部运行的应用程序有严格的规定。为了解决所有这些问题,Microsoft 设计了一种特殊的字符串数据类型,它分配在特定的、编码的、非托管的内存区域中,该区域无法被垃圾回收器访问。此类型的名称是 System.Security.SecureString。SecureString 类型具有几个操作其文本数据的方法。当您调用这些方法时,字符串的一部分将被解码,并在操作后重新编码。这发生得非常快,并且数据被编码的时间非常短,从而保证了数据保护。SecureString 类实现了 Idisposable 接口。当应用程序不再需要此类的数据时,您可以调用 Dispose 方法或使用 using 运算符来删除存储在持有 SecureString 文本数据的特殊缓冲区中的文本数据。
列表
显示文本处理示例的应用程序的完整列表可作为附件提供。
来源
- Jeffrey Richter - CLR via C#
- Andrew Troelsen - Pro C# 5.0 and the .NET 4.5 Framework
- MSDN
- http://www.introprogramming.info/english-intro-csharp-book/read-online/chapter-13-strings-and-text-processing/
- http://www.c-sharpcorner.com/UploadFile/mahesh/WorkingWithStringsP111232005042550AM/WorkingWithStringsP1.aspx