C# Socket编程(3)编码和解码
? ? ? 在網絡通信中,很多情況下:比如說QQ聊天,通訊雙方直接傳遞的都是字符信息。但是字符信息并不能夠直接通過網絡傳輸,這些字符集必須先轉換成一個字節序列后才能夠在網絡中傳輸,于是這里就產生了編碼和解碼的概念:
- 將字符序列轉換為字節序列的過程稱之為:編碼
- 將編碼的字節序列轉換為字符序列的過程稱之為:解碼
例如:對于Unicode字符來說,編碼是指將一組Unicode字符轉換為一個字節序列的過程,解碼就是講一個編碼字節序列轉換為一組Unicode字符。
目錄索引:
1.字符編碼基礎知識
1.1 ASCII字符集
1.2 非ASCII字符集
1.3 Unicode字符集
1.4 UTF(通用轉換格式)的出現
2.C#中不同編碼和Unicode之間的轉換
2.1 獲取系統所有編碼
2.2 獲取指定編碼信息
2.3 不同編碼間的轉換
3.C#編碼和解碼
?
字符編碼基礎知識
字符集(Charset):是一個系統支持的所有抽象字符的集合。字符是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。常見的編碼方式主要有一下三種:
1.1 ASCII字符集
ASCII(American?Standard?Code for?Information?Interchange,美國信息交換標準代碼)是基于拉丁字母的一套電腦編碼系統。它主要用于顯示現代英語,而其擴展版本EASCII則可以勉強顯示其他西歐語言。它是現今最通用的單字節編碼系統(但是有被Unicode追上的跡象),并等同于國際標準ISO/IEC 646。
1.2 非ASCII字符集
? 由于ASCII字符集是針對英語設計的,當處理漢字等其他非拉丁語系的字符時,這種編碼就不能適用了(因為適用128個字符表示英文是完全足夠的,但是用了表示中文就遠遠不夠了)。為了解決這個問題,不同的國加和地區制定了自己編碼標準。中國一般適用國標碼,常用的有GB2312-1980編碼和GB183030-2000編碼,其中GB183030-2000編碼漢字更多,是中國計算機系統必須遵循的基礎性標準之一。
1.3 Unicode字符集
? ? ? 由于每個國家、語系都擁有獨立的編碼方式,同一個二進制數字可以被解釋成不同的字符,因此要想打開一個文本文件,就必須知道它的編碼方式,否則就可能出現亂碼。為了使用國際信息交流更加方便,非營利機構統一碼聯盟制定和標準化了Unicode字符集。使用16位的編碼空間。也就是每個字符占用2個字節。這樣理論上一共最多可以表示216(即65536)個字符。基本滿足各種語言的使用。實際上當前版本的統一碼并未完全使用這16位編碼,而是保留了大量空間以作為特殊使用或將來擴展。
1.4 UTF(通用轉換格式)的出現
? ? Unicode的實現方式不同于編碼方式。一個字符的Unicode編碼是確定的。但是在實際傳輸過程中,由于不同系統平臺的設計不一定一致,以及出于節省空間的目的(例如:在C#中字符默認都是Unicode碼,即一個英文字符占兩個字節,一個漢字也是兩個字節,這對于能適應ASCII字符集來表示的字符來說比較顯得浪費。),對Unicode編碼的實現方式有所不同。Unicode的實現方式稱為Unicode轉換格式(Unicode Transformation Format,簡稱UTF)。目前流行和UFT格式包括UTF-8、UTF16和UTF-32。
? 其中,UTF-8編碼是互聯網上使用最廣泛的一種UTF格式,這是一種變長編碼,它將基本7位ASCII字符仍用7位編碼表示,占用一個字節(首位補0)。而遇到與其他Unicode字符混合的情況,將按一定算法轉換,每個字符使用1-3個字節編碼,并利用首位為0或1進行識別。這樣對以7位ASCII字符為主的西文文檔就大大節省了編碼長度。UTF-8是與字節順序無關的,它的字節順序在所有系統中都是一樣的,因此這種編碼可以使排序變得很容易。
2.C#中不同編碼和Unicode之間的轉換
? ? ? 在C#語言中對于不同編碼和Unicode之間的轉換使用位于System.Text命名空間中的Encoding類。通過這個類我們可以為不同的字符集直接進行轉換以及各個字符集的相關信息。
2.1 獲取系統所有編碼信息
? ? ? 我們通過調用Encoding類的GetEncoding()方法獲取包含所有編碼的數組,數組元素為EncodingInfo類,通過數組元素我們可以獲得各種類型編碼的信息。例如我們可以通過下面的代碼獲取主機上所有編碼的信息:
//獲取系統所有編碼名稱及其描述信息EncodingInfo[] allEncoding = Encoding.GetEncodings();foreach (EncodingInfo encoding in allEncoding)
{Console.WriteLine("編碼標識符:{0,-10}編碼名稱:{1,-12}編碼說明:{2}", encoding.CodePage, encoding.Name, encoding.DisplayName);}
Console.ReadLine();
運行如下:
?
?
2.2 獲取指定的編碼信息
Encoding 類提供了常用的字符集編碼可以直接通過調用屬性獲取:UTF-8,ASCII 等屬性,也可以通過調用GetEncoding(+4重載)方法直接獲取指定的字符集編碼對象。例如,下面的代碼:
//獲取指定的編碼描述信息Encoding gb18030Encoding = Encoding.GetEncoding("GB18030");Encoding asciiEncoding = Encoding.ASCII;Console.WriteLine("編碼標識符:{0,-10}編碼名稱:{1,-12}編碼說明:{2}", gb18030Encoding.CodePage, gb18030Encoding.HeaderName, gb18030Encoding.EncodingName);Console.WriteLine("編碼標識符:{0,-10}編碼名稱:{1,-12}編碼說明:{2}", asciiEncoding.CodePage, asciiEncoding.HeaderName, asciiEncoding.EncodingName);運行如下:
?
2.3在不同編碼之間進行轉換
我們可以可以通過利用 Encoding.Convert(+2重載)直接將字節數組從一種編碼轉換為另一種編碼。下面我們同樣通過一個示例代碼來學習如何對不同編碼的字節序列進行轉換。下面的示例程序,為了清楚的演示如何使用,可能代碼比較冗余(代碼中包含解碼和編碼部分,在隨后會給出相應示例),實際的應用中我們可以根據自己的情況進行適當的對方法抽象,重構,提升程序的可讀性和效率。代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace ConsoleApplication1 {class Program{public static void Main(){//不同編碼之間的轉換string GB18030String = "你好!晴天豬";Console.WriteLine("需要轉換的字符串:{0}",GB18030String);#region 對字符進行GB18030格式編碼//獲取編碼器Encoding gb18030Encoding = Encoding.GetEncoding("GB18030");//將字符串轉換為char類型數組char[] chars = GB18030String.ToCharArray();//獲取編碼為字節序列后的字節數組長度int buffLength = gb18030Encoding.GetByteCount(chars, 0, chars.Length);//根據獲取的字節長度聲明數組,存儲編碼后的字節byte[] gb18030Buffer = new byte[buffLength];//獲取GB18030編碼的字節序列gb18030Buffer = gb18030Encoding.GetBytes(chars, 0, chars.Length);Console.WriteLine("GB18030編碼的字節序列:{0}", BitConverter.ToString(gb18030Buffer));//將GB18030編碼的字節序列轉換成UTF-8編碼的字節序列byte[] unicodeBuffer = Encoding.Convert(gb18030Encoding, Encoding.UTF8, gb18030Buffer);Console.WriteLine("轉換為UTF-8編碼字節序列:{0}", BitConverter.ToString(unicodeBuffer));#endregion#region 將GB18030編碼轉換為UTF-8編碼//獲取UTF-8解碼Decoder utf8Decoder = Encoding.UTF8.GetDecoder();//獲取解碼為字符后字符數組的長度int utfChartsLength = utf8Decoder.GetCharCount(unicodeBuffer, 0, unicodeBuffer.Length, true);//根據獲取解碼后的長度創建char數組char[] utfChart = new char[utfChartsLength];//將UTF-8編碼的字節序列轉換為字符數組utf8Decoder.GetChars(unicodeBuffer, 0, unicodeBuffer.Length, utfChart, 0);StringBuilder strBuilder = new StringBuilder();foreach (char ca in utfChart){strBuilder.Append(ca);}Console.WriteLine("UTF-8的字符序列解碼:{0}", strBuilder.ToString());#endregionConsole.ReadLine();}} }運行程序:
?
3.C#編碼和解碼
在C#中為我們提供了Encoder和Decoder類,分別對字符進行編碼和對字節序列進行解碼的兩個類。通過使用它們,我們可以很方便進行對字符和字節序列進行編碼和解碼操作。由于它們的構造函數都是protected級別的,需要使用?Encoding?實現的GetEncoding方法才能獲取到它們的實例對象。下面我們通過一個Windows Forms示例程序來了解和學習如何使用這兩個類,編碼和解碼的主要代碼如下:
View Code /// <summary>/// 獲取字符串編碼之后的bytes數組/// </summary>/// <param name="codeType">編碼類型名稱</param>/// <param name="strCode">將被編碼的字符串</param>/// <returns></returns>private byte[] GetEncodeBeforeBuffer(string codeType,string strCode){//根據編碼類型構造該類型編碼的編碼器的實例Encoder encoder = Encoding.GetEncoding(codeType).GetEncoder();char[] chars = strCode.ToCharArray();//根據獲取對字符進行編碼所產生的字節數來創建一個byte數組byte[] bytes = new byte[encoder.GetByteCount(chars, 0, chars.Length, true)];//將字符寫入到byte數組中encoder.GetBytes(chars, 0, chars.Length, bytes, 0, true);return bytes;}/// <summary>///獲取字符串解碼之后的字符串/// </summary>/// <param name="codeType">編碼格式</param>/// <param name="byteCode">編碼的字節數組</param>/// <returns></returns>private string GetDecodeBeforeText(string codeType, byte[] byteCode){//根據編碼類型構造該類型編碼的解碼器的實例Decoder decoder = Encoding.GetEncoding(codeType).GetDecoder();//計算對字節序列(從指定字節數組開始)進行解碼所產生的字符數char[] chars = new char[decoder.GetCharCount(byteCode, 0, byteCode.Length,true)];//根據獲取的解碼所產生的字節數來創建一個char數組int charLen = decoder.GetChars(byteCode, 0, byteCode.Length, chars, 0);StringBuilder strResult = new StringBuilder();foreach (char c in chars){strResult = strResult.Append(c.ToString());}return strResult.ToString();}運行程序:
?
猛點擊下載:源代碼
轉載于:https://www.cnblogs.com/blosaa/p/3143517.html
總結
以上是生活随笔為你收集整理的C# Socket编程(3)编码和解码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【position也可以很复杂】当弹出层
- 下一篇: JS、JQuery和ExtJs的跨域处理