字符、字符串和文本處理

1.1字符html

在.NET Framework中,字符都是用16位Unicode編碼(UTF-16)的(編譯時用UTF-16編碼成2進制存到硬盤,程序運行時再用utf-16解碼顯示代碼中的字符串,在內存中相應的字節流就是用UTF-16編碼過的),也就是說全部字符都是佔2個字節16位,這簡化了國際化應用程序的開發。Unicode字符集有不少種編碼方案,經常使用的有:git

UTF-16:全部字符被編碼成2個字節正則表達式

UTF-8:十進制小於128的字符被編碼成1個字節(可表示歐美地區使用的字符),128~2047的字符被編碼成2個字節(可表示歐洲和中東語言),大於2047的字符被編碼成3個字節(可表示東亞地區的語言)編程

UTF-32:全部字符都被編碼成4個字節windows

Unicode字符集還有個ASCII編碼方案,這種編碼只能將小於128的16位字符轉換成單字節,而其餘超過127的字符都會丟失。編程語言

GB2312等其餘字符集(這些字符集可能只有一種同名編碼方案)ide

針對Char的一個實例,能夠調用Char類型的靜態方法GetUnicodeCategory,這個方法返回的是System.Globalization.UnicodeCategory枚舉類型的一個值。這個值指出該字符是控制字符、貨幣符號、小寫字母、大寫字母、標點符號、數字符號 仍是其餘Unicode標準定義的符號。 其餘一些靜態方法如IsDigit、IsLetter、IsUpper、IsControl、IsSymol等都在內部調用了GetUnicodeCategory,並簡單返回true或false。注意,因此這些方法要麼獲取單個字符做爲參數,要麼獲取一個String以及目標字符在這個String中的索引做爲參數。性能

另外,能夠調用靜態方法ToLowerInvariant或者ToUpperInvariant以一種忽略語言文化的方式,將一個字符轉化爲小寫或大寫。若是調用ToLower和ToUpper方法,在轉換時要使用與線程相關的語言文化信息,語言文化信息是這兩個方法在內部查詢System.Threading.Thread類的靜態CurrentCulture屬性來得到的。還能夠向這些方法傳遞CultureInfo類的一個實例來具體指定一種語言文化。ToLower和ToUpper之因此須要語言文化信息,是由於字母的大小寫轉換是依賴於語言文化操做的。ui

可使用三種技術實現各類數值類型與Char實例的相互轉換,下面按照優先順序列出這些技術。編碼

 

*轉型(強制類型轉換)要將一個Char轉換成一個數值(如Int32),最簡單的方法是強制類型轉換。在三種技術中,這種技術效率最高,由於編譯器會生成IL(Intermediate Language中間語言)指令來執行轉換,沒必要調用任何方法。

*使用Convert類型 System.Convert類型提供了幾個靜態方法來實現Char和數值類型的相互轉換。這些方法都以checked方式來執行轉換,所以一旦發現轉換形成數據丟失,就會拋出一個OverflowException異常。

*使用IConvertible接口 Char類型和FCL中的全部數值類型都實現了IConvertible接口。該接口定義了像ToUInt16和ToChar這樣的方法。可是這種技術效率最差,由於在值類型上調用一個接口方法,要求對實例進行裝箱(Char和全部數值類型都是值類型)。若是某個類型不能轉換(好比Char轉換成Boolean),或者轉換形成數據的丟失,IConvertible的方法會拋出一個System.InvalidCastException異常。

如下代碼簡單演示如何使用這三種技術

 1             Char c;
 2             Int32 n;
 3 
 4             //使用C#強制轉換技術實現數字與字符的相互轉型
 5             c = (Char) 65;
 6             Console.WriteLine(c);       //顯示"A"
 7 
 8             n = (Int32) c;
 9             Console.WriteLine(n);       //顯示"65"
