Share via


比較和排序特定文化特性的資料

不同的文化特性使用不同的排列項目的字母順序和慣例。例如,排序次序可以是區分大小寫或者不區分大小寫。排序次序可以根據注音或根據字元的外觀。在東亞語系中,排序次序可依筆劃和文字字根進行。排序次序同時也視語言和文化特性使用的字母基礎順序而定。例如,瑞典文的 Æ 字元的字母排列在 Z 之後。德文也使用這個字元,但它的排序次序類似 ae,其字母排列位於字母 A 之後。如果要支援特定文化特性和特性語言排序慣例,世界性的應用程式必須能夠根據個別的文化特性來比較和排序資料。

Note注意事項

在有些案例中,區分文化特性的行為並不適合。如需執行不區分文化特性作業之時機和方式的詳細資訊,請參閱不區分文化特性的字串作業

比較字串

CompareInfo 類別提供可用來執行區分文化特性字串比較的方法集。CultureInfo 類別具有 CultureInfo.CompareInfo 屬性,後者乃是此類別的執行個體。這個屬性定義比較和排序特定文化特性字串的方法。String.Compare 方法會使用 CultureInfo.CompareInfo 屬性的資訊來比較字串。如果 string1 小於 string2,String.Compare 方法將傳回負整數,如果 string1 和 string2 相等,將傳回零 (0),如果 string1 大於 string2,將傳回正整數。

下列程式碼範例展示根據用來執行比對的文化特性 String.Compare 方法,這兩個字串的評估方式有何不同。首先,CurrentCulture 會設為丹麥的丹麥文,且字串 "Apple" 和 "Æble" 會進行比較。丹麥文會將字元 Æ 視為單一字母,其字母排列位於字母 Z 之後。因此,在丹麥文化特性中,字串 "Æble" 大於 "Apple"。接著,CurrentCulture 會設為美式英文,並且再一次比較字串 "Apple" 和 "Æble"。這一次,字串 "Æble" 即被判斷為小於 "Apple"。英文會將字元 Æ 視為特殊符號,其字母排列位於字母 A 之前。

Imports System
Imports System.Globalization
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class TestClass
   Public Shared Sub Main()
      Dim str1 As String = "Apple"
      Dim str2 As String = "Æble"
      
      ' Sets the CurrentCulture to Danish in Denmark.
      Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
      Dim result1 As Integer = [String].Compare(str1, str2)
      Console.WriteLine(ControlChars.Newline + "When the CurrentCulture _
         is ""da-DK""," + ControlChars.Newline + " the result of _
         comparing_{0} with {1} is: {2}", str1, str2, result1)
      
      ' Sets the CurrentCulture to English in the U.S.
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      Dim result2 As Integer = [String].Compare(str1, str2)
      Console.WriteLine(ControlChars.Newline + "When the _
         CurrentCulture is""en-US""," + ControlChars.Newline + " _
         the result of comparing {0} with {1} is: {2}", str1, _
         str2,result2)
   End Sub
End Class
using System;
using System.Globalization;
using System.Threading;

public class CompareStringSample
{
   public static void Main()
   {
      string str1 = "Apple";
      string str2 = "Æble"; 

      // Sets the CurrentCulture to Danish in Denmark.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
      // Compares the two strings.
      int result1 = String.Compare(str1, str2);
      Console.WriteLine("\nWhen the CurrentCulture is \"da-DK\",\nthe 
            result of comparing {0} with {1} is: {2}",str1, str2, 
            result1);

      // Sets the CurrentCulture to English in the U.S.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      // Compares the two strings.
      int result2 = String.Compare(str1, str2);
      Console.WriteLine("\nWhen the CurrentCulture is \"en-US\",\nthe 
            result of comparing {0} with {1} is: {2}",str1, str2, 
            result2);
   }
}

如果您執行這個程式碼,它將產生下列輸出:

When the CurrentCulture is "da-DK", 
the result of comparing Apple with Æble is: -1

When the CurrentCulture is "en-US", 
the result of comparing Apple with Æble is: 1

如需比較字串的詳細資訊,請參閱 String 類別比較字串

使用替代排序次序

有些文化特性支援一個以上的排序次序。例如,文化特性 zh-CN (中國的中文) 支援發音排序 (預設) 和筆劃排序。當您使用文化特性名稱 (例如,zh-CN) 來建立 CultureInfo 物件時,將使用預設的排序次序。如果要指定替代排序次序,您可以使用替代排序次序的 LCID 來建立 CultureInfo 物件。然後從 CultureInfo.CompareInfo 取得 CompareInfo 物件 (用在字串比較)。或者,您也可以直接使用 CompareInfo.GetCompareInfo Method (Int32) 建立 CompareInfo 物件,指定 LCID 做為替代的排序次序。

下表列出支援替代排序次序的文化特性清單,以及預設和替代排序次序的 LCID。

文化特性名稱 語言-國家/地區 預設的排序名稱和 LCID 替代排序名稱和 LCID

es-ES

西班牙文 - 西班牙

國際:0x00000C0A

傳統:0x0000040A

zh-TW

中文 - 台灣

筆劃:0x00000404

注音符號:0x00030404

zh-CN

中文 - 中國

發音:0x00000804

筆劃:0x00020804

zh-HK

中文 - 香港特別行政區

發音:0x00000c04

筆劃:0x00020c04

zh-SG

中文 - 新加坡

發音:0x00001004

筆劃:0x00021004

zh-MO

中文 - 澳門特別行政區

發音:0x00001404

筆劃:0x00021404

ja-JP

日文 - 日本

預設:0x00000411

Unicode:0x00010411

ko-KR

韓文 - 韓國

預設:0x00000412

韓文 Xwansung - Unicode:0x00010412

de-DE

德文 - 德國

字典:0x00000407

電話簿排序 DIN:0x00010407

hu-HU

匈牙利文 - 匈牙利

預設:0x0000040e

技術排序:0x0001040e

ka-GE

喬治亞文 - 喬治亞

傳統:0x00000437

西班牙現代排序:0x00010437

搜尋字串

您可以使用多載的 CompareInfo.IndexOf 方法 來傳回指定字串中字元或子字串的以零起始索引。如果指定字串中找不到字元或子字串,該方法將傳回負整數。使用 CompareInfo.IndexOf 搜尋指定字元時,請注意接受 CompareOptions 參數的方法多載所執行的比較將與不接受 CompareOptions 參數的方法多載不同。搜尋 char (Visual Basic 中的 Char) 而且不接受 CompareOptions 型別參數的 CompareInfo.IndexOf 多載將會執行區分文化特性的搜尋。這表示如果 char 是代表預先組成字元的 Unicode 值,例如連字 'Æ' (\u00C6),它可能會被視為正確序列,例如 "AE" (\u0041\u0045) 中出現的任何一個元件,視文化特性而定。如果您要執行序數 (不區分文化特性) 搜尋,其中只有當 Unicode 值相同時,char 才會被視為等同於其他 char,請使用需要 CompareOptions 參數的其中一個 CompareInfo.IndexOf 多載。請將 CompareOptions 參數設為 CompareOptions.Ordinal 值。

您也可以使用搜尋 charString.IndexOf 方法的多載,來執行序數搜尋。請注意,搜尋字串的 String.IndexOf 方法之多載,將執行區分文化特性的搜尋。

下列程式碼範例展示根據文化特性,CompareInfo.IndexOf(string, char) 方法傳回的不同結果。CultureInfo 是為 "da-DK" (丹麥的丹麥文) 而建立的。接著,CompareInfo.IndexOf 方法的多載會用來在字串 "Æble" 和 "aeble" 中搜尋字元 'Æ'。請注意,CompareInfo.IndexOf 方法將針對 "da-DK" 文化特性使用 CompareOptions.Ordinal 參數,而不使用 CompareOptions.Ordinal 參數的 CompareInfo.Index 方法將傳回相同的結果。字元 'Æ' 只被視為等同於 Unicode 碼值 \u00E6。

Imports System
Imports System.Globalization
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class CompareClass
   Public Shared Sub Main()
      Dim str1 As String = "Æble"
      Dim str2 As String = "aeble"
      Dim find As Char = "Æ"
      
      ' Creates a CultureInfo for Danish in Denmark.
      Dim ci As New CultureInfo("da-DK")
      
      Dim result1 As Integer = ci.CompareInfo.IndexOf(str1, find)
      Dim result2 As Integer = ci.CompareInfo.IndexOf(str2, find)
      Dim result3 As Integer = ci.CompareInfo.IndexOf(str1, find, _ 
         CompareOptions.Ordinal)
      Dim result4 As Integer = ci.CompareInfo.IndexOf(str2, find, _
         CompareOptions.Ordinal)      
      
      Console.WriteLine(ControlChars.Newline + "CultureInfo is set to _
         {0}", ci.DisplayName)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str1, result1)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str2, result2)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char, CompareOptions) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str1, result3)
      Console.WriteLine(ControlChars.Newline + "Using _
         CompareInfo.IndexOf(string, char, CompareOptions) method" + _
         ControlChars.Newline + " the result of searching for {0} in the _
         string {1} is: {2}", find, str2, result4)
   End Sub
End Class
using System;
using System.Globalization;
using System.Threading;

public class CompareClass
{

   public static void Main()
   {
      string str1 = "Æble";
      string str2 = "aeble"; 
      char find = 'Æ';

      // Creates a CultureInfo for Danish in Denmark.
      CultureInfo ci= new CultureInfo("da-DK");

      int result1 = ci.CompareInfo.IndexOf(str1, find);
      int result2 = ci.CompareInfo.IndexOf(str2, find);
      int result3 = ci.CompareInfo.IndexOf(str1, find,   
         CompareOptions.Ordinal);
      int result4 = ci.CompareInfo.IndexOf(str2, find, 
         CompareOptions.Ordinal);

      Console.WriteLine("\nCultureInfo is set to {0} ", ci.DisplayName);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) 
         method\nthe result of searching for {0} in the string {1} is: 
         {2}", find, str1, result1);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) 
         method\nthe result of searching for {0} in the string {1} is: 
         {2}", find, str2, result2);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, 
         CompareOptions) method\nthe result of searching for {0} in the 
         string {1} is: {2}", find, str1, result3);
      Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, 
         CompareOptions) method\nthe result of searching for {0} in the 
         string {1} is: {2}", find, str2, result4);
   }
}

