Bootstrap

C#字符串--String

1. 概述

在 C# 中,string 是一个引用类型,用于表示文本数据。字符串是由 Unicode 字符组成的不可变序列。这意味着一旦创建了一个字符串对象,其内容就不能被改变。

2. 特性

不可变性:字符串对象一旦创建,其内容不能被改变。任何对字符串的修改操作都会返回一个新的字符串对象,而不会修改原始字符串。
引用类型:虽然字符串通常像值类型一样使用,但它实际上是引用类型。这意味着字符串变量实际上存储的是字符串对象的引用。
空字符串:string.Empty 表示一个空字符串,而不是 null。
字符串池:C# 使用字符串池来优化内存使用。相同的字符串字面量会共享同一个内存位置。
索引访问:可以通过索引访问字符串中的单个字符。
字符串方法:string 类提供了丰富的静态和实例方法,用于字符串操作,如连接、分割、替换、格式化等。

3.常用功能及示例

1. 字符串连接

string str1 = "Hello";
string str2 = "World";
string result1 = str1 + " " + str2;
Console.WriteLine(result1); // 输出: Hello World

string result2 = $"{str1} {str2}";//建议使用干方式连接字符
Console.WriteLine(result2); // 输出: Hello World

2. 字符串长度

string str = "Hello";
int length = str.Length;
Console.WriteLine(length); // 输出: 5

3. 字符串比较

string str1 = "Hello";
string str2 = "hello";
bool isEqual = string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine(isEqual); // 输出: True

4. 字符串查找

string str = "Hello, World!";
int index = str.IndexOf("World");
Console.WriteLine(index); // 输出: 7

5. 字符串替换

string str = "Hello, World!";
string result = str.Replace("World", "C#");
Console.WriteLine(result); // 输出: Hello, C#!

6. 字符串分割

string str = "Hello,World,C#";
string[] parts = str.Split(',');
foreach (var part in parts)
{
    Console.WriteLine(part); // 输出: Hello, World, C#
}

7. 字符串截取

string str = "Hello, World!";
string result = str.Substring(7, 5);
Console.WriteLine(result); // 输出: World

8. 字符串转小写

string str = "HELLO, WORLD!";
string lowerCase = str.ToLower();
Console.WriteLine(lowerCase); // 输出: hello, world!

9. 字符串转大写

string str = "hello, world!";
string upperCase = str.ToUpper();
Console.WriteLine(upperCase); // 输出: HELLO, WORLD!

10. 字符串修剪

string str = "   Hello, World!   ";
string trimmed = str.Trim();
Console.WriteLine(trimmed); // 输出: Hello, World!

11. 字符串格式化

string name = "Alice";
int age = 30;
string result = string.Format("Name: {0}, Age: {1}", name, age);
Console.WriteLine(result); // 输出: Name: Alice, Age: 30

12. 字符串拼接

List<string> words = new List<string> { "Hello", "World", "C#" };
string result = string.Join(", ", words);
Console.WriteLine(result); // 输出: Hello, World, C#

13. 字符串是否为空或空字符串

string str1 = "";
string str2 = null;
bool isNullOrEmpty1 = string.IsNullOrEmpty(str1);
bool isNullOrEmpty2 = string.IsNullOrEmpty(str2);
Console.WriteLine(isNullOrEmpty1); // 输出: True
Console.IsNullOrWhiteSpace(isNullOrEmpty2); // 输出: True

14. 字符串是否为空或空白字符串

string str1 = "   ";
string str2 = null;
bool isNullOrWhiteSpace1 = string.IsNullOrWhiteSpace(str1);
bool isNullOrWhiteSpace2 = string.IsNullOrWhiteSpace(str2);
Console.WriteLine(isNullOrWhiteSpace1); // 输出: True
Console.WriteLine(isNullOrWhiteSpace2); // 输出: True

15. 字符串编码转换

string str = "Hello, 世界!";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
string result = System.Text.Encoding.UTF8.GetString(bytes);
Console.WriteLine(result); // 输出: Hello, 世界!

16. 字符串反转

string str = "Hello";
char[] charArray = str.ToCharArray();
Array.Reverse(charArray);
string result = new string(charArray);
Console.WriteLine(result); // 输出: olleH

