`
kankan1218
  • 浏览: 277594 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Perl 的 utf8 与编码处理

    博客分类:
  • perl
阅读更多
 本文基于笔者查阅的 perldoc 和试验结果。鉴于经常有人被编码问题困扰,现笔者把所了解的关于 Perl utf8 与编码处理的资料总结一下。由于所知有限,可能会有讲错的地方,如有需要,可自行查阅:
perldoc Encode
perldoc PerlIO
perldoc utf8
perldoc encoding

下面用到这几个函数,能提供有用的帮助:
Encode::is_utf8($str)        # 当字符串 utf8 flag 为on时,返回真,否则返为假
utf8::is_utf8($str)        # 同上
Encode::_utf8_on($str)        # 手工设置 utf8 flag 为on
Encode::_utf8_off($str)        # 手工设置 utf8 flag 为off
PerlIO::get_layers(FP)        # 得到语柄的 layers
  

一. 基本概念
  Perl 以 ascii 方式或者 utf8 方式解释字符串,取决 Perl 字符串内部的 utf8 flag ,utf8 flag 影响着 Perl 对字符的定义。以下代码演示 utf8 flag 的影响:

   1. #!/bin/env perl
   2.

   3. # fileencoding: utf8
   4. # termencoding: gbk
   5.

   6. use strict;
   7. use warnings;
   8. use Encode;
   9. use Encode::CN;
  10.

  11. my $str = "中文字符串";
  12. &testing($str);
  13. Encode::_utf8_on($str);
  14. &testing($str);
  15.

  16. sub testing
  17. {
  18.         my ($str) = @_;
  19.         if (Encode::is_utf8($str))
  20.         {
  21.                 print "utf8: Yes\n";
  22.         }
  23.         else
  24.         {
  25.                 print "utf8: No\n";
  26.         }
  27.

  28.         print "Length: ", length($str), "\n";
  29.         while ($str =~ /(.)/g)
  30.         {
  31.                 print encode("gbk", $1), " ";
  32.         }
  33.

  34.         print "\n\n";
  35. }

复制代码
输出结果为:
utf8: No
Length: 15
? ? - ? ? ? ? - ? ? ? | ? ? 2

utf8: Yes
Length: 5
中 文 字 符 串

可以看到,当 utf8 flag 为 off 时,字符串按 ascii 处理;当为 on 时,则按 utf8 处理。注意 utf8 flag 跟字符串是否真为 utf8 编码无关,当字符串 utf8 flag 为 on 但非 utf8 编码时,print 会提示非法 utf8 字符。

二. Encode::encode ,Encode::decode ,PerlIO encoding layer
  当 decode(ENCODING, $str) 时,字符串被按 ENCODING 解码为 utf8 编码并设置 utf8 flag 为 on ;当 encode(ENCODING, $str) 时,字符串被从 utf8 编码重新编码为 ENCODING 并设置 utf8 flag 为 off ;假如原字符串为 utf8 编码,而 Encode::_utf8_on($str) ,Encode::_utf8_off($str) 分别和 $str = decode("utf8", $str) ,$str = encode("utf8", $str) 起的作用一致,但速度更快。
  可以给文件句柄加上 encoding(ENCODING) 的 layer ,则会在读入或者输出时自动处理。比如 open(FILE, "<+:encoding(gbk)", $location) 或者 binmode(FILE, ":encoding(gbk)") 时,则会在读入时自动调用 decode("gbk", ...) ,输出时自动调用 encode("gbk", ...) 。

三. use utf8 progma 与 use encoding ENCODING progma
  当 use utf8 时,脚本里的字符串,若包含非 ascii 字符,而自动设置字符串 utf8 flag 为 on :

   1. #!/bin/env perl
   2.

   3. # fileencoding: utf8
   4. # termencoding: gbk
   5.

   6. use strict;
   7. use warnings;
   8. use utf8;
   9.

  10. my $str = "abcd";
  11. my $str2 = "甲乙丙丁";
  12.

  13. foreach ($str, $str2)
  14. {
  15.         if (utf8::is_utf8($_))
  16.         {
  17.                 print "Yes\n";
  18.         }
  19.         else
  20.         {
  21.                 print "No\n";
  22.         }
  23. }

复制代码
输出结果为:
No
Yes

而 use encoding ENCODING 允许脚本为 ENCODING 编码而非一定为 utf8 编码。脚本里的字符串,自动按 ENCODING 转化为 utf8 编码并设置 utf8 flag 为 on ,就像自动调用了 decode(ENCODING, $str) 般,并自动给 STDIN 和 STDOUT 加上 encode(ENCODING) 的 layer :

   1. #!/bin/env perl
   2.

   3. # fileencoding: gbk
   4. # termencoding: gbk
   5.

   6. use strict;
   7. use warnings;
   8. use encoding "gbk";
   9.

  10. my $str = "abcd";
  11. my $str2 = "甲乙丙丁";
  12.

  13. foreach ($str, $str2)
  14. {
  15.         if (utf8::is_utf8($_))
  16.         {
  17.                 print "Yes\n";
  18.         }
  19.         else
  20.         {
  21.                 print "No\n";
  22.         }
  23. }
  24.

  25. print "\n";
  26. print STDOUT $str2, "\n";
  27. print STDERR $str2, "\n";
  28.

  29. print "\n";
  30. binmode(STDERR, ":encoding(gbk)");
  31.

  32. print STDOUT $str2, "\n";
  33. print STDERR $str2, "\n";

复制代码
输出结果为:
Yes
Yes

甲乙丙丁
Wide character in print at D:\test.pl line 26.
鐢蹭箼涓欎竵

甲乙丙丁
甲乙丙丁

$str 和 $str2 的 utf8 flag 都为 on,由于 STDERR 没有被自动设置 encoding(ENCODING) ,所以第一个 print STDERR 打印为乱码,造成那个 warning 的原因是,print 发现字符串里包含非 ascii 字符而且 utf8 flag 为真。


四. 使用 use utf8 和 use encoding ENCODING 的建议
1. 如果不很了解这两个 progma 起的作用,最好别用。
2. 在 tk 和 gtk 里,为了显示中文,手工的 decode(ENCODING, $text) 可能是更好的选择。
3. 使用 use encoding ENCODING 时,要注意字符串实际上是存为 utf8 格式的,比如这个代码,用来测试中文目录是否存在:

   1. #!/bin/env perl
   2.

   3. # fileencoding: gbk
   4. # termencoding: gbk
   5.

   6. use strict;
   7. use warnings;
   8. use encoding "gbk";
   9. use Encode;
  10.

  11. my $dir = "d:/备份数据/";
  12.

  13. if (-d encode("gbk", $dir))
  14. {
  15.         print "$dir 存在\n";
  16. }

复制代码
在这里,用 -d 测试 $dir 存在,手工的 encode 是必要的


该死的编码。。。。。。
分享到:
评论

相关推荐

    perl程序实现对UTF16编码的文件转换为utf8编码文件

    一些文件是uff16格式,虽然也是文本类型文件,但读取总是出现乱码,因此写了一个程序,可实现对UTF16编码的文件转换为utf8编码文件,请大家下载之前查清楚自己遇到的文件是否是utf16格式的.否则无效哦.使用方法请打开脚本...

    utf8 PERL语言编码测试

    PERL语言unicode转utf8, unicode转gb2312,中文转utf8,utf8转中文等测试代码

    GB2312-UTF-8编码批量转换

    当我们处理中文文本时,由于历史原因,可能会遇到GB2312或GBK编码的文件,而在互联网和现代软件中,UTF-8编码已成为主流。因此,进行"GBK-GB2312-UTF-8编码批量转换"是为了确保文本在不同系统和平台间能正确无误地...

    将汉字转为UTF8,支持文件转换格式

    "将汉字转为UTF8,支持文件转换格式"这个标题涉及到的关键知识点是字符编码的转换,特别是从GBK(或GB2312)编码到UTF-8编码的转换,以及批量文件处理。 UTF-8是一种广泛使用的Unicode字符编码,能够表示世界上几乎...

    gbk转utf-8批量转换

    2. **编写转换脚本**:对于熟悉编程的人来说,可以编写Python、Java、Perl等语言的脚本来批量读取GBK编码的文件,然后用UTF-8重新写入。Python的`codecs`库提供了方便的读写功能,如`codecs.open()`。 3. **使用...

    perl论坛程序CCB v20110627 简体中文 UTF8.zip

    久别的CCB Perl论坛,4年之后... 但旧的用户升级版继续提供GB2312 GBK编码升级包,同时为老用户提供GB2312 转utf8编码服务 5 提供了完整的mysql 接口,便于和其他系统连接 6 改进了总置顶功能,总置顶文章自动返回原页面

    如何处理UTF8格式的字符?

    在Perl编程语言中,处理UTF8格式的字符是一项常见的任务,因为UTF8是现代编码标准,广泛用于存储和传输多语言文本。以下是一份详细的指南,涵盖了如何在Perl中有效地处理UTF8字符。 首先,理解UTF8编码是关键。UTF8...

    cgi_form_utf8测试网页

    "cgi_form_utf8.html"这个文件很可能是用来测试Boa服务器处理UTF-8编码的CGI表单数据的能力。通过创建一个包含中文字符的表单,提交后由CGI程序处理并返回结果,观察是否出现乱码,以此检验服务器的编码处理是否正确...

    pcre-8.32.已编译的lib支持UTF8

    已编译的lib支持UTF8”指的是一个名为PCRE(Perl Compatible Regular Expressions)的库,版本为8.32,它已经被特别编译以支持UTF-8编码。PCRE是一个开源库,提供了正则表达式功能,广泛用于各种编程语言和应用中,...

    perl-Test-utf8

    Perl-Test-utf8 是一个Perl模块,专门用于在Perl测试脚本中处理和验证UTF-8编码的字符串。在Perl编程中,处理Unicode字符,尤其是UTF-8编码的字符,是一个常见但又可能出错的任务。这个模块提供了一套工具来确保你的...

    历史天气数据获取perl代码

    “输出文件编码utf8”意味着脚本生成的文件采用UTF-8编码,这是一种广泛支持的字符编码标准,可以正确处理全球多种语言的字符,确保数据的可读性不受限。 标签“历史天气”和“perl”进一步确认了代码的主题,它...

    perl_utf8_cheat_sheet

    `perl_utf8_cheat_sheet`是一个针对Perl中处理UTF-8编码的快速参考指南,包含了一系列实用示例。以下是对Perl和UTF-8在Perl中应用的详细解释: 1. **Perl与Unicode支持**: - Perl 5.8及以后的版本默认启用UTF-8...

    Perl_and_unicode_and_encode-源码.rar

    2. **Encode模块**:`Encode`是Perl中处理编码的核心模块,它允许我们声明字符串的外部编码(如ISO-8859-1或GBK),并将它们转换为内部的UTF-8格式。`decode`和`encode`函数是这个模块的核心,分别用于解码和编码...

    ActivePerl_5.16

    Perl 5.16引入了若干新特性,如新的字面量语法(如`say`函数,用于简化输出)、改进的正则表达式引擎以及对UTF-8编码更好的支持。此外,这个版本还优化了性能和稳定性,修复了许多已知的bug,提升了整体的编程体验。...

    perl论坛程序CCB v20110627 繁体中文 UTF8.zip

    久别的CCB Perl论坛,4年之后... 但旧的用户升级版继续提供GB2312 GBK编码升级包,同时为老用户提供GB2312 转utf8编码服务 5 提供了完整的mysql 接口,便于和其他系统连接 6 改进了总置顶功能,总置顶文章自动返回原页面

    记事本软件 还原 可以高亮显示各种语法 自定义语法高亮 支持ANSI,Unicode,UTF-8等编码互换

    2 支持ANSI,Unicode,UTF-8等编码互换 3 可以设置无限个书签(9种图标可换)轻松定位 4 空格,制表符彩色显示,并可互相转换 5 可以对任意的文本块进行操作,ALT键+鼠标 6 对括号{}〔〕()可以高亮配对...

    Perl用Post方法从新浪查天气

    此外,脚本还设置了标准输入、输出和错误流的编码格式为UTF-8,确保正确处理中文字符。 #### 二、核心逻辑 ##### 1. POST请求 - 定义了一个子程序 `do_POST`,该子程序接收URL、POST数据以及可选的HTTP头部作为...

    PERL 5.8.8

    1. **Unicode支持**:Perl 5.8.8引入了对Unicode的全面支持,允许开发者处理各种语言的字符集,包括非ASCII编码,如UTF-8。这使得Perl在处理全球化和多语言项目时更加灵活。 2. **正则表达式增强**:Perl 5.8.8的...

    中文转Unicode

    7. **文本分析与处理**:在自然语言处理(NLP)等领域,Unicode是处理中文文本的基础,如分词、词性标注、情感分析等。 了解和掌握中文转Unicode的原理及应用,对于进行跨平台的软件开发、网站设计以及处理多语言...

Global site tag (gtag.js) - Google Analytics