因為打開記事本亂碼后忿偷,就去翻了網(wǎng)上比較好的博客作為材料趣些,本文對網(wǎng)上的博客進(jìn)行的再次的編輯撰寫仿荆。
一、首先什么是編碼
編碼意思是一種含義的內(nèi)容坏平,以兩種不同含義表達(dá)拢操, 這兩種表達(dá)就是其中一種對另一種的編碼,類似的有舶替,文字編碼成2進(jìn)制和明文編碼成密文令境,中文翻譯成英語也是一種語言翻譯成另一種語言。
二坎穿、字符集
在計算機里展父,不論何種語言的字符,都是以二進(jìn)制的形式保存玲昧、傳輸、交換的篮绿。這就牽扯到字符的編碼和解碼問題了:同樣含義的字符孵延,如何在人類理解的形狀這一形式與計算機內(nèi)部的二進(jìn)制形式之間做出對應(yīng)呢?
不過亲配,在回答這個問題之前尘应,還有一個更基本的問題需要解答:當(dāng)計算機遭遇字符惶凝,我們到底需要計算機表示哪些字符?
這就引出了字符集(Charset)的概念犬钢。通常來說苍鲜,字符集是一類字符按照一定方式編號排成的表格。比如玷犹,中國為漢字曾陸續(xù)制定了多個字符集:GB2312混滔、GBK、GB18030歹颓;其中 GBK 字符集收錄了 21886 個漢字和圖形符號坯屿。又例如,Unicode 對世界上大多數(shù)文字系統(tǒng)進(jìn)行了同一的整理和編碼巍扛,因此正在逐漸成為計算機領(lǐng)域內(nèi)的事實標(biāo)準(zhǔn)领跛。基于 Unicode 字符集撤奸,流行的字符集有 UTF-8吠昭、UTF-16、UTF-32 等胧瓜。
三怎诫、Unicode
正如上一節(jié)所說,世界上存在著多種編碼方式贷痪,同一個二進(jìn)制數(shù)字可以被解釋成不同的符號幻妓。因此,要想打開一個文本文件劫拢,就必須知道它的編碼方式肉津,否則用錯誤的編碼方式解讀,就會出現(xiàn)亂碼舱沧。為什么電子郵件常常出現(xiàn)亂碼妹沙?就是因為發(fā)信人和收信人使用的編碼方式不一樣。
可以想象熟吏,如果有一種編碼距糖,將世界上所有的符號都納入其中。每一個符號都給予一個獨一無二的編碼牵寺,那么亂碼問題就會消失悍引。這就是 Unicode,就像它的名字都表示的帽氓,這是一種所有符號的編碼趣斤。
Unicode 當(dāng)然是一個很大的集合,現(xiàn)在的規(guī)睦栊荩可以容納100多萬個符號浓领。每個符號的編碼都不一樣玉凯,比如,U+0639表示阿拉伯字母Ain联贩,U+0041表示英語的大寫字母A漫仆,U+4E25表示漢字嚴(yán)。具體的符號對應(yīng)表泪幌,可以查詢[unicode.org]盲厌,或者專門的[漢字對應(yīng)表]。
四座菠、Unicode 的問題
這個二進(jìn)制代碼應(yīng)該如何存儲狸眼。
比如,漢字嚴(yán)的 Unicode 是十六進(jìn)制數(shù)4E25浴滴,轉(zhuǎn)換成二進(jìn)制數(shù)足足有15位(100111000100101)拓萌,也就是說,這個符號的表示至少需要2個字節(jié)升略。表示其他更大的符號微王,可能需要3個字節(jié)或者4個字節(jié),甚至更多品嚣。
這里就有兩個嚴(yán)重的問題炕倘,第一個問題是,如何才能區(qū)別 Unicode 和 ASCII 翰撑?計算機怎么知道三個字節(jié)表示一個符號罩旋,而不是分別表示三個符號呢?第二個問題是眶诈,我們已經(jīng)知道涨醋,英文字母只用一個字節(jié)表示就夠了,如果 Unicode 統(tǒng)一規(guī)定逝撬,每個符號用三個或四個字節(jié)表示浴骂,那么每個英文字母前都必然有二到三個字節(jié)是0,這對于存儲來說是極大的浪費宪潮,文本文件的大小會因此大出二三倍溯警,這是無法接受的。
它們造成的結(jié)果是:1)出現(xiàn)了 Unicode 的多種存儲方式狡相,也就是說有許多種不同的二進(jìn)制格式梯轻,可以用來表示 Unicode。2)Unicode 在很長一段時間內(nèi)無法推廣谣光,直到互聯(lián)網(wǎng)的出現(xiàn)檩淋。
五、UTF-8 編碼
互聯(lián)網(wǎng)的普及萄金,強烈要求出現(xiàn)一種統(tǒng)一的編碼方式蟀悦。UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實現(xiàn)方式。其他實現(xiàn)方式還包括 UTF-16(字符用兩個字節(jié)或四個字節(jié)表示)和 UTF-32(字符用四個字節(jié)表示)氧敢,不過在互聯(lián)網(wǎng)上基本不用日戈。重復(fù)一遍,這里的關(guān)系是孙乖,UTF-8 是 Unicode 的實現(xiàn)方式之一浙炼。
UTF-8 最大的一個特點,就是它是一種變長的編碼方式唯袄。它可以使用1-4個字節(jié)表示一個符號弯屈,根據(jù)不同的符號而變化字節(jié)長度。
UTF-8 的編碼規(guī)則很簡單恋拷,只有二條:
1)對于單字節(jié)的符號资厉,字節(jié)的第一位設(shè)為0,后面7位為這個符號的 Unicode 碼蔬顾。因此對于英語字母宴偿,UTF-8 編碼和 ASCII 碼是相同的。
2)對于n字節(jié)的符號(n > 1)诀豁,第一個字節(jié)的前n位都設(shè)為1窄刘,第n + 1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10舷胜。剩下的沒有提及的二進(jìn)制位娩践,全部為這個符號的 Unicode 碼。
下表總結(jié)了編碼規(guī)則烹骨,字母x表示可用編碼的位翻伺。
Unicode符號范圍 | UTF-8編碼方式
(十六進(jìn)制) | (二進(jìn)制)
------------------+---------------------------------------------
'' 0000 0000-0000 007F | 0xxxxxxx
'' 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
'' 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
'' 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
跟據(jù)上表,解讀 UTF-8 編碼非常簡單展氓。如果一個字節(jié)的第一位是0穆趴,則這個字節(jié)單獨就是一個字符;如果第一位是1遇汞,則連續(xù)有多少個1未妹,就表示當(dāng)前字符占用多少個字節(jié)。
下面空入,還是以漢字嚴(yán)為例络它,演示如何實現(xiàn) UTF-8 編碼。
嚴(yán)的 Unicode 是4E25(100111000100101)歪赢,根據(jù)上表化戳,可以發(fā)現(xiàn)4E25處在第三行的范圍內(nèi)(0000 0800 - 0000 FFFF),因此嚴(yán)的 UTF-8 編碼需要三個字節(jié),即格式是1110xxxx 10xxxxxx 10xxxxxx点楼。然后扫尖,從嚴(yán)的最后一個二進(jìn)制位開始,依次從后向前填入格式中的x掠廓,多出的位補0换怖。這樣就得到了,嚴(yán)的 UTF-8 編碼是11100100 10111000 10100101蟀瞧,轉(zhuǎn)換成十六進(jìn)制就是E4B8A5沉颂。
六、Windows系統(tǒng)記事本編碼
曾經(jīng)有一個笑話悦污,把「聯(lián)通」兩個字寫在txt記事本上铸屉,保存再次打開后,“聯(lián)通”這兩個字就消失了切端。如果我沒記錯的話彻坛,還曾有好事者據(jù)此編排,認(rèn)定 Windows 背后的微軟和聯(lián)通有仇帆赢,故意不讓聯(lián)通二字正常顯示小压。
Windows 系統(tǒng)記事本里的「Unicode 編碼」實際上是「帶有 BOM 的小端序 UTF-16」。這意味著 Windows 將 Unicode 字符集和 UTF-16 劃上了等號椰于。這實際是不對的怠益。
七、Windows 記事本都做了什么
這里著重感謝 margen 對 Windows 記事本程序做的逆向工作瘾婿。沒有他的工作蜻牢,本文不至于這樣精彩。光榮屬于前輩偏陪!
保存的過程
根據(jù) [margen 的逆向分析]抢呆,在打開文件的過程中,記事本程序會調(diào)用 fDetermineFileType 來判斷文件的編碼類型笛谦。翻譯成 C 語言代碼抱虐,大致如下。饥脑,Windows 記事本在以 ANSI 保存文件時恳邀,沒有任何多余的動作,直接將 buffer 中的內(nèi)容通過 WriteFile 系統(tǒng)調(diào)用寫入到 txt 文件當(dāng)中灶轰。
我們以 010editor打開保存了「聯(lián)通」二字文件看看谣沸。
(img)
可以看到,在簡體中文 Windows 下笋颤,以記事本保存「聯(lián)通」兩個字乳附。那么保存得到的 txt 文件內(nèi),就僅有 0xC1AACDA8 這些內(nèi)容。而 0xC1AA 和 0xCDA8 正是「聯(lián)通」兩個字的 GBK 編碼赋除。
打開的過程
根據(jù) margen 的逆向分析阱缓,在打開文件的過程中,記事本程序會調(diào)用 fDetermineFileType 來判斷文件的編碼類型贤重。翻譯成 C 語言代碼茬祷,大致如下清焕。
int __stdcall fDetermineFileType(LPVOID lpBuffer,int cb)
{
int iType = 0;
WORD wSign = 0;
if( cb <= 1 ) return 0;
wSign = *(PWORD)lpBuffer;
switch( wSign )
{
case 0xBBEF:
{
if( cb >= 3 && (PBYTE)lpBuffer[3] == 0xBF) iType = 3;
}
break;
case 0xFEFF:
{
iType = 1;
}
break;
case 0xFFFE:
{
iType = 2;
}
break;
default:
{
if( !IsInputTextUnicode( lpBuffer, cb ) )
{
if( IsTextUTF8( lpBuffer, cb ) ) iType = 3;
}
else iType = 1;
}
}
return iType;
}
首先并蝗,代碼從文件頭部取出了前 2 個字節(jié),然后走 switch 分支判斷秸妥。
若前兩個字節(jié)是 0xBBEF滚停,且文件第三個字節(jié)是 0xBF,則組成 UTF-8 的 BOM(雖然 UTF-8 不需要)粥惧。那么據(jù)此判斷文件編碼是 UTF-8键畴。
若前兩個字節(jié)是 0xFEFF,那么這是(Big-Endian)大端序 UTF-16 的 BOM突雪。據(jù)此判斷文件編碼是(Windows 所謂的)Unicode Big-Endian編碼起惕。
若前兩個字節(jié)是 0xFFFE,那么這是小端序的 UTF-16 的 BOM咏删。據(jù)此判斷文件編碼是(Windows 所謂的)Unicode Little- Endian編碼惹想。因此字符 "Zero Width No-Break Space" (“零寬無間斷間隔”)又被稱作 BOM。
否則督函,則需要做更深層次的判斷嘀粱。注意到,iType 被初始化為 0辰狡,代表 ANSI 編碼(簡體中文下是 CP936锋叨,相當(dāng)于是 GBK 編碼)。若已走到了 default 分支宛篇,要函數(shù)返回 0娃磺,當(dāng)且僅當(dāng) IsTextUTF8( lpBuffer, cb ) 為 false 才行。然而叫倍,這個函數(shù)的寫法是這樣的偷卧。
否則,則需要做更深層次的判斷段标。注意到涯冠,iType 被初始化為 0,代表 ANSI 編碼(簡體中文下是 CP936逼庞,相當(dāng)于是 GBK 編碼)蛇更。若已走到了 default 分支,要函數(shù)返回 0,當(dāng)且僅當(dāng) IsTextUTF8( lpBuffer, cb ) 為 false 才行派任。然而砸逊,這個函數(shù)的寫法是這樣的。
BOOL IsTextUTF8( LPSTR lpBuffer, int iBufSize )
{
int iLeftBytes = 0;
BOOL bUtf8 = FALSE;
if( iBufSize <= 0 ) return FALSE;
for( int i=0;i<iBufSize;i++)
{
char c = lpBuffer[i];
if( c < 0 ) bUtf8 = TRUE;
if( iLeftBytes == 0 )
{
if( c >= 0 ) continue;
do
{
c <<= 1;
iLeftBytes++;
} while( c < 0 );
iLeftBytes--;
if( iLeftBytes == 0 ) return FALSE;
}
else
{
c &= 0xC0;
if( c != (char)0x80 ) return FALSE;
else iLeftBytes--;
}
}
if( iLeftBytes ) return FALSE;
return bUtf8;
}
我們重點看 for 循環(huán)內(nèi)部的邏輯掌逛。首先师逸,char c = lpBuffer[i]; 從 buffer 中取出一個字節(jié),保存在 signed char 當(dāng)中豆混。而后判斷 if( c < 0 )篓像。因為 c 是有符號的 char,所以 c < 0 意味著最高位是 1皿伺。這就意味著該字符肯定不是 ASCII 字符员辩,可能是一個 UTF-8 字符。因此將 bUtf8 置為 true鸵鸥。
而后奠滑,在 if( iLeftBytes == 0 ) 分支中,我們看到 c <<= 1; iLeftBytes++; 的 do-while 循環(huán)妒穴。這是在判斷 UTF-8 編碼的首字符中宋税,有多少個前綴的 1。根據(jù) UTF-8 的編碼規(guī)則讼油,這個數(shù)值就是該 UTF-8 字符的編碼長度杰赛,記錄在 iLeftBytes 當(dāng)中。
接下來汁讼,根據(jù) iLeftBytes 的大小淆攻,逐一檢查后續(xù)的字節(jié),是否以 10 開頭嘿架。一旦發(fā)現(xiàn)有不滿足條件的字節(jié)瓶珊,就能判定當(dāng)前文檔不是 UTF-8 編碼的∷时耄或是(在 for 循環(huán)結(jié)束之后)發(fā)現(xiàn) iLeftBytes 尚未自減到 0 就已經(jīng)到了文檔末尾伞芹,則也可以判定當(dāng)前文檔不是 UTF-8 編碼的。
也就是說蝉娜,這個函數(shù)的邏輯唱较,是根據(jù) UTF-8 編碼規(guī)則,全文掃描召川。若發(fā)現(xiàn)有一個字符不符合 UTF-8 的編碼規(guī)則南缓,則返回 false;否則若全文都符合 UTF-8 的編碼規(guī)則荧呐,則返回 true汉形。
八纸镊、「聯(lián)通」都經(jīng)歷了什么?
回過頭概疆,我們看到逗威,聯(lián)通二字以 ANSI(CP936)保存的 txt 文件里只有 0xC1AACDA8 這些內(nèi)容。因為無有 BOM岔冀,所以在 fDetermineFileType 函數(shù)中必然走到 default 分支凯旭,而后陷入 IsTextUTF8 函數(shù)當(dāng)中。
不巧的是使套,0xC1AA 和 0xCDA8 都符合 UTF-8 編碼的要求罐呼。因此該函數(shù)返回 true。于是童漩,Windows 記事本打開這一文件時弄贿,認(rèn)定這是一個無 BOM 的 UTF-8 編碼的文件。于是按照 UTF-8 編碼去解讀 0xC1AACDA8矫膨,那么就亂碼了。
九期奔、還有哪些字符
從前文的分析侧馅,我們可以得到結(jié)論:如果一個以 ANSI(CP936/GBK)保存的文檔,內(nèi)里包含的所有字符呐萌,都不幸滿足了 UTF-8 的編碼規(guī)則馁痴。那么這個文檔將被 Windows 記事本當(dāng)做是 UTF-8 編碼的文件打開,就會亂碼肺孤。
由于 GBK 是雙字節(jié)的編碼格式罗晕,只可能滿足 UTF-8 中對 U+0080 至 U+07FF 編碼的格式:110xxxxx, 10xxxxxx。我們可以將這些字符全都掃描輸出出來赠堵。以下是完成這一任務(wù)的 Python 代碼小渊。
pluses = map(lambda i:"+%s" % (hex(i)[2:].upper()), xrange(16))
headline = "%s%s" % (" " * 7, " ".join(pluses))
print headline
for i in xrange(192, 224):
high = hex(i)[2:].upper()
for j in xrange(4):
low = hex(128 + j * 16)[2:].upper()
chars = map(lambda k:(chr(i) + chr(128 + j * 16 + k)).decode("gbk"), xrange(16))
line = u"0x%s%s %s" % (high, low, " ".join(chars))
print line
得到的結(jié)果是:
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0xC080 纮 纴 纻 纼 绖 绤 绬 绹 缊 缐 缞 缷 缹 缻 缼 缽
0xC090 缾 缿 罀 罁 罃 罆 罇 罈 罉 罊 罋 罌 罍 罎 罏 罒
0xC0A0 罓 饋 愧 潰 坤 昆 捆 困 括 擴 廓 闊 垃 拉 喇 蠟
0xC0B0 臘 辣 啦 萊 來 賴 藍(lán) 婪 欄 攔 籃 闌 蘭 瀾 讕 攬
0xC180 羳 羴 羵 羶 羷 羺 羻 羾 翀 翂 翃 翄 翆 翇 翈 翉
0xC190 翋 翍 翏 翐 翑 習(xí) 翓 翖 翗 翙 翚 翛 翜 翝 翞 翢
0xC1A0 翣 痢 立 粒 瀝 隸 力 璃 哩 倆 聯(lián) 蓮 連 鐮 廉 憐
0xC1B0 漣 簾 斂 臉 鏈 戀 煉 練 糧 涼 梁 粱 良 兩 輛 量
0xC280 聙 聛 聜 聝 聞 聟 聠 聡 聢 聣 聤 聥 聦 聧 聨 聫
0xC290 聬 聭 聮 聯(lián) 聰 聲 聳 聴 聵 聶 職 聸 聹 聺 聻 聼
0xC2A0 聽 隆 壟 攏 隴 樓 婁 摟 簍 漏 陋 蘆 盧 顱 廬 爐
0xC2B0 擄 鹵 虜 魯 麓 碌 露 路 賂 鹿 潞 祿 錄 陸 戮 驢
0xC380 脌 脕 脗 脙 脛 脜 脝 脟 脠 脡 脢 脣 脤 脥 脦 脧
0xC390 脨 脩 脪 脫 脭 脮 脰 脳 脴 脵 脷 脹 脺 脻 脼 脽
0xC3A0 脿 謾 芒 茫 盲 氓 忙 莽 貓 茅 錨 毛 矛 鉚 卯 茂
0xC3B0 冒 帽 貌 貿(mào) 么 玫 枚 梅 酶 霉 煤 沒 眉 媒 鎂 每
0xC480 膧 膩 膫 膬 膭 膮 膯 膰 膱 膲 膴 膵 膶 膷 膸 膹
0xC490 膼 膽 膾 膿 臄 臅 臇 臈 臉 臋 臍 臎 臏 臐 臑 臒
0xC4A0 臓 摹 蘑 模 膜 磨 摩 魔 抹 末 莫 墨 默 沫 漠 寞
0xC4B0 陌 謀 牟 某 拇 牡 畝 姆 母 墓 暮 幕 募 慕 木 目
0xC580 艀 艁 艂 艃 艅 艆 艈 艊 艌 艍 艎 艐 艑 艒 艓 艔
0xC590 艕 艖 艗 艙 艛 艜 艝 艞 艠 艡 艢 艣 艤 艥 艦 艧
0xC5A0 艩 擰 濘 牛 扭 鈕 紐 膿 濃 農(nóng) 弄 奴 努 怒 女 暖
0xC5B0 虐 瘧 挪 懦 糯 諾 哦 歐 鷗 毆 藕 嘔 偶 漚 啪 趴
0xC680 苺 苼 苽 苾 苿 茀 茊 茋 茍 茐 茒 茓 茖 茘 茙 茝
0xC690 茞 茟 茠 茡 茢 茣 茤 茥 茦 茩 茪 茮 茰 茲 茷 茻
0xC6A0 茽 啤 脾 疲 皮 匹 痞 僻 屁 譬 篇 偏 片 騙 飄 漂
0xC6B0 瓢 票 撇 瞥 拼 頻 貧 品 聘 乒 坪 蘋 萍 平 憑 瓶
0xC780 莯 莵 莻 莾 莿 菂 菃 菄 菆 菈 菉 菋 菍 菎 菐 菑
0xC790 菒 菓 菕 菗 菙 菚 菛 菞 菢 菣 菤 菦 菧 菨 菫 菬
0xC7A0 菭 恰 洽 牽 扦 釬 鉛 千 遷 簽 仟 謙 乾 黔 錢 鉗
0xC7B0 前 潛 遣 淺 譴 塹 嵌 欠 歉 槍 嗆 腔 羌 墻 薔 強
0xC880 葊 葋 葌 葍 葎 葏 葐 葒 葓 葔 葕 葖 葘 葝 葞 葟
0xC890 葠 葢 葤 葥 葦 葧 葨 葪 葮 葯 葰 葲 葴 葷 葹 葻
0xC8A0 葼 取 娶 齲 趣 去 圈 顴 權(quán) 醛 泉 全 痊 拳 犬 券
0xC8B0 勸 缺 炔 瘸 卻 鵲 榷 確 雀 裙 群 然 燃 冉 染 瓤
0xC980 蓘 蓙 蓚 蓛 蓜 蓞 蓡 蓢 蓤 蓧 蓨 蓩 蓪 蓫 蓭 蓮
0xC990 蓯 蓱 蓲 蓳 蓴 蓵 蓶 蓷 蓸 蓹 蓺 蓻 蓽 蓾 蔀 蔁
0xC9A0 蔂 傘 散 桑 嗓 喪 搔 騷 掃 嫂 瑟 色 澀 森 僧 莎
0xC9B0 砂 殺 剎 沙 紗 傻 啥 煞 篩 曬 珊 苫 杉 山 刪 煽
0xCA80 蕗 蕘 蕚 蕛 蕜 蕝 蕟 蕠 蕡 蕢 蕣 蕥 蕦 蕧 蕩 蕪
0xCA90 蕫 蕬 蕭 蕮 蕯 蕰 蕱 蕳 蕵 蕶 蕷 蕸 蕼 蕽 蕿 薀
0xCAA0 薁 省 盛 剩 勝 圣 師 失 獅 施 濕 詩 尸 虱 十 石
0xCAB0 拾 時 什 食 蝕 實 識 史 矢 使 屎 駛 始 式 示 士
0xCB80 藔 藖 藗 藘 藙 藚 藛 藝 藞 藟 藠 藡 藢 藣 藥 藦
0xCB90 藧 藨 藪 藫 藬 藭 藮 藯 藰 藱 藲 藳 藴 藵 藶 藷
0xCBA0 藸 恕 刷 耍 摔 衰 甩 帥 栓 拴 霜 雙 爽 誰 水 睡
0xCBB0 稅 吮 瞬 順 舜 說 碩 朔 爍 斯 撕 嘶 思 私 司 絲
0xCC80 虁 虂 虃 虄 虅 虆 虇 虈 虉 虊 虋 虌 虒 虓 處 虖
0xCC90 虗 虘 虙 虛 虜 虝 號 虠 虡 虣 虤 虥 虦 虧 虨 虩
0xCCA0 虪 獺 撻 蹋 踏 胎 苔 抬 臺 泰 酞 太 態(tài) 汰 坍 攤
0xCCB0 貪 癱 灘 壇 檀 痰 潭 譚 談 坦 毯 袒 碳 探 嘆 炭
0xCD80 蛝 蛠 蛡 蛢 蛣 蛥 蛦 蛧 蛨 蛪 蛫 蛬 蛯 蛵 蛶 蛷
0xCD90 蛺 蛻 蛼 蛽 蛿 蜁 蜄 蜅 蜆 蜋 蜌 蜎 蜏 蜐 蜑 蜔
0xCDA0 蜖 汀 廷 停 亭 庭 挺 艇 通 桐 酮 瞳 同 銅 彤 童
0xCDB0 桶 捅 筒 統(tǒng) 痛 偷 投 頭 透 凸 禿 突 圖 徒 途 涂
0xCE80 蝷 蝸 蝹 蝺 蝿 螀 螁 螄 螆 螇 螉 螊 螌 螎 螏 螐
0xCE90 螑 螒 螔 螕 螖 螘 螙 螚 螛 螜 螝 螞 螠 螡 螢 螣
0xCEA0 螤 巍 微 危 韋 違 桅 圍 唯 惟 為 濰 維 葦 萎 委
0xCEB0 偉 偽 尾 緯 未 蔚 味 畏 胃 喂 魏 位 渭 謂 尉 慰
0xCF80 蟺 蟻 蟼 蟽 蟿 蠀 蠁 蠂 蠄 蠅 蠆 蠇 蠈 蠉 蠋 蠌
0xCF90 蠍 蠎 蠏 蠐 蠑 蠒 蠔 蠗 蠘 蠙 蠚 蠜 蠝 蠞 蠟 蠠
0xCFA0 蠣 稀 息 希 悉 膝 夕 惜 熄 烯 溪 汐 犀 檄 襲 席
0xCFB0 習(xí) 媳 喜 銑 洗 系 隙 戲 細(xì) 瞎 蝦 匣 霞 轄 暇 峽
0xD080 衻 衼 袀 袃 袆 袇 袉 袊 袌 袎 袏 袐 袑 袓 袔 袕
0xD090 袗 袘 袙 袚 袛 袝 袞 袟 袠 袡 袣 袥 袦 袧 袨 袩
0xD0A0 袪 小 孝 校 肖 嘯 笑 效 楔 些 歇 蝎 鞋 協(xié) 挾 攜
0xD0B0 邪 斜 脅 諧 寫 械 卸 蟹 懈 泄 瀉 謝 屑 薪 芯 鋅
0xD180 褉 褋 褌 褍 褎 褏 褑 褔 褕 褖 褗 褘 褜 褝 褞 褟
0xD190 褠 褢 褣 褤 褦 褧 褨 褩 褬 褭 褮 褯 褱 褲 褳 褵
0xD1A0 褷 選 癬 眩 絢 靴 薛 學(xué) 穴 雪 血 勛 熏 循 旬 詢
0xD1B0 尋 馴 巡 殉 汛 訓(xùn) 訊 遜 迅 壓 押 鴉 鴨 呀 丫 芽
0xD280 襽 襾 覀 覂 覄 覅 覇 覈 覉 覊 見 覌 覍 覎 規(guī) 覐
0xD290 覑 覒 覓 覔 覕 視 覗 覘 覙 覚 覛 覜 覝 覞 覟 覠
0xD2A0 覡 搖 堯 遙 窯 謠 姚 咬 舀 藥 要 耀 椰 噎 耶 爺
0xD2B0 野 冶 也 頁 掖 業(yè) 葉 曳 腋 夜 液 一 壹 醫(yī) 揖 銥
0xD380 觻 觼 觽 觾 觿 訁 訂 訃 訄 訅 訆 計 訉 訊 訋 訌
0xD390 訍 討 訏 訐 訑 訒 訓(xùn) 訔 訕 訖 託 記 訙 訚 訛 訜
0xD3A0 訝 印 英 櫻 嬰 鷹 應(yīng) 纓 瑩 螢 營 熒 蠅 迎 贏 盈
0xD3B0 影 穎 硬 映 喲 擁 傭 臃 癰 庸 雍 踴 蛹 詠 泳 涌
0xD480 詟 詠 詡 詢 詣 詤 詥 試 詧 詨 詩 詪 詫 詬 詭 詮
0xD490 詯 詰 話 該 詳 詴 詵 詶 詷 詸 詺 詻 詼 詽 詾 詿
0xD4A0 誀 浴 寓 裕 預(yù) 豫 馭 鴛 淵 冤 元 垣 袁 原 援 轅
0xD6A0 譅 幀 癥 鄭 證 芝 枝 支 吱 蜘 知 肢 脂 汁 之 織
0xD6B0 職 直 植 殖 執(zhí) 值 侄 址 指 止 趾 只 旨 紙 志 摯
0xD780 讇 讈 讉 變 讋 讌 讍 讎 讏 讐 讑 讒 讓 讔 讕 讖
0xD790 讗 讘 讙 讚 讛 讜 讝 讞 讟 讬 讱 讻 诇 诐 诪 谉
0xD7A0 谞 住 注 祝 駐 抓 爪 拽 專 磚 轉(zhuǎn) 撰 賺 篆 樁 莊
0xD7B0 裝 妝 撞 壯 狀 椎 錐 追 贅 墜 綴 諄 準(zhǔn) 捉 拙 卓
0xD880 貈 貋 貍 貎 貏 貐 貑 貒 貓 貕 貖 貗 貙 貚 貛 貜
0xD890 貝 貞 貟 負(fù) 財 貢 貣 貤 貥 貦 貧 貨 販 貪 貫 責(zé)
0xD8A0 貭 亍 丌 兀 丐 廿 卅 丕 亙 丞 鬲 孬 噩 丨 禺 丿
0xD8B0 匕 乇 夭 爻 卮 氐 囟 胤 馗 毓 睪 鼗 丶 亟 鼐 乜
0xD980 賭 賮 賯 賰 賱 賲 賳 賴 賵 賶 賷 賸 賹 賺 賻 購
0xD990 賽 賾 賿 贀 贁 贂 贃 贄 贅 贆 贇 贈 贉 贊 贋 贌
0xD9A0 贍 佟 佗 伲 伽 佶 佴 侑 侉 侃 侏 佾 佻 儕 佼 儂
0xD9B0 侔 儔 儼 儷 俅 俚 俁 俜 俑 俟 俸 倩 偌 俳 倬 倏
0xDA80 趢 趤 趥 趦 趧 趨 趩 趪 趫 趬 趭 趮 趯 趰 趲 趶
0xDA90 趷 趹 趻 趽 跀 跁 跂 跅 跇 跈 跉 跊 跍 跐 跒 跓
0xDAA0 跔 凇 冖 冢 冥 讠 訐 訌 訕 謳 詎 訥 詁 訶 詆 詔
0xDAB0 詘 詒 誆 誄 詿 詰 詼 詵 詬 詮 諍 諢 詡 誚 誥 誑
0xDB80 踿 蹃 蹅 蹆 蹌 蹍 蹎 蹏 蹐 蹓 蹔 蹕 蹖 蹗 蹘 蹚
0xDB90 蹛 蹜 蹝 蹞 蹟 蹠 蹡 蹢 蹣 蹤 蹥 蹧 蹨 蹪 蹫 蹮
0xDBA0 蹱 邸 邰 郟 郅 邾 鄶 郄 郇 鄆 酈 郢 郜 郗 郛 郫
0xDBB0 郯 郾 鄄 鄢 鄞 鄣 鄱 鄯 鄹 酃 酆 芻 奐 勱 劬 劭
0xDC80 軃 軄 軅 軆 軇 軈 軉 車 軋 軌 軍 軏 軐 軑 軒 軓
0xDC90 軔 軕 軖 軗 軘 軙 軚 軛 軜 軝 軞 軟 軠 軡 転 軣
0xDCA0 軤 堋 堍 埽 埭 堀 堞 堙 塄 堠 塥 塬 墁 墉 墚 墀
0xDCB0 馨 鼙 懿 艸 艽 艿 芏 芊 芨 芄 芎 芑 薌 芙 芫 蕓
0xDD80 輤 輥 輦 輧 輨 輩 輪 輫 輬 輭 輮 輯 輰 輱 輲 輳
0xDD90 輴 輵 輶 輷 輸 輹 輺 輻 輼 輽 輾 輿 轀 轁 轂 轃
0xDDA0 轄 蕁 茛 藎 荬 蓀 葒 荮 莰 荸 蒔 萵 莠 莪 莓 莜
0xDDB0 蒞 荼 薟 莩 荽 蕕 荻 莘 莞 莨 鶯 莼 菁 萁 菥 菘
0xDE80 迉 迊 迋 迌 迍 迏 迒 迖 迗 迚 迠 迡 迣 迧 迬 迯
0xDE90 迱 迲 迴 迵 迶 迺 迻 迼 迾 迿 逇 逈 逌 逎 逓 逕
0xDEA0 逘 蕖 蔻 蓿 蓼 蕙 蕈 蕨 蕤 蕞 蕺 瞢 蕃 蘄 蕻 薤
0xDEB0 薨 薇 薏 蕹 藪 薜 薅 薹 薷 薰 蘚 藁 藜 藿 蘧 蘅
0xDF80 還 邅 邆 邇 邉 邊 邌 邍 邎 邏 邐 邒 邔 邖 邘 邚
0xDF90 邜 邞 邟 邠 邤 邥 邧 邨 邩 邫 邭 邲 邷 邼 邽 邿
0xDFA0 郀 摺 擷 擼 撙 攛 搟 擐 擗 擤 擢 攉 攥 攮 弋 忒
0xDFB0 甙 弒 卟 叱 嘰 叩 叨 叻 吒 吖 吆 呋 嘸 囈 呔 嚦
若一個文檔里只包含這個表格中的漢字(可以再包含 ASCII 字符),在簡體中文 Windows 下在記事本中以 ANSI 編碼保存茫叭,則再次打開必然亂碼酬屉。特別地,這個表格本身也會亂碼揍愁。
據(jù)此呐萨,你可以構(gòu)造出各種跟微軟「有仇」的文檔。比如「聯(lián)通」莽囤,比如「小泉水」谬擦。
本文參考地址:
https://liam0205.me/2017/08/27/mojibake-in-Windows-Notepad-due-to-wrong-encoding-detect/
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html