17. 字符串插入

string str = "HelloWorld";
string result = str.Insert(5, ", ");
Console.WriteLine(result); // 输出: Hello, World

18. 字符串删除

string str = "Hello, World!";
string result = str.Remove(5, 2);
Console.WriteLine(result); // 输出: Hello World!

19. 字符串复制

string str = "Hello";
string copy = string.Copy(str);
Console.WriteLine(copy); // 输出: Hello

20. 字符串哈希码

string str = "Hello";
int hashCode = str.GetHashCode();
Console.WriteLine(hashCode); // 输出: 哈希码值

21. 字符串的性能优化

使用 StringBuilder 来构建和修改字符串,以提高性能。

using System.Text;

StringBuilder sb = new StringBuilder();
sb.Append("Hello, ");
sb.Append("World!");
string result = sb.ToString();
Console.WriteLine(result); // 输出: Hello, World!

4.稍微复杂一点的功能及示例

1. 正则表达式匹配

using System.Text.RegularExpressions;

string input = "The quick brown fox jumps over the lazy dog.";
string pattern = @"\b\w{4}\b"; // 匹配四个字母的单词
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
    Console.WriteLine(match.Value); // 输出: quick, over, lazy
}

2. 正则表达式替换

using System.Text.RegularExpressions;

string input = "The quick brown fox jumps over the lazy dog.";
string pattern = @"\b\w{4}\b"; // 匹配四个字母的单词
string result = Regex.Replace(input, pattern, "****");
Console.WriteLine(result); // 输出: The **** brown fox jumps **** the **** dog.

3. 字符串解析

string input = "Name: Alice, Age: 30, City: New York";
string[] parts = input.Split(new[] { ',', ':' }, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> data = new Dictionary<string, string>();
for (int i = 0; i < parts.Length; i += 2)
{
    string key = parts[i].Trim();
    string value = parts[i + 1].Trim();
    data[key] = value;
}
foreach (var item in data)
{
    Console.WriteLine($"{item.Key}: {item.Value}"); // 输出: Name: Alice, Age: 30, City: New York
}

4. 字符串格式化日期

using System;

DateTime date = DateTime.Now;
string formattedDate = date.ToString("yyyy-MM-dd HH:mm:ss");
Console.WriteLine(formattedDate); // 输出: 当前日期和时间的格式化字符串

5. 字符串加密和解密

using System.Security.Cryptography;
using System.Text;

public static string Encrypt(string plainText, string key)
{
    using (Aes aesAlg = Aes.Create())
    {
        byte[] keyBytes = Encoding.UTF8.GetBytes(key);
        byte[] iv = new byte[16]; // 初始化向量
        aesAlg.Key = keyBytes;
        aesAlg.IV = iv;

        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter sw = new StreamWriter(cs))
                {
                    sw.Write(plainText);
                }
                return Convert.ToBase64String(ms.ToArray());
            }
        }
    }
}

public static string Decrypt(string cipherText, string key)
{
    using (Aes aesAlg = Aes.Create())
    {
        byte[] keyBytes = Encoding.UTF8.GetBytes(key);
        byte[] iv = new byte[16]; // 初始化向量
        aesAlg.Key = keyBytes;
        aesAlg.IV = iv;

        ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

        byte[] cipherBytes = Convert.FromBase64String(cipherText);

        using (MemoryStream ms = new MemoryStream(cipherBytes))
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader sr = new StreamReader(cs))
                {
                    return sr.ReadToEnd();
                }
            }
        }
    }
}

string plainText = "Hello, World!";
string key = "ThisIsASecretKey123";
string encryptedText = Encrypt(plainText, key);
string decryptedText = Decrypt(encryptedText, key);

Console.WriteLine($"Original: {plainText}");
Console.WriteLine($"Encrypted: {encryptedText}");
Console.WriteLine($"Decrypted: {decryptedText}");

6. 多线程处理字符串

using System.Threading.Tasks;

string input = "The quick brown fox jumps over the lazy dog.";
string[] words = input.Split(' ');

Parallel.ForEach(words, word =>
{
    Console.WriteLine(word);
});

7. 字符串排序

string input = "The quick brown fox jumps over the lazy dog.";
string[] words = input.Split(' ');
Array.Sort(words);
foreach (var word in words)
{
    Console.WriteLine(word); // 输出: The, brown, dog., fox, jumps, lazy, over, quick, the
}

8. 字符串去重

string input = "The quick brown fox jumps over the lazy dog.";
string[] words = input.Split(' ');
var uniqueWords = new HashSet<string>(words);
foreach (var word in uniqueWords)
{
    Console.WriteLine(word); // 输出: The, quick, brown, fox, jumps, over, the, lazy, dog.
}

9. 字符串分组

string input = "The quick brown fox jumps over the lazy dog.";
string[] words = input.Split(' ');
var groupedWords = words.GroupBy(word => word[0]);
foreach (var group in groupedWords)
{
    Console.WriteLine($"Group: {group.Key}");
    foreach (var word in group)
    {
        Console.WriteLine(word);
    }
}

10. 字符串压缩和解压

using System.IO.Compression;
using System.IO;

public static string Compress(string text)
{
    byte[] buffer = Encoding.UTF8.GetBytes(text);
    using (var memoryStream = new MemoryStream())
    {
        using (var gzipStream = new GZipStream(memoryStream, CompressionLevel.Optimal))
        {
            gzipStream.Write(buffer, 0, buffer.Length);
        }
        return Convert.ToBase64String(memoryStream.ToArray());
    }
}

public static string Decompress(string compressedText)
{
    byte[] buffer = Convert.FromBase64String(compressedText);
    using (var memoryStream = new MemoryStream(buffer))
    {
        using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
        {
            using (var streamReader = new StreamReader(gzipStream, Encoding.UTF8))
            {
                return streamReader.ReadToEnd();
            }
        }
    }
}

string originalText = "The quick brown fox jumps over the lazy dog.";
string compressedText = Compress(originalText);
string decompressedText = Decompress(compressedText);

Console.WriteLine($"Original: {originalText}");
Console.WriteLine($"Compressed: {compressedText}");
Console.WriteLine($"Decompressed: {decompressedText}");

5.使用注意事项

1. 不可变性

• 性能影响:频繁修改字符串会导致大量临时对象的创建,增加内存开销和垃圾回收的压力。对于频繁修改的字符串,建议使用 StringBuilder。
• 示例:

string s = "Hello";
s += " World"; // 实际上创建了新的字符串对象

2. 字符串池

• 字符串池:编译器会将相同的字符串字面量放入字符串池中,以节省内存。
• 示例:

string s1 = "Hello";
string s2 = "Hello";
bool areSame = object.ReferenceEquals(s1, s2); // true

3. 空字符串与 null

• 空字符串:string.Empty 表示一个空字符串,长度为 0。
• null:表示没有引用任何字符串对象。
• 示例:

string empty = string.Empty;
string nullString = null;

bool isEmpty = string.IsNullOrEmpty(empty); // true
bool isNull = string.IsNullOrEmpty(nullString); // true

4. 字符串比较

• 区分大小写:默认情况下,字符串比较是区分大小写的。
• 不区分大小写:使用 StringComparison.OrdinalIgnoreCase 或 StringComparer.OrdinalIgnoreCase 进行不区分大小写的比较。
• 示例:

string s1 = "Hello";
string s2 = "hello";

bool areEqual = string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase); // true
  1. 字符串格式化
    • string.Format:用于格式化字符串。
    • 插值字符串:使用 $ 符号进行字符串插值。
    • 示例:
string name = "Alice";
int age = 30;

string formatted = string.Format("Name: {0}, Age: {1}", name, age);
string interpolated = $"Name: {name}, Age: {age}";

6. 字符串分割和连接

• Split:将字符串分割成多个子字符串。
• Join:将多个子字符串连接成一个字符串。
• 示例:

string input = "Hello,World,C#";
string[] parts = input.Split(',');

string joined = string.Join(", ", parts);

7. 字符串编码

• 编码转换:使用 System.Text.Encoding 类进行字符串的编码和解码。
• 示例:

string str = "Hello, 世界!";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(str);
string result = System.Text.Encoding.UTF8.GetString(bytes);

8. 异常处理

• 空指针异常:访问 null 字符串的属性或方法会引发 NullReferenceException。
• 示例:

string nullString = null;
try
{
    int length = nullString.Length; // 抛出 NullReferenceException
}
catch (NullReferenceException ex)
{
    Console.WriteLine("字符串为空");
}

9. 性能优化

• StringBuilder:对于频繁修改的字符串,使用 StringBuilder 可以显著提高性能。
• 示例:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
    sb.Append(i.ToString());
}
string result = sb.ToString();

10. 字符串正则表达式

• 预编译正则表达式:对于频繁使用的正则表达式,可以预编译以提高性能。
• 示例:

using System.Text.RegularExpressions;

Regex regex = new Regex(@"\b\w{4}\b", RegexOptions.Compiled);
string input = "The quick brown fox jumps over the lazy dog.";
MatchCollection matches = regex.Matches(input);
foreach (Match match in matches)
{
    Console.WriteLine(match.Value); // 输出: quick, over, lazy
}

11. 字符串资源管理

• 国际化和本地化:使用资源文件(.resx)来管理不同语言的字符串,以便支持多语言应用。
• 示例:

using System.Resources;
using System.Globalization;

ResourceManager rm = new ResourceManager("MyApp.Resources", Assembly.GetExecutingAssembly());
string greeting = rm.GetString("Greeting", new CultureInfo("fr-FR"));
Console.WriteLine(greeting); // 输出: Bonjour

12. 字符串安全

• 防止注入攻击:在处理用户输入时,特别是用于 SQL 查询或命令行参数时,使用参数化查询或转义特殊字符,以防止 SQL 注入或命令注入。
• 示例:

using System.Data.SqlClient;

string userInput = "userInput";
string query = "SELECT * FROM Users WHERE Username = @Username";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    SqlCommand command = new SqlCommand(query, connection);
    command.Parameters.AddWithValue("@Username", userInput);
    // 执行查询
}

13. 字符串比较

• 文化敏感性:在进行字符串比较时,考虑文化差异,使用适当的 StringComparison 枚举值。
• 示例:

string s1 = "strasse";
string s2 = "straße";

bool areEqual = string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase); // false
bool areEqualWithCulture = string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase | StringComparison.CultureInfoIgnoreCase); // true

14. 字符串长度

• 最大长度:C# 中的字符串最大长度受系统内存限制,但通常可以达到 2GB。
• 检查长度:在处理长字符串时,确保检查字符串长度,避免超出预期。
• 示例:

string longString = new string('a', int.MaxValue - 100);
if (longString.Length > 1000000)
{
    Console.WriteLine("字符串过长");
}

15. 字符串格式化

• 自定义格式化:使用自定义格式化字符串来控制输出格式。
• 示例:

double number = 123456.789;
string formatted = number.ToString("N2"); // 输出: 123,456.79

16. 字符串编码

• 多字节字符:处理多字节字符(如中文、日文等)时,确保使用正确的编码方式。
• 示例:

string chineseString = "你好,世界!";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(chineseString);
string result = System.Text.Encoding.UTF8.GetString(bytes);

17. 字符串缓存

• 缓存常用字符串:对于频繁使用的字符串,可以考虑缓存以提高性能。
• 示例:

private static readonly string CachedString = "Frequently used string";

public void UseCachedString()
{
    Console.WriteLine(CachedString);
}

18. 字符串搜索

• 高效搜索:使用 IndexOf 方法进行字符串搜索,注意区分大小写和文化敏感性。
• 示例:

string input = "Hello, World!";
int index = input.IndexOf("World", StringComparison.OrdinalIgnoreCase);
Console.WriteLine(index); // 输出: 7

6.实践总结(实在写不完根本,写不完)

1. 使用 StringBuilder 进行频繁的字符串拼接。
2. 处理用户输入时注意安全问题,防止注入攻击。
3. 使用资源文件进行国际化和本地化。
4. 考虑文化差异进行字符串比较。
5. 检查字符串长度,避免超出预期。
6. 使用自定义格式化字符串控制输出格式。
7. 处理多字节字符时使用正确的编码方式。
8. 缓存常用字符串以提高性能。
9. 使用 IndexOf 方法进行高效的字符串搜索。
10. 预编译正则表达式以提高性能。

;