字符与字符串

C#中的char类型和string类型都用于处理Unicode标准字符。

char类型

char用于处理单个字符,字面量使用一对单引号定义,如'a'。其中,有一些特殊字符无法直接表示,可以使用\符号进行转义,常用的转义字符包括如下表。

转义字符
\0空字符(NULL)
\'单引号
\"双引号
\\\符号
\a报警
\b退格符
\f换页符
\n换行符
\r回车符
\t水平制表符
\v垂直制表符

下面的代码演示了字符及其编码之间的转换。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            char ch = 'A';
            int code = (int)ch;
            Console.WriteLine(ch);
            Console.WriteLine(code);
            Console.WriteLine((char)code);
        }
    }
}

代码执行结果如下图。

String类

C#中的string类型用于处理Unicode字符序列,即字符串类型,主要用于各种文本类数据。字符串的字面量使用一对双引号定义,如"abc123万事如意"。在字符串中,对于一些特殊字符同样需要转义,其方法与char类型中的转义方式相同。

实际上,string类型是System.String类的映射,这样,我们就可以使用String类中的一系列成员来操作字符串,下面来一些常用操作。

首先是Length属性,返回字符串中的字符数量,如下面的代码。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "abc123万事如意";
            Console.WriteLine(s.Length);
        }
    }
}

代码会返回10。

Contains()方法用于判断字符串中是否包含指定的内容,如下面的代码会显示True。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "abc123万事如意";
            Console.WriteLine(s.Contains("123"));
        }
    }
}

String类中常用的方法还包括:

StartsWith()和EndsWith()方法判断字符串是否是以指定的内容开始(前缀)和结束(后缀)。

IndexOf()和LastIndexOf()方法返回指定内容在字符串中第一次出现和最后一次出现的索引位置;请注意,索引值是从0开始,即第一个字符索引值为0、第二个字符索引值为1,以此类推。

Insert(index,s)方法,将s插入到index指定的索引位置,并返回新的字符串对象。

Replace(oldStr,newStr)方法,将字符串中的oldStr替换为newStr,并返回新的字符串对象。

Remove(index,length)方法,从index索引开始删除length指定数量的字符,如果不指定length参数,则删除从index索引开始的所有内容;方法会返回修改后的新字符串对象。

Substring(index,length)方法,载取从index开始的指定数量(length参数)的字符,如果不指定length参数,则截取从index开始的所有内容,方法返回载取的内容。

ToUpper()和ToLower()方法,将字符串中的字母转换为大写或小写,并返回修改后的字符串。

Trim()方法,删除字符串开始和结尾位置的空白字符,并返回修改后的字符串。此外,TrimStart()方法删除字符串开始位置的空白字符,TrimEnd()方法删除字符串结束位置的空白字符。

PadLeft()和PadRight()方法,将字符串格式化为等宽格式,并可以使用指定的字符填充空白位置,如下面的代码。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s1 = "abcd";
            string s2 = "efg";
            Console.WriteLine(s1.PadLeft(10,'*'));
            Console.WriteLine(s2.PadLeft(10, '*'));
            Console.WriteLine(s1.PadRight(10, '*'));
            Console.WriteLine(s2.PadRight(10, '*'));
        }
    }
}

代码执行结果如下图所示。

ToCharArray()方法将字符转换为字符数组,先来看一个简单的示例,后续课程还会有关于数组的详细讨论。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "abcdefg";
            char[] arr = s.ToCharArray();
            for (int i = 0; i < arr.Length; i++)
                Console.WriteLine(arr[i]);
        }
    }
}

代码执行结果如下图。

Split()方法可以使用指定的内容将字符中分割为string数组,如下面的代码。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "abcd,efg,hijk,lmn";
            string[] arr = s.Split(',');
            for (int i = 0; i < arr.Length; i++)
                Console.WriteLine(arr[i]);
        }
    }
}

代码执行结果如下图。

Join()方法定义为静态方法,可以将字符数组或字符串数组连接成一个字符串,并可以指定分隔内容,如下面的代码。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] strArr =
                 new string[] { "abcd","efg","hijk","lmn" };
            char[] chArr =
                 new char[] { 'a','b','c','d','e','f','g'};
            Console.WriteLine(string.Join("",strArr));
            Console.WriteLine(string.Join(",", chArr));
        }
    }
}

代码执行结果如下图。

逐字字符串

前面说过,在字符串中的特殊字符同样需要转义,如果需要书写大量的特殊字符,使用转义就很不方便,而且容易出错;此时,可以使用逐字字符串。

在字符串字面量的一对双引号前使用@符号就可以定义逐字字符串,而在逐字字符串中,只需要使用两个双引号表示双引号,其它字符都不需要转义,包括回车、制表、\等一系列特殊字符。下面的代码演示了逐字字符串的使用。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s1 = @"""c:\test.txt""";
            string s2 = @"abcdefghijklmn";
            Console.WriteLine(s1);
            Console.WriteLine(s2);
        }
    }
}

代码执行结果如下图。

格式化输出

将各种数据,以特定的格式组合成字符串是一种常用的功能,如Console.WriteLine()方法就大量的使用了格式化字符串显示测试结果。此外,String.Format()方法和稍后讨论的StringBuilder类中的AppendFormat()等方法也可以使用格式化字符串。

前面的示例,在Console.WriteLine()方法的第一个参数中,我们使用{0}、{1}等作为数据的占位符,然后从第二个参数开始依次写出它们,最终会组合一个完整的字符串显示出来。实际上,在占位符中还可以通过冒号(:)定义一些格式化符来确认数据的格式。常用的格式化字符包括:

  • C或c,显示货币格式。
  • D或d,显示整数,可指定数据显示宽度。
  • E或e,显示科学计数格式。
  • F或f,显示浮点数,可指定显示的小数位。
  • N或n,数字中使用分隔符。
  • P或p,显示为百分数格式。
  • X或x,显示十六进制数,其中,X大写时A到F显示大写,x小写时a到f显示小写。

下面的代码,我们来看一些数据的格式化输出结果。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            int x = 123;
            float y = 123.456f;
            Console.WriteLine("{0:c}", y);
            Console.WriteLine("{0:6d}", x);
            Console.WriteLine("{0:e}", y);
            Console.WriteLine("{0:f2}", y);
            Console.WriteLine("{0:X2}", x);
        }
    }
}

代码执行结果如下图。

StringBuilder类

String类用于处理不可变字符串,也就是说,当修改字符串内容时,就会生成的字符串对象,对于大量的字符中来说,String可能并不是那么高效。

前面的示例中,字符串进行连接时使用了+运算符,对于少量的连接操作,如五、六个以内的字符串连接,C#中做了优化,可以放心使用+运算符;但对于大量的字符串组合,特别是需要不同类型的数据组合成字符串时,应使用StringBuilder类(System.Text命名空间)。

StringBuilder类的常用构造方法有:

  • StringBuilder(string),使用参数的内容初始化对象内容。
  • StringBuilder(string,int),使用参数一的内容初始化对象,并使用参数二指定初始尺寸。
  • StringBuilder(int),使用参数指定初始尺寸。

常用的方法有:

  • Append()方法,一系列的重载版本,可以将各种类型的数据添加到StringBuilder对象中。
  • AppendFormat()方法,与Console.WriteLine()和String.Format()方法的参数设置相似,可以将各种数据格式化后添加到StringBuilder对象中。
  • AppendLine()方法,添加内容后会自动添加一个换行符,添加空行时可以使用没有参数的版本。
  • Insert()方法,在参数一指定的索引位置添加参数二指定的内容。
  • Replace()方法,将参数一的内容替换为参数二的内容。
  • Remove()方法,从参数一开始的索引位置删除参数二指定的字符数量。
  • Clear()方法,清除全部内容。
  • ToString()方法,返回对象中的字符串内容。

下面的代码演示了StringBuilder类的使用。

C#
using System;
using System.Text;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder sb = new StringBuilder(100);
            sb.Append("abc");
            sb.AppendFormat("1{0}{1}", 2, 3);
            sb.Insert(3,"d");
            Console.WriteLine(sb.ToString());
        }
    }
}

代码执行结果如下图。

获取MD5和SHA-1编码

MD5和SHA-1是基本的散列算法,下面,我们在CStr类中封装相应的方法,用于获取字符串散列编码后的字符串形式。

下面的代码包括MD5和SHA-1算法的转换方法。

