- 論壇徽章:
- 0
|
本帖最后由 paktc 于 2013-12-31 18:04 編輯
去年的時(shí)候就看了網(wǎng)上有關(guān)的一些文章。但也就是臨時(shí)需要,臨時(shí)看看。
沒有去探索究竟是咋回事。最近又翻了不少文章,做了一個(gè)小小的總結(jié),結(jié)合了自己的觀點(diǎn)。
以下討論全部是基于windows xp平臺(tái)。
參考文章:
關(guān)于Perl對(duì)中文的處理問題
有了這篇文章我們知道以u(píng)tf-8形式保存的perl腳本,如何在屏幕上輸出我們想要的中文。
Perl Unicode全攻略
這篇就更詳細(xì)了,如何轉(zhuǎn)碼,有幾種方法,終端顯示、GUI的時(shí)候是以什么編碼輸出,應(yīng)有盡有
Perl如何創(chuàng)建一個(gè)UTF-8的文件
CSDN的一個(gè)問答貼(代碼見7樓、11樓)
在windows下讀取utf-8文本一定會(huì)遇到BOM的問題,于是下面幾個(gè)文章也少不了了:
UTF-8、BOM、<feff>的問題
「帶 BOM 的 UTF-8」和「無 BOM 的 UTF-8」有什么區(qū)別?
Windows 記事本的 ANSI、Unicode、UTF-8 這三種編碼模式有什么區(qū)別?
好了,資料那么多,其實(shí)都輪不到我說什么。做了幾種情況下的測(cè)試,在ANSI格式下保存的perl腳本
處理utf-8文本的時(shí)候遇到了不少頭痛的問題,最后自己做了一些總結(jié),一句話描述就是:
用ANSI格式保存的perl 如何正確顯示、讀取、生成 UTF-8格式的文本。
用"中文"兩個(gè)字作為示例,先做一個(gè)簡(jiǎn)單的解析,稍后作為參考:- use Encode;
- $text="中文";
- printf "“$text”一詞在三種狀態(tài)下的編碼數(shù)據(jù):\n";
- printf("%-25s","原GB2312編碼:");
- xcode($text,'x');
- printf("%-25s","根據(jù)其編碼信息,解碼為統(tǒng)一碼:");
- xcode(decode('gb2312',$text),'x');
- printf("%-25s","按UTF-8編碼:");
- xcode(encode('utf8',decode('gb2312',$text)),'x');
- print "\n";
- <STDIN>;
- #一個(gè)用來顯示編碼的函數(shù)
- sub xcode {
- # xcode("string",'Mode'); Mode = x(hex), b(bin), d(int)
- for my $v ( split(//,$_[0]) ) {
- print sprintf ("%l$_[1] ",ord($v));
- }
- print "\n" if (!defined $_[2]);
- }
復(fù)制代碼
“中文”一詞在三種狀態(tài)下的編碼數(shù)據(jù):
原GB2312編碼: d6 d0 ce c4
按GB2312解碼為統(tǒng)一碼: 4e2d 6587
按UTF-8編碼: e4 b8 ad e6 96 87
$data=decode('gb2312',$text) 對(duì) $text 解碼成 “統(tǒng)一碼” 到 $data (參考 http://zh.wikipedia.org/wiki/Unicode)
這個(gè)過程就像有一個(gè)八進(jìn)制的數(shù)字要轉(zhuǎn)為十六進(jìn)制,我們暫時(shí)先轉(zhuǎn)到十進(jìn)制,然后再轉(zhuǎn)十六進(jìn)制。
為什么不直接轉(zhuǎn)呢?只因?yàn)槲覀兿胍戎肋@個(gè)數(shù)在我們熟悉的形式是怎么樣的,讓我們有一個(gè)清楚的對(duì)照。
"寫"的操作 (腳本用ANSI文本形式保存)- use Encode;
- #生成utf-8文本
- #正確的方法1
- open WRT,">:utf8","UTF-8 1.txt";
- print WRT decode('gb2312',"中文"); #通過decode解碼為“統(tǒng)一碼”
- close WRT; #然后perl以:utf8形式寫入文本時(shí)幫我們將“統(tǒng)一碼”轉(zhuǎn)為UTF-8編碼
- #錯(cuò)誤示例
- open WRT,">:utf8","UTF8 ERR.txt";
- print WRT "中文"; #此時(shí)"中文"的編碼還是GB2312的形式
- close WRT; #perl將其當(dāng)做“中間數(shù)據(jù)”直接轉(zhuǎn)為utf8將得到錯(cuò)誤的結(jié)果
- #正確的方法2
- open WRT,">:raw","UTF8 2.txt";
- print WRT encode("utf-8",decode('gb2312',"中文")); #用:raw模式,直接以UTF-8編碼的形式寫入。
- close WRT;
復(fù)制代碼 用notepad打開三種方法輸出的文本顯示如下:
三種結(jié)果.jpg (19.22 KB, 下載次數(shù): 109)
下載附件
2013-12-30 20:40 上傳
也就是說,要讓perl輸出時(shí)做出正確的轉(zhuǎn)換,先要把數(shù)據(jù)轉(zhuǎn)化為 “通用” 的數(shù)據(jù)。
或者就干脆不要讓perl幫你做轉(zhuǎn)換,自己用函數(shù)編碼出正確的UTF-8格式的“中文”編碼,
并以:raw 形式寫入文本。
下面是讀取、在終端輸出的操作:(腳本以ANSI格式保存)
錯(cuò)誤的示例:- use Encode;
- open READ,"<:utf8","UTF-8 1.txt";
- $text=<READ>;
- print $text;
- close READ;
- <STDIN>;
復(fù)制代碼 原本的中文被顯示為:涓 枃 并提示wide character。
原因是perl用<:utf8 模式讀取的時(shí)候,分析了utf-8編碼并轉(zhuǎn)碼為“統(tǒng)一碼”:
0x4e2d 0x6587,在cmd終端上顯示需要再編碼為GB2312格式。把print $text 改
為 print encode('gb2312',$text);就可以顯示正確的結(jié)果
或者用<:raw模式讀入,得到的是UTF-8編碼的數(shù)據(jù),
先 decode('utf-8',$text) 轉(zhuǎn)到中間數(shù)據(jù) 然后再將返回的結(jié)果encode('gb2312', ... 并打印到終端
- use Encode;
- open READ,"<:raw","UTF-8 1.txt";
- $text=<READ>;
- print encode('gb2312',decode('utf-8',$text));
- close WRT;
- <STDIN>;
復(fù)制代碼 windows下讀取帶BOM(\xef\xbb\xbf 位于文件頭)的UTF-8文本
方法有幾種:
一、"<:raw"模式讀入文本數(shù)據(jù),去掉\xef\xbb\xbf 對(duì)剩下的數(shù)據(jù)轉(zhuǎn)碼。
二、用 <:utf8模式讀取(<:raw讀取后進(jìn)行decode也行) perl不會(huì)幫你去掉\xef\xbb\xbf
而是像對(duì)待所有文本一樣,對(duì)其轉(zhuǎn)碼,變成了\x{feff} ,這個(gè)時(shí)候去掉\xfe\xff 就是了。- use Encode;
- #第一種方法
- open FILE, "<:raw","UTF-8 with BOM.txt";
- $raw=<FILE>;
- $raw=~s/\xef\xbb\xbf//;
- print encode('gb2312',decode('utf-8',$raw));
- close FILE;
- #第二種方法A
- open FILE, "<:utf8","UTF-8 with BOM.txt";
- $data=<FILE>;
- $data=~s/\x{feff}//;
- print encode('gb2312',$data);
- close FILE;
- #第二種方法B
- open FILE, "<:raw","UTF-8 with BOM.txt";
- $raw=<FILE>;
- $data=decode('utf-8',$raw);
- $data=~s/\x{feff}//;
- print encode('gb2312',$data);
- close FILE;
- <STDIN>;
復(fù)制代碼 2013-12-30
補(bǔ)充,以上所說的“統(tǒng)一碼”,請(qǐng)參考 http://zh.wikipedia.org/wiki/Unicode
2013-12-31
讀windows下的unicode文本(UTF-16)
這里一定會(huì)遇到BOM,參考這篇文章:
Unicode簽名bom
所謂的unicode保存的文件實(shí)際上是utf-16,只不過恰好跟unicode的碼相同而已,
在概念上unicode與utf是兩回事,unicode是內(nèi)存編碼表示方案,而utf是如何保存和
傳輸unicode的方案。
示例文本unicode.txt(另存的時(shí)候選unicode)
第一行的編碼是:ff fe 2d 4e fd 56 36 52 20 90 d 0 a
第二行的編碼是:0 2c 7b 8c 4e 4c 88
(ff fe 就是文件頭,BOM)
decode('utf-16',$uni_str) 的時(shí)候和處理UTF-8的時(shí)候是不一樣的。它會(huì)幫你去掉BOM。
所以不需要手動(dòng)去掉\xFF\xFE ,在處理文本第二行的時(shí)候提示
UTF-16:Unrecognised BOM 2c …… 因?yàn)榈诙惺遣粠OM信息的,所以
把全文合并到一個(gè)變量中,做一次處理就可以得到正確的結(jié)果
|
|