字符串、字符、字節以及bit位小結與疑問


 字符串是由一個個字符組成的,每個字符又有一個或多個字節來表示,每個字節又由8個bit位來表示

在C#里 字符串通常由string來聲明,字符由char來聲明,字節由byte來表示,位由bit來表示,具體分析見下面的測試代碼分析:

完整測試代碼:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Linq.Expressions;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 using System.IO;
 8 namespace CSharpRumenJD
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14 
15             string unicodestr = "啊?/123";
16             Console.WriteLine("字符串:" + unicodestr);
17             Console.WriteLine("字符長度:" + unicodestr.Length);
18             Console.WriteLine("Unicode字節長度:" + System.Text.Encoding.Unicode.GetByteCount(unicodestr));
19             var unicodebytes = System.Text.Encoding.Unicode.GetBytes(unicodestr);
20             Console.WriteLine("gb2312字節長度:" + Encoding.GetEncoding("gb2312").GetByteCount(unicodestr));
21             var gb2312bytes = System.Text.Encoding.GetEncoding("gb2312").GetBytes(unicodestr);
22             #region 亂碼測試
23             var gb2312tounidecodestr = System.Text.Encoding.Unicode.GetString(gb2312bytes);
24             Console.WriteLine("gb2312bytes轉化成Unicode字符串:" + gb2312tounidecodestr);
25             var gb2312str = System.Text.Encoding.GetEncoding("gb2312").GetString(gb2312bytes);
26             Console.WriteLine("gb2312bytes字符串:" + gb2312str);
27             #endregion
28             #region 打印二進制數據
29             int capacity = gb2312bytes.Length * 8;
30             StringBuilder sb = new StringBuilder(capacity);
31             for (int i = 0; i < gb2312bytes.Length; i++)
32             {
33                 sb.Append(gb2312bytes[i] + ":" + Convert.ToString(gb2312bytes[i], 2).PadLeft(8, '0') + "|");
34             }
35             Console.WriteLine(sb.ToString().TrimEnd('|'));
36             #endregion
37             StreamWriter sw = new StreamWriter("1.txt", false, System.Text.Encoding.Unicode);
38             sw.Write(unicodestr);
39             sw.Close();
40             StreamWriter sw1 = new StreamWriter("2.txt", false, Encoding.GetEncoding("gb2312"));
41             sw1.Write(unicodestr);
42             sw1.Close();
43             Console.ReadKey();
44         }
45     }
46 }
View Code

測試結果:


 

通過測試結果可以看到同樣一個字符串,

通過Unicode編碼獲取的字節長度為12,通過GB2312獲取的字節長度為7,

而且使用Unicode去把GB2312編碼的的字節數組轉化成字符串時出現亂碼問題,使用GB2312的編碼方式把GB2312編碼的字節數組轉化成字符串時沒有任何問題的,

疑問一:為什么兩種編碼方式得到的字節長度不同呢?


 

Unicode碼:Unicode碼也是一種國際標准編碼,Unicode目前普遍采用的是UCS-2,它用兩個字節來編碼一個字符(多虧了ohmygirl的指點),C#中的Unicode默認使用UTF-16編碼格式,所以上面的字符串的字節長度為12,

GB2312編碼是ANSI編碼中的一個分支,在使用 ANSI 編碼支持多種語言階段,每個字符使用一個字節或多個字節來表示(MBCS),因此,這種方式存放的字符也被稱作多字節字符。比如,"啊?/123"長度7個字節,每個漢字占2個字節,每個英文和數字字符占1個字節,

字符與編碼的發展

從計算機對多國語言的支持角度看,大致可以分為三個階段:

 

系統內碼

說明

系統

階段一

ASCII

計算機剛開始只支持英語,其它語言不能夠在計算機上存儲和顯示。

英文 DOS

階段二

ANSI編碼
(本地化)

為使計算機支持更多語言,通常使用 0x80~0xFF 范圍的 2 個字節來表示 1 個字符。比如:漢字 '中' 在中文操作系統中,使用 [0xD6,0xD0] 這兩個字節存儲。

不同的國家和地區制定了不同的標准,由此產生了 GB2312, BIG5, JIS 等各自的編碼標准。這些使用 2 個字節來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼。在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。

不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。

中文 DOS,中文 Windows 95/98,日文 Windows 95/98

階段三

UNICODE
(國際化)

為了使國際間信息交流更加方便,國際組織制定了 UNICODE 字符集,為各種語言中的每一個字符設定了統一並且唯一的數字編號,以滿足跨語言、跨平台進行文本轉換、處理的要求。

Windows NT/2000/XP,Linux,Java

 

疑問二:最后一行的十進制數字代表什么呢?


 

因為字節數組是由GB2312編碼格式得到的,所以需要先了解GB2312的處理方式,在使用GB2312的程序中,每個漢字及符號以兩個字節來表示。第一個字節稱為“高位字節”(也稱“區字節)”,第二個字節稱為“低位字節”(也稱“位字節”),“高位字節”使用了0xA1-0xF7(把01-87區的區號加上0xA0),“低位字節”使用了0xA1-0xFE(把01-94加上 0xA0),其中0xA0轉化成10進制數字就是160,“啊”字是GB2312字符集的第一個漢字,它的區號16,位號01,則區位碼是1601,

所以高位字節碼為0xA0+16即160+16=176,低位字節碼0xA0+01即160+1=161,正好和吻合,而剩下的五個十進制數字和啊字后面的五個字符個數相符,經查:

 

疑問三:為什么生成的文本文件大小和字節不一致?



從下圖可以看到GB2312編碼格式生成的文件大小為7字節,和控制台打印出來的一致,而Unicode編碼格式生成的文件為14字節,比控制台打印出來的字節長度真真的大了2個字節,不知道如何解釋這個現象

 

 參考資料:

  1. 字符,字節和編碼
  2. bit、byte、位、字節、漢字、字符之間的區別
  3. 信息交換用漢字編碼字符集
  4. GB2312字符集的詳解
  5. ASCII碼對照表

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM