||
背景:
别人用Win32::GUI 写了一个图形界面,其中要处理中文英文,中文乱码或者不匹配。
以前都是到网上随便搞个代码,能用就行,不是很了解其中的原理。
答应了帮助别人,就到网上查了所有的资料,
特别感谢 许伦大神写的这份文档
。
熟读了50遍,终于顿悟。
终结了一套方法:
1首先把所有的输入文件控制成utf-8格式。
2控制你的cmd终端的编码格式,
比如gbk,chcp 936
或者utf-8,chcp 65001
3知道你GUI界面上显示字符的编码
#这些内容时刻记住
在Perl看来, 字符串只有两种形式。一种是octets, 即8位序列, 也就是我们通常说的字节数组.另一种utf8编码的字符串, perl管它叫string。也就是说: Perl只认识两种编码:Ascii(octets)和utf8(string)。
正则匹配更好的支持utf8,所以我们要把字符串在perl内部都自动转换成utf8编码
怎么判断变量$searchitem2是utf8还是octets?
我又总结一套方法
my $flag;
$flag = utf8::is_utf8($searchitem2); # since Perl 5.8.1
print $flag,"item2ggg\n";
$flag = utf8::valid($searchitem2);
print $flag,"item2vv\n";
如果两个flag都是utf8则为utf8.
print length($searchitem2) . "^^^^^^^^^^\n";
#如果长度是汉字的个数则为utf8
########################################################
具体方法:
读取GUI中的字符到变量,然后把变量直接输出到cmd,如果显示正常就说明和cmd中的编码一致
#####################################################################################
具体分析参考我的demo.pl
关键代码
###################################
sub searchbutton_Click
{
my $content;
my $searchitem2 =$Window->textfield2->Text(); #汉 #不是utf8
my $old=$searchitem2;
# 这里的3个eval,可以告诉我们GUI中不是什么编码
eval {my $str2 = $searchitem2; Encode::decode("gbk", $str2, 1)};
print "not gbk: $@\n" if $@;
eval {my $str2 = $searchitem2; Encode::decode("big5", $str2, 1)};
print "not big5: $@\n" if $@;
eval {my $str2 = $searchitem2; Encode::decode("utf8", $str2, 1)};
print "not utf8: $@\n" if $@;
#知道不是utf-8编码
#然后我们可以把cmd设置成gbk编码,然后把print $searchitem2.可以正常显示,说明GUI中是GBK编码
$searchitem2 = Encode::decode("gbk", $searchitem2); #解码成utf8
print length($searchitem2) . "^^^^^^^^^^\n";
my $flag;
$flag = utf8::is_utf8($searchitem2); # since Perl 5.8.1
print $flag,"item2ggg\n";
$flag = utf8::valid($searchitem2);
print $flag,"item2vv\n";
open FH,"<:encoding(UTF-8)","$file" or die "can't know utf-8,please confirm utf-8";
#open FH,"$file" or die "can't know utf-8,please confirm utf-8";
while(<FH>)
{
#$_= decode("UTF-8", $_);#有些电脑默认是打开utf8的,有些是默认关闭的
$_=decode_utf8($_); #打开utf-8的文件会不会自动打开utf8的开关,如果打开就不需要这句话
#如果报错,cannot decode string with wide characters,提示我们重复decode
$flag = utf8::is_utf8($_); # since Perl 5.8.1
print $flag,"ggggggggg\n";
$flag = utf8::valid($_);
print $flag,"vvvvvvvvvv\n";
#如果这两个$flag 不是1,就说明是关的状态,需要开启。
if($_=~/$searchitem2/) #if($_=~/汉/) run ok
{
#在显示之前需要把它编码成终端支持的格式
$content = Encode::encode('gbk', $_);
$resutobj->{'-text'}.="$content ok\r\n";
}
else
{
#如果cmd终端是utf-8,可以直接打印utf8的。
#如果cmd终端是gbk,则需要先编码再打印
print $_;
#$resutobj->{'-text'}.= " $old fail\r\n"; #这里可以打印出来,说明是gbk编码
}
}
}
##########################################################
考虑是不是重复decode了。
Encode::_utf8_on($str); 开启utf8模式,不仅仅是on,需要确保正确解码,
具体转换方法如下
解决的方法很显然, 如果你的字符串本来不是utf8编码的, 应该先把它转成utf8编码, 并且使它的utf8 flag处于开启状态。
1
对于一个gb2312编码的字符串, 你可以使用
程序代码:
$str = Encode::decode("gb2312",$str);
来将其转化为utf8编码并开启utf8 flag。
2
如果你的字符串编码本来就是utf8,只是utf8 flag没有打开, 那么你可以使用以下三种方式中的任一种来开启utf8 flag:
程序代码:
$str = Encode::decode_utf8($str);
$str = Encode::decode("utf8",$str);
Encode::_utf8_on($str);
###########################################################
更多 精彩: http://blog.sciencenet.cn/home.php?mod=space&uid=950202
###########################################################
最好还有1点要注意
utf8不是utf-8
utf8是perl独特的编码,虽然和utf-8很像(可以在编码为utf-8的终端直接输出utf8的编码的内容)。
所以都要转成utf8,才能让perl处理。
$str 是utf-8编码的。需要转utf8,这样perl正则处理才好。
$str = Encode::decode_utf8($str);
好像显示乱码:
可以看我的word,
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-10-20 01:46
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社