亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 25102 | 回復(fù): 9
打印 上一主題 下一主題

【分享】Perl讀取和生成、顯示UTF-8文本、UTF-16文本 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2013-12-30 21:44 |只看該作者 |倒序?yàn)g覽
本帖最后由 paktc 于 2013-12-31 18:04 編輯

    去年的時(shí)候就看了網(wǎng)上有關(guān)的一些文章。但也就是臨時(shí)需要,臨時(shí)看看。
沒有去探索究竟是咋回事。最近又翻了不少文章,做了一個(gè)小小的總結(jié),結(jié)合了自己的觀點(diǎn)。
以下討論全部是基于windows xp平臺(tái)。

參考文章:
關(guān)于Perl對(duì)中文的處理問題
有了這篇文章我們知道以u(píng)tf-8形式保存的perl腳本,如何在屏幕上輸出我們想要的中文。

Perl Unicode全攻略
這篇就更詳細(xì)了,如何轉(zhuǎn)碼,有幾種方法,終端顯示、GUI的時(shí)候是以什么編碼輸出,應(yīng)有盡有

Perl如何創(chuàng)建一個(gè)UTF-8的文件
CSDN的一個(gè)問答貼(代碼見7樓、11樓)

在windows下讀取utf-8文本一定會(huì)遇到BOM的問題,于是下面幾個(gè)文章也少不了了:
UTF-8、BOM、<feff>的問題
「帶 BOM 的 UTF-8」和「無 BOM 的 UTF-8」有什么區(qū)別?
Windows 記事本的 ANSI、Unicode、UTF-8 這三種編碼模式有什么區(qū)別?

     好了,資料那么多,其實(shí)都輪不到我說什么。做了幾種情況下的測(cè)試,在ANSI格式下保存的perl腳本
處理utf-8文本的時(shí)候遇到了不少頭痛的問題,最后自己做了一些總結(jié),一句話描述就是:
用ANSI格式保存的perl 如何正確顯示、讀取、生成 UTF-8格式的文本。

