字元編碼再次剖析
這幾天一直在研究字元編碼,也學到了不少的知識,現在在此進行細細總結。轉載請註明出處。
首先引用一段網上對字元編碼的風趣解釋:
問:計算機是怎麼表示文字的? 他不會. 他就會說0和1.
於是乎 有一幫人為了表示字母和各種符號,就發明了ASCII 實際上就是固定了.一個八位的位元組固定的01排列來表示固定的字元.
比如.字母A 的ASCII碼就是.65. 這個排列就是.01000001.當然,這只是ASCII的編碼,同樣呢,有好多好多種編碼,當然道理是一樣的. 當你要把這個串"A",傳送到別的機器,千萬要記住,你發的不是文字"A",你發過去的是一串01000001(ASCII的時候).
那麼現在我們就要好好理解一下字元和位元組的概念了,一個字元可以由任意整數個位元組進行表示,這也就是說,一個字元可以由一個位元組表示,也可以由多個位元組表示,如在ASCII中一個字元由一個位元組組成,而gb2312和ASCII相容,而且由兩個位元組來表示中文,gbk是gb2312的超集,這也就意味著gb類的字元編碼是變長儲存的。而unicode(預設的實現方式是小頭儲存,即ucs-2)每個字元是由兩個位元組儲存的,且字元的第二個位元組在儲存的時候放在前面,而且通過補0和ascii形成假相容,unicode big endian即所謂的大頭儲存,即字元的第一個位元組放在前面。這兩種unicode的儲存方式造成了儲存空間的浪費,而且與ascii是假相容的。而utf-8解決了上述的兩個問題,目前windows下的預設編碼方式是ansi,即gbk,在vc6.0下是ansi,而在vs2010已經採用了utf-8的編碼方式。
在這裡我們可以使用ultraedit的十六進位制檢視工具來檢視不同編碼的檔案的儲存結構。分別將一個有相同的文字內容的文字檔案另存為ansi編碼,unicode編碼,unicode big endian編碼和utf-8編碼的檔案並且用ultraedit開啟,切換至十六進位制檢視下,進行檢視。可以看到,ansi檔案沒有字首,ascii字元用一個位元組,而中文用兩個位元組。而unicode編碼的檔案有字首FF FE,unicode big endian有檔案字首FE FF,而且可以看到不管任何字元都用兩個位元組表示,其中有很多的00位元組,這勢必會在c語言中字串的操作上帶來很大的不便。utf-8有檔案字首EF BB BF,而且中文是用三個位元組表示的。可以通過檢視vc和vs生成的檔案來檢視其不同的編碼方式。
現在我有一箇中英文混合的utf-8編碼的檔案,想逐行列印其中的每一個字元,那麼可以使用下面的程式:
string path = "C:\\Users\\Yelbosh\\Desktop\\tem.txt";
System.IO.StreamReader sr = new System.IO.StreamReader(path, Encoding.UTF8);
string tempstr = sr.ReadToEnd();
foreach (char tempc in tempstr)
{
Console.WriteLine(tempc.ToString());
}
這裡其他編碼方式的檔案當然也可以,我們最主要使用的是foreach函式,這裡可以通過streamreader按照不同的編碼方式解析檔案的內容。
C#也提供了很多的方法來進行不同編碼方式之間的位元組陣列的轉換。使用encoding的convert方法可以在不同的編碼方式之間進行轉換。
string str = "你好嗎我其實h好的i";
System.Text.Encoding gb2 = System.Text.Encoding.GetEncoding("GB2312");
byte[] b1 = gb2.GetBytes(str);
/*
foreach (byte b in b1)
{
Console.Write(b.ToString("X2")); Console.Write("\t");
}
Console.Write("\n");
* * */
System.Text.Encoding uni = System.Text.Encoding.GetEncoding("Unicode");
string msg = uni.GetString(System.Text.Encoding.Convert(gb2, uni, b1));
Console.Write(msg);
通過實驗我們可以得出正確的結論。其實我們也可以看出字串的顯示已經脫離了底層,已經不屬於編碼方式的範疇了。
但是c#並沒有給出原始碼,那麼計算機如何進行不同編碼方式之間的轉換呢?它是怎麼識別變長儲存呢?如何用c++編寫不同字元編碼方式之間的轉換呢?請繼續關注該部落格~
相關文章
- 字元編碼字元
- 字串-字元編碼字串字元
- 聊聊字元編碼字元
- 1.3.0 Python 字元編碼Python字元
- 字元編碼轉換字元
- 圖解字元編碼圖解字元
- 字元編碼問題字元
- 字符集編碼(二):字元編碼模型字元模型
- 字元編碼那些事兒字元
- 深入剖析go中字串的編碼問題——特殊字元的string怎麼轉byte?Go字串字元
- python教程3.3:字元和編碼Python字元
- MySQL 中字元編碼問題MySql字元
- 字元編碼問題記錄字元
- MySQL字元編碼設定方法MySql字元
- IDEA如何設定編碼格式,字元編碼,全域性編碼和專案編碼格式Idea字元
- 每日 30 秒 ⏱ 字元編碼排雷錄字元
- 字元編碼與檔案處理字元
- ptyon 特殊處理 url 編碼與解碼,字元編碼轉化 unicode字元Unicode
- 結合例項學習|字元編碼和解碼字元
- Redis字串型別內部編碼剖析Redis字串型別
- scheme跳轉特殊字元編碼問題Scheme字元
- GC機制+字元編碼+檔案操作GC字元
- Chardet: 通用字元編碼檢測器字元
- 計算機字元編碼的前世今生計算機字元
- 程式設計入門之字元編碼與亂碼程式設計字元
- 字元編碼及空白漢字佔位符字元
- 從一個故事開始聊聊字元編碼字元
- 字元編碼發展史1 — ASCII和EASCII字元ASCII
- 網址URL中特殊字元轉義編碼字元
- 字元編碼:Unicode & UTF-16 & UTF-8字元Unicode
- [20210422]如何檢視字元的ascii編碼.txt字元ASCII
- XSS與字元編碼的那些事兒 ---科普文字元
- 關於字元編碼你應該知道的事情字元
- 字元編碼發展史2 — ISO-8859-N字元
- maven編譯遇到"編碼GBK的不可對映字元"警告的處理Maven編譯字元
- 深入剖析Vue原始碼 - 例項掛載,編譯流程Vue原始碼編譯
- 可能是最詳細的字元編碼詳解字元
- Java 如何獲取字元所對應的UniCode編碼Java字元Unicode
- 字元編碼發展史4 — Unicode與UTF-8字元Unicode