這個程式碼產生下列輸出:

CultureInfo is set to Danish (Denmark) 

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: -1

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1

如果您使用 CultureInfo ci = new CultureInfo ("en-US") 取代 CultureInfo ci = new CultureInfo ("da-DK");,則使用 CompareOptions.Ordinal 參數的 CompareInfo.Index 方法和不使用 CompareOptions.Ordinal 參數的 CompareInfo.Index 方法將傳回不同的結果。由 CompareInfo.IndexOf(string, char) 執行的區分文化特性比較,會將字元 'Æ' 評估為與其元件 "ae" 完全相同。由 CompareInfo.IndexOf(string, char, CompareOptions.Ordinal) 方法執行的序數 (不區分文化特性) 比較,不會傳回等同於 "ae" 的字元 'Æ',因為其 Unicode 碼的值不相符。

當您重新編譯和執行 "en-US" 文化特性的程式碼時,將產生下列輸出:

The CurrentCulture property is set to English (United States) 

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0

Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1

排序字串

Array 類別提供多載的 Array.Sort 方法,可讓您依據 CultureInfo.CurrentCulture 屬性排序陣列。在下列範例中,將建立由三個字串組成的陣列。首先,CurrentCulture 將設為 "en-US",並且將呼叫 Array.Sort 方法。產生的排序次序將使用為 "en-US" 文化特性的排序慣例做為依據。接著,CurrentCulture 將設為 "da-DK",並且再次呼叫 Array.Sort 方法。由於使用了為 "da-DK" 文化特性的排序慣例,因此請注意產生的排序次序與 "en-US" 結果有何不同之處。

Imports System
Imports System.Threading
Imports System.IO
Imports System.Globalization
Imports Microsoft.VisualBasic

