分类: WINDOWS
2007-05-17 16:24:40
今天处理perl的中文字符处理,发现了有如下现象.
1. 源文件中直接引用的字符,那么将按照文本本来的存储方式存储,比如 ex.pl 文件中定义了
my $val = "新建文件夹";
而ex.pl 被存储为ANSI格式. 那么 "新建文件夹"也是以此种方式编码.
这样的话,UTF-8,unicode等也可类推.
2. 源文件中读入的字符. 比如
my $val =
那么将依赖于当前所处于的 编码方式,如果是936 codepage也就是简体中文.
那么val将存储为cp936 方式.gbk/gb2312.
3. use utf8; 选项
此选项表示此作用域下的字符串,perl在内部以utf8进行存储,因此在此种情况下,
my $val = "新建文件夹"; 有可能导致问题,如果ex.pl以utf8不兼容格式存储,比如多字节存储 。
4. 默认console的输入得到的是什么? 我在调试中发现,实际上选择默认,或者所谓的ANSI来存储中文,
实际上是以多字节MBCS来进行存储,也就是说以当前codepage的编码方式来存储的.
5. 今天碰到的问题就是
open my $fh, '>:encoding(utf-8)', $filename or die "open($filename): $!";
XMLout($data, OutputFile => $fh , RootName => "component" , XMLDecl => "");
close($fh);
为什么将中文写出了乱码?
这个实际上是 >:encoding(utf-8)的实现不是我们所想的执行了类似Encode::from_to($val,"cp936","utf8") or die "error"; 从结果看,似乎是将每个自己都扩展了一倍,比如 0xd0 => 0xd0 0x00 .这样C936的编码,就变得乱七八糟.
6. perl内部存储格式和直接utf-8格式的区别.
perl的内部格式是以unicde形式存储的. 而utf-8还是以字节流形式存在的. 看下面的例子.
$str = utf8("骆驼"); # 假设文件是以utf-8存储的
print length($str) ; 将会 = 6 ,因为utf-8编码的字节流就是6个字节
$str= decode("utf-8",$str); # perl内部格式,unicode,
print length($str); # = 2
{
use bytes;
print length($str); # 6 字节流形式
}
7. unicode::string 的用法.
此包,能够将指定的输入字符转化为其它表述格式.
$u = utf8("骆驼"); # 文件以utf-8存储
print length($u->utf8); # 6
2007-07-26
假如 open $fh , <:encoding(utf-8)",$filename 这种方式,那么不需要在
$line = <$fh> 后使用$line = decode ("utf-8",$line); 否则需要decoding.
也就是说在打开文件的时候如果指定格式,那么perl将自动帮你将读入的格式转换为内部格式.
另外带有格式的文件往往开头有bom字节,比如一个文件开始
to : ,那么使用
$line =~ m/\s*to/i ; 是无法匹配的,需要用
$line =~ m/\W*to/i ; 来匹配,也就是说允许to之前出任意个不可见字符.
假如你已经知道了当前的字符串格式是perl的内部格式,那么如果你要打印到目前的console上,比如console是 cp936的,那么打印就是出现乱码.
这种情况下:
$internaldata;
$cp936data = encode("cp936" , $internaldata);
print $cp936data,"\n";
这样就能够显示正确的中文.