10 
11             c = unchecked((Char) (65536 + 65));
12             Console.WriteLine(c);       //顯示"A"
13 
14             //使用Convert實現數字與字符的相互轉換
15             c = Convert.ToChar(65);
16             Console.WriteLine(c);       //顯示"A"
17 
18             n = Convert.ToInt32(c);
19             Console.WriteLine(n);       //顯示"65"
20 
21             //演示Convert的範圍檢查
22             try
23             {
24                 c = Convert.ToChar(70000);  //對16位來講太大
25                 Console.WriteLine(c);   // 不執行
26             }
27             catch (OverflowException)
28             {
29                 
30                 Console.WriteLine("Can't 70000 to a char!");
31             }
32 
33             //使用IConvertible實現數字與字符的相互轉換
34             c = ((IConvertible) 65).ToChar(null);
35             Console.WriteLine(c);       //顯示"A"
36 
37             n = ((IConvertible) c).ToInt32(null);
38             Console.WriteLine(n);       //顯示"65"
View Code

1.2 System.String類型

1.2.1 構造字符串

一個String表明一個不可變的順序字符集。String類型直接派生自Object,因此它是一個引用類型。所以String對象老是存在於堆上,永遠不會跑到線程棧。許多編程語言都將String視爲一個基元類型----能夠再源代碼中直接表示文本常量字符串(string s="hi"); 編譯器將這些文本常量字符串放到模塊的元數據中,並在運行時加載和引用它們。

在C#中,不能使用new操做符從一個文本常量字符串構造一個String對象。

對於換行符、回車符和退格符這樣的特殊字符,C#採用的是C/C++開發人員熟悉的轉義機制:

1  // 包含回車符和換行符的字符串
2 string s="hi\r\nthere";
3 
4 //NewLine是System.Environment類型定義的一個屬性,NewLine屬性是依賴於平臺的,它在任何平臺上都能正確工做,建議使用這種方式
5 string s="hi"+Environment.NewLine+"there";

可使用C#的+操做符將幾個字符串鏈接成一個,以下所示:

對於以下由好幾個文本常量字符串組成的字符串:

string s="hi"+" "+"there";

//注意:編譯器會在編譯時鏈接它們,最終只會將一個字符串放到模塊的元數據中
對於以下由好幾個非文本常量字符串組成的字符串:
string s1="hi"; string s2="there"; string s=s1+s2; 

//注意:對非文本常量字符串使用+操做符,鏈接會在運行時進行。
若要在運行時將幾個字符串鏈接到一塊兒,應避免使用+操做符,由於它會在堆上建立多個字符串對象,而堆是須要回收的,從而影響性能。相反,應儘可能使用System.Text.StringBuilder類型
 

C#還提供了逐字字符串,一般用於指定文件或目錄的路徑,或與正則表達式配合使用。採起這種方式,引號之間的全部字符都會被視爲字符串的一部分:

1 //指定應用程序路徑
2 string file="C:\\windows\\System32\\Notepad.exe";
3 
4 //使用逐字字符串來指定應用程序路徑
5 string file=@"C:\windows\System32\Notepad.exe";

在字符串前添加@符號,使編譯器知道字符串是一個逐字字符串,這告訴編譯器將反斜槓視爲文本常量,而不是轉義符,使文件路徑在源代碼中更易讀。

1.2.2 字符串是不可變的

string對象最重要的一個事實就是,它是不可變的,也就是說字符串一經建立便不能更改,不能變長,變短或修改其中任何字符。

因此容許對一個字符串進行各類操做而不實質的改變字符串:

1 string s="hiworld"; if(s.ToUperInvariant().Substring(0,2).EndsWith("EXE"))
2 {
3     ...
4 }

在此,ToUperInvariant()返回一個新的字符串,它沒有修改s的字符,而後Substring(0,2)在ToUperInvariant()返回的新字符串的基礎上又返回一個新字符串。 ToUperInvariant和Substring建立的兩個臨時字符串不會由應用程序代碼長久的引用,垃圾回收器會在下次回收時回收它們的內存,若是執行大量的字符串操做,會在堆上建立大量的string對象,形成頻繁的垃圾回收,從而損害應用程序的性能,要想高效率地執行大量字符串操做,請用StringBuilder類。

使字符串不可變,還意味着在操縱或訪問一個字符串時不會發生線程同步問題。

相關文章
相關標籤/搜索