用"中文"兩個(gè)字作為示例,先做一個(gè)簡(jiǎn)單的解析,稍后作為參考:
  1. use Encode;
  2. $text="中文";
  3. printf "“$text”一詞在三種狀態(tài)下的編碼數(shù)據(jù):\n";
  4. printf("%-25s","原GB2312編碼:");
  5. xcode($text,'x');
  6. printf("%-25s","根據(jù)其編碼信息,解碼為統(tǒng)一碼:");
  7. xcode(decode('gb2312',$text),'x');
  8. printf("%-25s","按UTF-8編碼:");
  9. xcode(encode('utf8',decode('gb2312',$text)),'x');
  10. print "\n";
  11. <STDIN>;

  12. #一個(gè)用來顯示編碼的函數(shù)
  13. sub xcode {
  14.         # xcode("string",'Mode'); Mode = x(hex), b(bin), d(int)
  15.         for my $v ( split(//,$_[0]) ) {
  16.                 print sprintf ("%l$_[1] ",ord($v));        
  17.         }
  18.         print "\n" if (!defined $_[2]);
  19. }

復(fù)制代碼

“中文”一詞在三種狀態(tài)下的編碼數(shù)據(jù):
原GB2312編碼:            d6 d0 ce c4
按GB2312解碼為統(tǒng)一碼:    4e2d 6587
按UTF-8編碼:             e4 b8 ad e6 96 87


$data=decode('gb2312',$text) 對(duì) $text 解碼成 “統(tǒng)一碼” 到 $data (參考 http://zh.wikipedia.org/wiki/Unicode
這個(gè)過程就像有一個(gè)八進(jìn)制的數(shù)字要轉(zhuǎn)為十六進(jìn)制,我們暫時(shí)先轉(zhuǎn)到十進(jìn)制,然后再轉(zhuǎn)十六進(jìn)制。
為什么不直接轉(zhuǎn)呢?只因?yàn)槲覀兿胍戎肋@個(gè)數(shù)在我們熟悉的形式是怎么樣的,讓我們有一個(gè)清楚的對(duì)照。

"寫"的操作
(腳本用ANSI文本形式保存)
  1. use Encode;
  2. #生成utf-8文本

  3. #正確的方法1
  4. open WRT,">:utf8","UTF-8 1.txt";
  5. print WRT decode('gb2312',"中文");  #通過decode解碼為“統(tǒng)一碼”
  6. close WRT;                             #然后perl以:utf8形式寫入文本時(shí)幫我們將“統(tǒng)一碼”轉(zhuǎn)為UTF-8編碼

  7. #錯(cuò)誤示例
  8. open WRT,">:utf8","UTF8 ERR.txt";
  9. print WRT "中文";                   #此時(shí)"中文"的編碼還是GB2312的形式
  10. close WRT;                          #perl將其當(dāng)做“中間數(shù)據(jù)”直接轉(zhuǎn)為utf8將得到錯(cuò)誤的結(jié)果

  11. #正確的方法2
  12. open WRT,">:raw","UTF8 2.txt";
  13. print WRT encode("utf-8",decode('gb2312',"中文"));  #用:raw模式,直接以UTF-8編碼的形式寫入。
  14. close WRT;
復(fù)制代碼
用notepad打開三種方法輸出的文本顯示如下:


    也就是說,要讓perl輸出時(shí)做出正確的轉(zhuǎn)換,先要把數(shù)據(jù)轉(zhuǎn)化為 “通用” 的數(shù)據(jù)。
或者就干脆不要讓perl幫你做轉(zhuǎn)換,自己用函數(shù)編碼出正確的UTF-8格式的“中文”編碼,
并以:raw 形式寫入文本。

下面是讀取、在終端輸出的操作:(腳本以ANSI格式保存)
錯(cuò)誤的示例:
  1. use Encode;

  2. open READ,"<:utf8","UTF-8 1.txt";
  3. $text=<READ>;
  4. print $text;
  5. close READ;
  6. <STDIN>;
復(fù)制代碼
原本的中文被顯示為:涓 枃 并提示wide character。
      原因是perl用<:utf8 模式讀取的時(shí)候,分析了utf-8編碼并轉(zhuǎn)碼為“統(tǒng)一碼”:
0x4e2d 0x6587,在cmd終端上顯示需要再編碼為GB2312格式。把print $text 改
為 print encode('gb2312',$text);就可以顯示正確的結(jié)果

      或者用<:raw模式讀入,得到的是UTF-8編碼的數(shù)據(jù),
先 decode('utf-8',$text) 轉(zhuǎn)到中間數(shù)據(jù)  然后再將返回的結(jié)果encode('gb2312', ... 并打印到終端

  1. use Encode;

  2. open READ,"<:raw","UTF-8 1.txt";
  3. $text=<READ>;
  4. print encode('gb2312',decode('utf-8',$text));
  5. close WRT;
  6. <STDIN>;
復(fù)制代碼
windows下讀取帶BOM(\xef\xbb\xbf 位于文件頭)的UTF-8文本
方法有幾種:
一、"<:raw"模式讀入文本數(shù)據(jù),去掉\xef\xbb\xbf 對(duì)剩下的數(shù)據(jù)轉(zhuǎn)碼。
二、用 <:utf8模式讀取(<:raw讀取后進(jìn)行decode也行) perl不會(huì)幫你去掉\xef\xbb\xbf
而是像對(duì)待所有文本一樣,對(duì)其轉(zhuǎn)碼,變成了\x{feff} ,這個(gè)時(shí)候去掉\xfe\xff 就是了。
  1. use Encode;

  2. #第一種方法
  3. open FILE, "<:raw","UTF-8 with BOM.txt";
  4. $raw=<FILE>;
  5. $raw=~s/\xef\xbb\xbf//;
  6. print encode('gb2312',decode('utf-8',$raw));
  7. close FILE;

  8. #第二種方法A
  9. open FILE, "<:utf8","UTF-8 with BOM.txt";
  10. $data=<FILE>;
  11. $data=~s/\x{feff}//;
  12. print encode('gb2312',$data);
  13. close FILE;

  14. #第二種方法B
  15. open FILE, "<:raw","UTF-8 with BOM.txt";
  16. $raw=<FILE>;
  17. $data=decode('utf-8',$raw);
  18. $data=~s/\x{feff}//;
  19. print encode('gb2312',$data);
  20. close FILE;
  21. <STDIN>;
復(fù)制代碼
2013-12-30
補(bǔ)充,以上所說的“統(tǒng)一碼”,請(qǐng)參考 http://zh.wikipedia.org/wiki/Unicode

2013-12-31
讀windows下的unicode文本(UTF-16)
這里一定會(huì)遇到BOM,參考這篇文章:
Unicode簽名bom
         所謂的unicode保存的文件實(shí)際上是utf-16,只不過恰好跟unicode的碼相同而已,
    在概念上unicode與utf是兩回事,unicode是內(nèi)存編碼表示方案,而utf是如何保存和
    傳輸unicode的方案。

示例文本unicode.txt(另存的時(shí)候選unicode)
  • 中國(guó)制造
  • 第二行


第一行的編碼是:ff fe 2d 4e fd 56 36 52 20 90 d 0 a   
第二行的編碼是:0 2c 7b 8c 4e 4c 88
(ff fe 就是文件頭,BOM)

decode('utf-16',$uni_str) 的時(shí)候和處理UTF-8的時(shí)候是不一樣的。它會(huì)幫你去掉BOM。
所以不需要手動(dòng)去掉\xFF\xFE ,在處理文本第二行的時(shí)候提示
UTF-16:Unrecognised BOM 2c ……   因?yàn)榈诙惺遣粠OM信息的,所以
把全文合并到一個(gè)變量中,做一次處理就可以得到正確的結(jié)果



論壇徽章:
3
CU十二周年紀(jì)念徽章
日期:2013-10-24 15:41:34子鼠
日期:2013-12-14 14:57:19射手座
日期:2014-04-25 21:23:23
2 [報(bào)告]
發(fā)表于 2013-12-30 21:53 |只看該作者
這個(gè)不錯(cuò)  支持下

論壇徽章:
2
射手座
日期:2014-10-10 15:59:4715-16賽季CBA聯(lián)賽之上海
日期:2016-03-03 10:27:14
3 [報(bào)告]
發(fā)表于 2013-12-31 08:49 |只看該作者
Mark~                                    

論壇徽章:
1
雙子座
日期:2013-11-06 17:18:01
4 [報(bào)告]
發(fā)表于 2013-12-31 09:09 |只看該作者
支持一下。

論壇徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午馬
日期:2014-08-06 03:56:58
5 [報(bào)告]
發(fā)表于 2013-12-31 15:03 |只看該作者
支持 {:2_172:}

論壇徽章:
0
6 [報(bào)告]
發(fā)表于 2013-12-31 20:47 |只看該作者
本帖最后由 paktc 于 2013-12-31 22:01 編輯

這里咨詢大家一個(gè)問題,
在嘗試寫UTF-16BE文本的時(shí)候,\r\n 寫入文本后,編碼總是不正確。
其他字符比如 tab 都正常,這個(gè)問題如何解決?

代碼保存為ANSI格式
  1. use Encode;
  2. open WRT,'>:encoding(utf-16)','encoding[utf-16].txt' or die "$!";
  3. print WRT decode('gb2312',"中        文\r\n");      # 1
  4. close WRT;
復(fù)制代碼
好像是activeperl的問題?在ubuntu寫了個(gè)腳本(用utf-8格式保存的),

  1. #!/usr/bin/perl -s
  2. use Encode;
  3. chdir "~/桌面";
  4. open WRT,">encoding(UTF-16):crlf","new.x";
  5. print WRT decode('utf-8',"中文\n");
  6. close WRT;
復(fù)制代碼
生成的txt文件復(fù)制到windows查看,換行正常。
同樣的腳本復(fù)制到windows執(zhí)行,行尾就變成了兩個(gè)黑色符號(hào)。
……

Using :encoding and :crlf together?
The :crlf PerlIO layer doesn't like the :encoding layer.

在這里找到了最終答案 關(guān)鍵詞 "perl  write utf-16 text crlf"
Writing a Unicode file via perl ...
http://blogs.msdn.com/b/brettsh/archive/2006/06/07/620986.aspx

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2019-03-08 10:03 |只看該作者
留個(gè)記號(hào),備用。
雖然用處理過許多中文文件,但有些東西記不住,經(jīng)常折騰好半天才解決。

論壇徽章:
0
8 [報(bào)告]
發(fā)表于 2019-05-06 00:01 |只看該作者
支持一下。
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP