用perl寫(xiě)文本處理程序,或者寫(xiě)服務(wù)器端腳本的時(shí)候,常常會(huì )遇到“Wide character in print”的警告或者錯誤。
這是因為在程序中處理中文等寬字符時(shí),perl不能識別要處理的內容。
首先要知道perl只能處理兩種編碼:ascii碼和utf-8。ascii碼是很少的,像中文、日文、韓文等字符要想能被perl處理,只能用utf-8編碼方式。字符串在perl內部的存儲格式如下圖:
當flag是1的時(shí)候,perl就會(huì )把那個(gè)字符串當做utf-8編碼的字符來(lái)處理;如果是0,perl就不能認知字符串中除了ascii碼之外的字符,這個(gè)時(shí)候,就會(huì )報出“Wide character in print”的警告或者錯誤。
舉個(gè)例子,你要在程序中處理‘當歷史成為歷史’這個(gè)字符串,如果你的程序文件是utf-8編碼的話(huà),一般情況下直接處理就行了,因為這時(shí)字符串的utf8-flag是打開(kāi)的。如果你的程序文件是gb2312的話(huà),那么你就需要把那個(gè)字符串的utf8-flag打開(kāi)。但是,一般還會(huì )有這樣的問(wèn)題,因為這個(gè)字符串是gb2312編碼的,所以你要做兩件事情:將字符串的編碼轉為utf-8和打開(kāi)utf8-flag。
use Encode;
use strict;
my $str = "當歷史成為歷史";
Encode::_utf8_on($str);
print $str. "\n";
Encode::_utf8_off($str);
print $str. "\n";
將上面的這段程序存到文件里,試圖運行的時(shí)候就會(huì )報錯:Wide character in print at test.pl line 6。這就是因為utf8-flag被關(guān)閉,perl不能識別字符串。
當然,在每個(gè)處理寬字符的地方加上Encode::_utf8_on函數確實(shí)是個(gè)解決辦法。但是一般來(lái)說(shuō),在每個(gè)地方都加上這樣的函數,既在編寫(xiě)程序的時(shí)候麻煩,維護的時(shí)候更麻煩。
這里還有一個(gè)更好的辦法:在程序文件的頭部加上以下內容
use utf8;
binmode(STDIN, ':encoding(utf8)');
binmode(STDOUT, ':encoding(utf8)');
binmode(STDERR, ':encoding(utf8)');