C#
using System;
using System.Text;
using System.Security.Cryptography;
public static class CStr
{
    //将字符串转换为字节数组
    public static byte[] ToBytes(string s)
    {
        try { return Encoding.Default.GetBytes(s); }
        catch { return null; }
    }
    // 将字节内容还原成字符串
    public static string ToStr(byte[] bytes)
    {
        try { return Encoding.Default.GetString(bytes); }
        catch { return ""; }
    }
    //将字节数组内容以十六进制字符串显示
    public static string ToHexStr(byte[] bts)
    {
        try
        {
            StringBuilder result =
                new StringBuilder(bts.Length * 2);
            for (int i = 0; i < bts.Length; i++)
            {
                result.Append(bts[i].ToString("X2"));
            }
            return result.ToString();
        }
        catch { return ""; }
    }
    //MD5
    public static string ToMd5(this string s)
    {
        byte[] bytes = ToBytes(s);
        using (MD5CryptoServiceProvider csp =
            new MD5CryptoServiceProvider())
        {
            byte[] hash = csp.ComputeHash(bytes);
            return ToHexStr(hash);
        }
    }
    // SHA-1
    public static string ToSha1(this string s)
    {
        byte[] bytes = ToBytes(s);
        using (SHA1CryptoServiceProvider csp =
            new SHA1CryptoServiceProvider())
        {
            byte[] hash = csp.ComputeHash(bytes);
            return ToHexStr(hash);
        }
    }
}

代码,我们将ToMd5()和ToSha1()方法定义为String类的扩展方法。下面,我们在Main()方法中测试它们的使用。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "12345";
            Console.WriteLine(s.ToMd5());
            Console.WriteLine(s.ToSha1());
        }
    }
}

代码执行结果如下图。

获取GUID

GUID可以保存全球唯一标识,下面的代码,我们在CStr类中添加获取GUID的代码。

C#
using System;
public static class CStr
{
    public static string GuidStr
    {
        get
        {
            return Guid.NewGuid().ToString("N");
        }
    }
    // 其它代码
}

Guid结构定义在System命名空间,其中的NewGuid()方法获取一个新的Guid结构数据;使用ToString()方法可以返回GUID的字符串形式,请注意其中的参数,使用N时只获取字母和数字,不包括花括号和连字符等符号,其它的参数还有:

  • D,返回的字符串中包含连字符。
  • B,返回的字符串中包含连字符和花括号。
  • P,返回的字符串中包含连字符和圆括号。
  • X,返回十六进制值形式数据,并包含大括号。

下面的代码,我们使用CStr.GuidStr属性获取GUID,请注意,每次执行的结果都是不同的。

C#
using System;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(CStr.GuidStr);
        }
    }
}

下图中可以看到显示的GUID字符串的格式。

BASE64

BASE64编码与MD5等散列算法不同,BASE64编码是双向的,即,可以将内容生成为BASE64格式,也可以从BASE64中还原。

下面的代码,我们通过BASE64编码和解码复制一个文件。

C#
using System;
using System.IO;
namespace HelloProject
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = @"d:\test.txt";
            string base64 = Convert.ToBase64String(File.ReadAllBytes(path));
            Console.WriteLine(base64);
            byte[] bytes = Convert.FromBase64String(base64);
            File.WriteAllBytes(@"d:\test_bak.txt",bytes);
            Console.WriteLine("OK");
        }
    }
}

代码中复制的源文件是d:\test.txt,这是一个文本文件,其中的内容是abcdefg,需要我们手工准备这个文件;复制的目标文件是d:\test_bak.txt。执行代码后,如果显示为下图内容,则表示操作成功。

实际工作中,BASE64可以帮助我们方便地在客户端和服务器之间进行数据传输,如果只需要对字符串进行编码和解码,则需要在字符串类型和字节数组之间进行转换,如下面的两个方法。

C#
    //将字符串转换为字节数组
    public static byte[] ToBytes(string s)
    {
        try { return Encoding.Default.GetBytes(s); }
        catch { return null; }
    }
    // 将字节内容还原成字符串
    public static string ToStr(byte[] bytes)
    {
        try { return Encoding.Default.GetString(bytes); }
        catch { return ""; }
}

代码中的Encoding类定义在System.Text命名空间,请注意引用。

本站内容均为原创作品,转载请注明出处,本页面网址为:http://caohuayu.com/chy/article/Article.aspx?code=cc002009