Public Class TextToFile   
   Public Shared Sub Main()
      Dim str1 As [String] = "Apple"
      Dim str2 As [String] = "Æble"
      Dim str3 As [String] = "Zebra"
      
      ' Creates and initializes a new Array to store 
      ' these date/time objects.
      Dim stringArray As Array = Array.CreateInstance(GetType([String]), _
         3)
      stringArray.SetValue(str1, 0)
      stringArray.SetValue(str2, 1)
      stringArray.SetValue(str3, 2)
      
      ' Displays the values of the Array.
      Console.WriteLine(ControlChars.Newline + "The Array initially _
         contains the following strings:")
      PrintIndexAndValues(stringArray)
      
      ' Sets the CurrentCulture to "en-US".
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      ' Sorts the values of the Array.
      Array.Sort(stringArray)
      
      ' Displays the values of the Array.
      Console.WriteLine(ControlChars.Newline + "After sorting for the _
         culture ""en-US"":")
      PrintIndexAndValues(stringArray)
      
      ' Sets the CurrentCulture to "da-DK".
      Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
      ' Sort the values of the Array.
      Array.Sort(stringArray)
      
      ' Displays the values of the Array.
      Console.WriteLine(ControlChars.Newline + "After sorting for the _
         culture ""da-DK"":")
      PrintIndexAndValues(stringArray)
   End Sub

   Public Shared Sub PrintIndexAndValues(myArray As Array)
      Dim i As Integer
      For i = myArray.GetLowerBound(0) To myArray.GetUpperBound(0)
         Console.WriteLine(ControlChars.Tab + "[{0}]:" + _
            ControlChars.Tab + "{1}", i, myArray.GetValue(i))
      Next i
   End Sub 
End Class
using System;
using System.Threading;
using System.Globalization;

public class ArraySort 
{
   public static void Main(String[] args) 
   {
      String str1 = "Apple";
      String str2 = "Æble";
      String str3 = "Zebra";

      // Creates and initializes a new Array to store the strings.
      Array stringArray = Array.CreateInstance( typeof(String), 3 );
      stringArray.SetValue(str1, 0 );
      stringArray.SetValue(str2, 1 );
      stringArray.SetValue(str3, 2 );

      // Displays the values of the Array.
      Console.WriteLine( "\nThe Array initially contains the following 
            strings:" );
      PrintIndexAndValues(stringArray);

      // Sets the CurrentCulture to "en-US".
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      // Sort the values of the Array.
      Array.Sort(stringArray);

      // Displays the values of the Array.
      Console.WriteLine( "\nAfter sorting for the culture \"en-US\":" );
      PrintIndexAndValues(stringArray); 

      // Sets the CurrentCulture to "da-DK".
      Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
      // Sort the values of the Array.
      Array.Sort(stringArray);

      // Displays the values of the Array.
      Console.WriteLine( "\nAfter sorting for the culture \"da-DK\":" );
      PrintIndexAndValues(stringArray); 
   }
   public static void PrintIndexAndValues(Array myArray)  
   {
      for ( int i = myArray.GetLowerBound(0); i <= 
            myArray.GetUpperBound(0); i++ )
      Console.WriteLine( "\t[{0}]:\t{1}", i, myArray.GetValue( i ) );
   }
}

這個程式碼產生下列輸出:

The Array initially contains the following strings:
   [0]:   Apple
   [1]:   Æble
   [2]:   Zebra

After sorting for the culture "en-US":
   [0]:   Æble
   [1]:   Apple
   [2]:   Zebra

After sorting for the culture "da-DK":
   [0]:   Apple
   [1]:   Zebra
   [2]:   Æble

使用排序鍵

排序鍵將用來支援區分文化特性的排序作業。根據 Unicode Standard,字串的每個字元都指定有數種排序權重,其中包括字母、大小寫和變音符號權重。排序鍵可以當做特定字串的這些權重的存放庫。例如,排序鍵可能含有字母權重字串,之後跟隨大小寫權重字串,等等。如需排序鍵概念的詳細資訊,請參閱<Unicode Standard>,網址為 www.unicode.org。

在 .NET Framework 中,SortKey 類別會將字串對應到其排序鍵 (反之亦然)。您可以使用 CompareInfo.GetSortKey 方法為您指定的字串建立排序鍵。指定字串所產生的排序鍵是位元序列,該位元序列將式 CurrentCulture 和您指定的 CompareOptions 而有所不同。例如,如果您在建立排序鍵時指定 IgnoreCase,使用該排序鍵的字串比對作業將會忽略大小寫。

當您建立字串的排序鍵後,您可以將它當做參數傳遞給 SortKey 類別提供的方法。SortKey.Compare 方法可用來比較排序鍵。由於 SortKey.Compare 執行簡單的位元組逐一比較,因此速度要比使用 String.Compare 快得多。在時常用到排序功能的應用程式中,您可以為此應用程式使用到的所有字串產生並儲存排序鍵,藉以提高效能。如果必須使用排序或比對作業,您可以使用排序鍵,而不是字串。

下列程式碼範例會在 CurrentCulture 設為 "da-DK" 時建立兩個字串的排序鍵。它將使用 SortKey.Compare 方法來比較這兩個字串,並且顯示其結果。如果 string1 小於 string2,SortKey.Compare 方法會傳回負整數,如果 string1 和 string2 相等,將傳回零 (0),如果 string1 大於 string2,將傳回正整數。接著,CurrentCulture 將設為 "en-US" 文化特性,同時為相同的字串建立排序鍵。然後比較字串的排序鍵和顯示其結果。請注意,排序的結果將依據 CurrentCulture 而有所不同。雖然下列程式碼範例的結果和這個主題稍早之前出現的比較字串範例結果完全相同,但是 SortKey.Compare 方法比 String.Compare 方法速度更快。

Imports System
Imports System.Threading
Imports System.Globalization
Imports Microsoft.VisualBasic

Public Class SortKeySample
   Public Shared Sub Main()
      Dim str1 As [String] = "Apple"
      Dim str2 As [String] = "Æble"
      
      ' Sets the CurrentCulture to "da-DK".
      Dim dk As New CultureInfo("da-DK")
      Thread.CurrentThread.CurrentCulture = dk
      
      ' Creates a culturally sensitive sort key for str1.
      Dim sc1 As SortKey = dk.CompareInfo.GetSortKey(str1)
      ' Create a culturally sensitive sort key for str2.
      Dim sc2 As SortKey = dk.CompareInfo.GetSortKey(str2)
      
      ' Compares the two sort keys and display the results.
      Dim result1 As Integer = SortKey.Compare(sc1, sc2)
      Console.WriteLine(ControlChars.Newline + "When the CurrentCulture _
         is ""da-DK""," + ControlChars.Newline + " the result of _
         comparing {0} with {1} is: {2}", str1, str2, result1)
      
      ' Sets the CurrentCulture to "en-US".
      Dim enus As New CultureInfo("en-US")
      Thread.CurrentThread.CurrentCulture = enus
      
      ' Creates a culturally sensitive sort key for str1.
      Dim sc3 As SortKey = enus.CompareInfo.GetSortKey(str1)
      ' Create a culturally sensitive sort key for str1.
      Dim sc4 As SortKey = enus.CompareInfo.GetSortKey(str2)
      
      ' Compares the two sort keys and display the results.
      Dim result2 As Integer = SortKey.Compare(sc3, sc4)
      Console.WriteLine(ControlChars.Newline + "When the CurrentCulture _
         is ""en-US""," + ControlChars.Newline + " the result of _
         comparing {0} with {1} is: {2}", str1, str2, result2)
   End Sub
End Class
using System;
using System.Threading;
using System.Globalization;

public class SortKeySample 
{
   public static void Main(String[] args) 
   {
      String str1 = "Apple";
      String str2 = "Æble";

      // Sets the CurrentCulture to "da-DK".
      CultureInfo dk = new CultureInfo("da-DK");
      Thread.CurrentThread.CurrentCulture = dk;

      // Creates a culturally sensitive sort key for str1.
      SortKey sc1 = dk.CompareInfo.GetSortKey(str1);
      // Create a culturally sensitive sort key for str2.
      SortKey sc2 = dk.CompareInfo.GetSortKey(str2);

      // Compares the two sort keys and display the results.
      int result1 = SortKey.Compare(sc1, sc2);
      Console.WriteLine("\nWhen the CurrentCulture is \"da-DK\",\nthe 
            result of comparing {0} with {1} is: {2}", str1, str2, 
            result1);

      // Sets the CurrentCulture to "en-US".
      CultureInfo enus = new CultureInfo("en-US");
      Thread.CurrentThread.CurrentCulture = enus ;

      // Creates a culturally sensitive sort key for str1.
      SortKey sc3 = enus.CompareInfo.GetSortKey(str1);
      // Create a culturally sensitive sort key for str1.
      SortKey sc4 = enus.CompareInfo.GetSortKey(str2);

      // Compares the two sort keys and display the results.
      int result2 = SortKey.Compare(sc3, sc4);
      Console.WriteLine("\nWhen the CurrentCulture is \"en-US\",\nthe 
            result of comparing {0} with {1} is: {2}", str1, str2, 
            result2);
   }
}

這個程式碼產生下列輸出:

When the CurrentCulture is "da-DK", 
the result of comparing Apple with Æble is: -1

When the CurrentCulture is "en-US", 
the result of comparing Apple with Æble is: 1

正規化

您可以在排序之前將字串正規化為大寫或小寫。字串排序和大小寫的規則是特定的語言。例如,即使是在以拉丁文指令碼為基礎的語言中,有不同的撰寫和排序規則。只有少數的語言 (包括英文) 的排序次序是與字碼指標的次序相符 (例如,A [65] 在 B [66] 之前)。

請勿使用字碼指標來執行正確的排序和字串比對。此外,.NET Framework 不會強迫或保證指定的正規化格式您應該在您所開發的應用程式中執行適合的正規化作業。

請參閱

參考

CompareInfo Class
SortKey Class

概念

不區分文化特性的字串作業

其他資源

編碼和當地語系化