編碼是將字元集轉換成位元組序列的處理程序。解碼則正好相反,它是將已編碼的位元組序列轉換成字元集的處理程序。
Encoder 可維持 GetBytes 連續呼叫之間的狀態資訊,因此它可以正確地對展開區塊的字元序列進行編碼。Encoder 也會在資料區塊尾端保留尾端字元,並在下一次編碼作業中使用該尾端字元。例如,資料區塊可能會以無對應的高 Surrogate 做為結尾,而對應的低 Surrogate 則會放在下一個資料區塊。因此,Decoder 和 Encoder 類別在網路傳輸和檔案作業中是非常有用的,因為這些作業經常會處理資料區塊,而非完整的資料流。
GetByteCount 方法判斷編碼 Unicode 字元集會產生多少位元組,而 GetBytes 方法則執行實際的編碼作業。
若要取得此類別實作的執行個體,請使用 Encoding 實作的 GetEncoder 方法。
Decoder 可維持 GetChars 連續呼叫之間的狀態資訊,因此它可以正確地對展開區塊的位元組序列進行解碼。Decoder 也會保留資料區塊尾端的結尾位元組,並在下一次解碼作業中使用該結尾位元組。因此,GetDecoder 和 GetEncoder 在網路傳輸和檔案作業中是非常有用的,因為這些作業經常會處理資料區塊而非完整的資料流。
GetCharCount 方法會判斷有多少字元會造成位元組序列的解碼,而由 GetChars 方法執行實際解碼。
若要取得此類別實作的執行個體,請使用 Encoding 實作的 GetDecoder 方法。
1.指定的編碼方式,將 Unicode 字元陣列轉換成位元組區塊。比較時,先使用 UTF7Encoding 對字元陣列進行編碼。接著,再使用 Encoder 對字元陣列進行編碼。
using System;
using System.Text;
class EncoderTest {
public static void Main() {
// The characters to encode.
Char[] chars = new Char[] {
'\u0023', // #
'\u0025', // %
'\u03a0', // Pi
'\u03a3' // Sigma
};
// Encode characters using an Encoding object.
Encoding encoding = Encoding.UTF7;
Console.WriteLine("Using Encoding\n--------------");
// Encode complete array for comparison.
Byte[] allCharactersFromEncoding = encoding.GetBytes(chars);
Console.WriteLine("All characters encoded:");
ShowArray(allCharactersFromEncoding);
// Encode characters, one-by-one.
// The Encoding object will NOT maintain state between calls.
Byte[] firstchar = encoding.GetBytes(chars, 0, 1);
Console.WriteLine("First character:");
ShowArray(firstchar);
Byte[] secondchar = encoding.GetBytes(chars, 1, 1);
Console.WriteLine("Second character:");
ShowArray(secondchar);
Byte[] thirdchar = encoding.GetBytes(chars, 2, 1);
Console.WriteLine("Third character:");
ShowArray(thirdchar);
Byte[] fourthchar = encoding.GetBytes(chars, 3, 1);
Console.WriteLine("Fourth character:");
ShowArray(fourthchar);
// Now, encode characters using an Encoder object.
Encoder encoder = encoding.GetEncoder();
Console.WriteLine("Using Encoder\n-------------");
// Encode complete array for comparison.
Byte[] allCharactersFromEncoder = new Byte[encoder.GetByteCount(chars, 0, chars.Length, true)];
encoder.GetBytes(chars, 0, chars.Length, allCharactersFromEncoder, 0, true);
Console.WriteLine("All characters encoded:");
ShowArray(allCharactersFromEncoder);
// Do not flush state; i.e. maintain state between calls.
bool bFlushState = false;
// Encode characters one-by-one.
// By maintaining state, the Encoder will not store extra bytes in the output.
Byte[] firstcharNoFlush = new Byte[encoder.GetByteCount(chars, 0, 1, bFlushState)];
encoder.GetBytes(chars, 0, 1, firstcharNoFlush, 0, bFlushState);
Console.WriteLine("First character:");
ShowArray(firstcharNoFlush);
Byte[] secondcharNoFlush = new Byte[encoder.GetByteCount(chars, 1, 1, bFlushState)];
encoder.GetBytes(chars, 1, 1, secondcharNoFlush, 0, bFlushState);
Console.WriteLine("Second character:");
ShowArray(secondcharNoFlush);
Byte[] thirdcharNoFlush = new Byte[encoder.GetByteCount(chars, 2, 1, bFlushState)];
encoder.GetBytes(chars, 2, 1, thirdcharNoFlush, 0, bFlushState);
Console.WriteLine("Third character:");
ShowArray(thirdcharNoFlush);
// Must flush state on last call to GetBytes().
bFlushState = true;
Byte[] fourthcharNoFlush = new Byte[encoder.GetByteCount(chars, 3, 1, bFlushState)];
encoder.GetBytes(chars, 3, 1, fourthcharNoFlush, 0, bFlushState);
Console.WriteLine("Fourth character:");
ShowArray(fourthcharNoFlush);
}
public static void ShowArray(Array theArray) {
foreach (Object o in theArray) {
Console.Write("[{0}]", o);
}
Console.WriteLine("\n");
}
}
2.使用 Decoder 將兩個不同的位元組陣列轉換成一個字元陣列。其中一個字元的位元組會展開陣列。它和 System.IO.StreamReader 在讀取資料流時的內部作業方式類似。
using System;
using System.Text;
public class dec
{
public static void Main()
{
// These bytes in UTF-8 correspond to 3 different Unicode
// characters: space (U+0020), # (U+0023), and the biohazard
// symbol (U+2623). Note the biohazard symbol requires 3 bytes
// in UTF-8 (hexadecimal e2, 98, a3). Decoders store state across
// multiple calls to GetChars, handling the case when one char
// is in multiple byte arrays.
byte[] bytes1 = { 0x20, 0x23, 0xe2 };
byte[] bytes2 = { 0x98, 0xa3 };
char[] chars = new char[3];
Decoder d = Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(bytes1, 0, bytes1.Length, chars, 0);
// The value of charLen should be 2 now.
charLen += d.GetChars(bytes2, 0, bytes2.Length, chars, charLen);
foreach(char c in chars)
Console.Write("U+{0:X4} ", (ushort)c);
}
}
以上資料來源: http://msdn.microsoft.com/zh-tw/library/h5y3703w(v=vs.80)
3. Encoding 類別
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Encoding : ICloneable
編碼是將 Unicode 字元集轉換成位元組序列的處理程序。解碼正好相反,它是將已編碼的位元組序列轉換成 Unicode 字元集的處理程序。
Unicode 標準會指派字碼指標 (數字) 給每個受支援指令碼中的每個字元。Unicode Transformation Format (UTF) 是用來編碼該字碼指標的方法。Unicode 標準 3.2 版使用下列 UTF:
- UTF-8,將每個字碼指標表示成 1 到 4 個位元組的序列。
- UTF-16,將每個字碼指標表示成 1 到 2 個 16 位元整數的序列。
- UTF-32,將每個字碼指標表示成 32 位元整數。
.NET Framework 提供下列 Encoding 類別實作來支援目前的 Unicode 編碼方式和其他編碼方式:
- ASCIIEncoding 可編碼 Unicode 字元成單一 7 位元 ASCII 字元。這種編碼方式只支援 U+0000 和 U+007F 之間的字元值。字碼頁 20127。也可透過 ASCII 屬性取得。
- UTF7Encoding 會使用 UTF-7 編碼方式為 Unicode 字元編碼。這種編碼方式支援所有的 Unicode 字元值。字碼頁 65000。也可透過 UTF7 屬性取得。
- UTF8Encoding 會使用 UTF-8 編碼方式為 Unicode 字元編碼。這種編碼方式支援所有的 Unicode 字元值。字碼頁 65001。也可透過 UTF8 屬性取得。
- UnicodeEncoding 會使用 UTF-16 編碼方式為 Unicode 字元編碼。同時支援 Little-Endian (字碼頁 1200) 和 Big-Endian (字碼頁 1201) 位元組順序。也可透過 Unicode 屬性和 BigEndianUnicode屬性取得。
- UTF32Encoding 會使用 UTF-32 編碼方式為 Unicode 字元編碼。同時支援 Little-Endian (字碼頁 65005) 和 Big-Endian (字碼頁 65006) 位元組順序。也可透過 UTF32 屬性取得。
使用 GetEncoding 方法取得其他編碼方式。使用 GetEncodings 方法,取得所有編碼方式的清單。
GetByteCount 方法判斷編碼 Unicode 字元集會產生多少位元組,而 GetBytes 方法則執行實際的編碼作業。
同樣地,GetCharCount 方法會判斷有多少字元會造成位元組序列的解碼,而由 GetChars 方法執行實際解碼。
如果要轉換的資料只可以從連續區塊 (例如從資料流讀取的資料) 取得時,或資料量太大而必須分成較小區塊時,請分別使用衍生類別的 GetDecoder 方法或 GetEncoder 方法提供的 Decoder 或Encoder。
UTF-16 和 UTF-32 編碼器可以使用 Big-Endian 位元組順序 (最大顯著性位元組在前) 或 Little-Endian 位元組順序 (最小顯著性位元組在前)。例如,拉丁大寫字母 A (U+0041) 會序列化如下 (使用十六進位):
- UTF-16 Big-Endian 位元組順序:00 41
- UTF-16 Little-Endian 位元組順序:41 00
- UTF-32 Big-Endian 位元組順序:00 00 00 41
- UTF-32 Little-Endian 位元組順序:41 00 00 00
或是,Encoding 會提供前序編碼,這會是位元組陣列,您可將它加在編碼過程所得位元組序列的前面。如果前序編碼含有位元組順序標記 (Unicode 中的字碼指標 U+FEFF),就可以協助解碼器判斷位元組順序和轉換格式或 UTF。Unicode 位元組順序標記會序列化為如下所示 (以十六進位方式):
- UTF-8:EF BB BF
- UTF-16 Big-Endian 位元組順序:FE FF
- UTF-16 Little-Endian 位元組順序:FF FE
- UTF-32 Big-Endian 位元組順序:00 00 FE FF
- UTF-32 Little-Endian 位元組順序:FF FE 00 00
使用原生的位元組順序來儲存 Unicode 字元,通常會更有效率。例如,在 Intel 電腦之類的 Little-Endian 平台上,最好使用 Little-Endian 位元組順序。
GetPreamble 方法會傳回可包含位元組順序標記的位元組陣列。如果此位元組陣列有前置編碼的資料流,將有助於解碼器識別所用的編碼格式。
如需位元組順序和位元組順序標記的詳細資訊,請參閱 www.unicode.org 網站上的<The Unicode Standard>。
EX: 編碼方式轉換成另一個編碼方式
using System;
using System.Text;
namespace ConvertExample
{
class ConvertExampleClass
{
static void Main()
{
string unicodeString = "This string contains the unicode character Pi(\u03a0)";
// Create two different encodings.
Encoding ascii = Encoding.ASCII;
Encoding unicode = Encoding.Unicode;
// Convert the string into a byte[].
byte[] unicodeBytes = unicode.GetBytes(unicodeString);
// Perform the conversion from one encoding to the other.
byte[] asciiBytes = Encoding.Convert(unicode, ascii, unicodeBytes);
// Convert the new byte[] into a char[] and then into a string.
// This is a slightly different approach to converting to illustrate
// the use of GetCharCount/GetChars.
char[] asciiChars = new char[ascii.GetCharCount(asciiBytes, 0, asciiBytes.Length)];
ascii.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0);
string asciiString = new string(asciiChars);
// Display the strings created before and after the conversion.
Console.WriteLine("Original string: {0}", unicodeString);
Console.WriteLine("Ascii converted string: {0}", asciiString);
}
}
}
以上資料來源: http://msdn.microsoft.com/zh-tw/library/system.text.encoding(v=vs.80)
沒有留言:
張貼留言