perl中字符串编码分析和注意事项

来源:互联网 发布:办公软件ppt教程 编辑:程序博客网 时间:2024/06/05 15:58

》在 Perl看来, 字符串只有两种形式. 一种是octets, 即8位序列, 也就是我们通常说的字节数组. 另一种utf8编码的字符串, perl管它叫string. 也就是说: Perl只熟悉两种编码: Ascii(octets)和utf8(string).

perl内部字符串由flag标志位和数据区两部分组成,其存储结构如下:

这里写图片描述

  1. 假如utf8 flag是On perl就会把数据区内容当成utf8字符串来处理;
  2. 假如utf8 flag是Off, perl就会把数据区内容当成octets来处理. 即字节来处理;

所有字符串相关的函数包括正则表达式、文件检测、都会受utf8 flag的影响。在默认情况下,utf8 flag标志位是off状态,当我们在代码中使用了 use utf8 ,则代表flag标志位是on状态,在当前词法范围内都是有效的。

Encode中的is_utf8函数可以用于检测当前flag开启情况,1代表on 0代表off;以下代码均是使用notepad++进行编码,字符编码格式选择UTF-8格式。


编码格式转换

若要进行不同编码之间的转换,可以使用Encode模块中的decode函数和encode函数,这两个函数使用如下

$octets = encode(ENCODING, STRING);
将标量字符串STRING从perl内部格式编码成ENCODING格式,并且返回字节流序列。

For example, to convert a string from Perl's internal format into ISO-8859-1:$octets = encode("iso-8859-1", $string);

$string = decode(ENCODING, OCTETS);
以ENCODING编码格式从字节流中解读字符信息,并转化为perl内部格式编码。

For example, to convert ISO-8859-1 data into a string in Perl's internal format:$string = decode("iso-8859-1", $octets);

下面展示gbk和utf8之间的相互转码,两种编码格式需要经过perl内部编码格式:

这里写图片描述

若待编码的字符串已经是perl内部编码格式(flag on +utf8编码),则可以直接进行编码或者解码,不需要按照上述的过程进行。

例子1:

use Encode;#当前关闭print "utf8 flag is 0ff\n" if !Encode::is_utf8($string1);my $string1 = "你好";//是utf8格式,若不编码屏幕输出乱码print Encode::encode("gbk",Encode::decode("utf8",$string1)),"\n";#flag是off状态,当作字节来处理,长度为6print "length:",length($string1),"\n";

运行结果:

这里写图片描述

例子2:

print "***********utf8 flag is on***************\n";#此后utf8 flag 为onuse utf8;my $string2 = "你好";#当前onprint "utf8 flag is on\n" if Encode::is_utf8($string2);#这里$string2相当于是内部格式了 flag is on and utf8 format#可以直接编码,不用先解码后编码了print Encode::encode("gbk",$string2),"\n";#当作string来处理,长度为2print "length:",length($string2),"\n\n\n\n";

运行结果:

这里写图片描述


注意事项

我们在使用perl中的文件测试符-e -s -f或者系统命令copy函数时,均要求这些函数的入参或者变量是gbk编码格式,否则会导致不符合预期的编码结果,举例如下:

我在目录下这个路径下创建了txt文件“E:\perl\文件夹1\log.txt”,不同的编码格式答案是不符合预期的。

例子3:

print "**********file test and system copy attentions**************\n";#文件测试或者调用系统copy函数等函数时 均需要使用gbk编码my $src1 = "E:\\perl\\文件夹1\\log.txt";my $src2 = "E:\\perl\\文件夹1\\log.txt";#$src2字符串flag标志位是on,并且本身是utf8编码,#因此$src2是perl内部格式,可以转为国标my $gbk_src = Encode::encode("gbk", $src2);print "gbk encode:$gbk_src\n";#文件存在 则打印if (-e $gbk_src){    print "it exists\n";}#文件不存在 则打印unless (-e $src){    print "it don't exist\n";}

运行结果:

这里写图片描述

字符串来源

为了能够正确的进行字符串编解码, 我们首先要知道字符串本来的编码和utf8 flag开关情况, 这里我们讨论几种情况.

  1. 命令行参数和标准输入. 从命令行参数或标准输入(STDIN)来的字符串, 它的编码跟locale有关. 假如你的locale是zh_CN或zh_CN.gb2312, 那么进来的字符串就是gb2312编码, 假如你的locale是zh_CN.gbk, 那么进来的编码就是gbk, 假如你的编码是zh_CN.UTF8, 那进来的编码就是utf8. 不管是什么编码, 进来的字符串的utf8 flag都是关闭的状态.
  2. 你的源代码里的字符串. 这要看你编写源代码时用的是什么编码. 在editplus里, 你可以通过”文件”->”另存为”查看和更改编码. 在linux下, 你可以cat一个源代码文件, 假如中文正常显示, 说明源代码的编码跟locale是一致的. 源代码里的字符串的utf8 flag同样是关闭的状态.
    假如你的源代码里含有中文, 那么你最好遵循这个原则: 1) 编写代码时使用utf8编码, 2)在文件的开头加上use utf8;语句. 这样, 你源代码里的字符串就都会是utf8编码的, 并且utf8 flag也已经打开.
  3. 从文件读入. 这个毫无疑问, 你的文件是什么编码, 读进来就是什么编码了. 读进来以后, utf8 flag是off状态.
  4. 抓取网页. 网页是什么编码就是什么编码, utf8 flag是off状态. 网站的编码可以从响应头里或者html

参考入下资料:
http://blog.csdn.net/c_base_jin/article/details/78768591

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 au没有波形 没有声音怎么办 屏幕驱动板坏了怎么办 安吉星流量超了怎么办 网络被伪基站覆盖怎么办 骨头渣子卡嗓子里怎么办 执法仪记录仪关不了机怎么办 执法记录仪开不了机怎么办 华为警务通丢了怎么办 华德安执法记录仪死机怎么办 行车仪内存满了怎么办 海康威视摄像头没有通道怎么办 电脑屏膜变大了怎么办 手机2g模块坏了怎么办 腾讯大王卡是2g怎么办 华为手机4g坏了怎么办 优盘中毒打不开怎么办 vr头戴链接不起怎么办 人在缺氧的时候怎么办 脑缺氧供血不足怎么办 睡多了大脑缺氧怎么办 吃了过期的东西怎么办 吃了过期的牛肉怎么办 生存战争肉腐烂了怎么办? 家里进了蝙蝠找不到了怎么办 方舟手游恐龙找不到了怎么办 这是我的战争怎么办 小孩吃坏东西呕吐发烧怎么办 睿芽密码忘了怎么办 做绿豆糕太稀了怎么办 自热火锅吃完后怎么办 自煮火锅吃完了怎么办 自热火锅没熟怎么办 厕所被米饭堵了怎么办 减完肥肉特别松怎么办 新开的熟食店没人光顾怎么办 吃剩的软炸里脊怎么办 小火锅加热时胀盒该怎么办 天丝面料容易皱怎么办 快递员拒不送件怎么办 鞋店里面买到假鞋子了怎么办 孕吐伤了胃疼怎么办