[分享] 解壓縮zip檔,產生亂碼,如何解決的心得 [論壇 - Ubuntu 與工具程式及軟體推薦]


正在瀏覽:   1 名遊客


 到底部   前一個主題   下一個主題  [無發表權] 請登錄或者註冊

(1) 2 »


[分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 905
MP : 679 / 30217
EXP: 23
離線
統整連結

============================================


這一篇的內容是從「這一篇」分出來的。

用意,是要給未來遇到相同問題的人,有一個方向,可以去解決。
解法主要來自於「這一頁」的步驟。只是加上範例,和指令的步驟,以利學習。
若有其他的方式,也請踴躍分享,感恩不盡。

以下是我測試成功的範例。測試環境是 「xubuntu 14.04 64 位元 英文界面」。

注意: 以下的解法,是假設裡面的檔名是有「Big5」編碼的狀況下,若同時還有其他的編碼的檔案,我就不確定是否會正常,沒測試過 :p

## 範例

依照「這一頁」,選擇下載 TXT,當作範例。

參考「這一頁」的步驟。

## 下載範例檔案

```
wget -c "http://data.gov.tw/iisi/logaccess/20?dataUrl=http://www.cns11643.gov.tw/AIDB/Open_Data.zip&ndctype=TXT&ndcnid=5961" -O Open_Data.zip
```

上面的指令應該可以改成,參考「這一頁的說明」。

```
$ wget -c "http://www.cns11643.gov.tw/AIDB/Open_Data.zip" -O Open_Data.zip
```

## 先用7-zip解壓縮。
```sh
$ env LC_ALL=C 7z x Open_Data.zip
```

## 使用convmv預覽轉換結果
```sh
$ convmv -f BIG5 -t UTF-8 -r Open_Data
```

## 使用convmv轉換
```sh
$ convmv -f BIG5 -t UTF-8 -r Open_Data --notest
```

## 簡單的觀看轉換後結果是否可以正常看到中文字,而不是亂碼。
```sh
$ ls Open_Data/MapingTables
```


## 後記(2016-08-30)

後來在重新看下面我自己「回覆#4」貼的「一篇文章」,
該篇文章底下有一個回覆提到一個「unzip」指令的下法,
剛在「Xbuntu 16.04」測試下面的指令,是可以成功的。

執行


$ unzip -O big5 Open_Data.zip



執行下面指令


$ unzip



就可以看到用法


UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

...略...

modifiers:

-O CHARSET specify a character encoding for DOS, Windows and OS/2 archives
-I CHARSET specify a character encoding for UNIX and other archives

...略...





剛又使用「unzip big5」再重新查詢一下,發現「這篇」,「這篇」,「這篇」,「這篇」,「這篇」都有提到相關的用法。

然後查到這個論壇更早之前也有相關的「討論

convmv」的用法可以參考「這篇」,「這篇」。



2014/10/8 14:12
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2009/10/16 8:57
所屬群組:
已註冊使用者
等級: 22
HP : 0 / 541
MP : 204 / 22060
EXP: 67
離線
安安,其實我最感興趣的是 "如何能正確的判斷出" 文件的編碼,其在程式設計上是如何判斷出來的,也就是演算方式。

在 Geany 這個文書編輯器官方文件中,曾說過這是很困難而且容易判斷錯誤,但有些文書編輯器,似乎能正確自動判出來,可能我僅僅試用 UTF-8 和 Big5 來測,對於其它 encoding 就沒測了。

大部份這類轉碼工具,都必需指定文字編碼,所以,一個大的問題就是若我不知道這個文件是採用何種文件編碼的呢?

以前在 DOS 使用的 Big5,問題很多,招人詬病,其中一個最大的原因就是在 Big5 碼中用到當時就在 UNIX 中的這個 "/"(2014-10-09 修正應為 "\") 符號。在以前不得不用 Big5 碼時,例如要用 PHP 寫程式,那個經典的 "許功蓋" 問題,這種經驗相信很多人都了解。

所以後來在中文上才會衍生出一大堆奇奇怪怪的文字編碼方式,可謂是萬碼奔騰也不為過,這種困擾,當時的資策會要付相當大的責任。

文件自動偵測方式,我想也是用 "試" 一份文件是否有奇怪的字元,然後再 "多方" 判斷這些字元是用那一種編碼的(如 Big5 的編碼範圍) .. 等等。

所以對這方面很好奇 ^_^

2014/10/9 1:49
同源一体、感同身受、樂於分享、教學相長!
寬廣的心, 世界不會小 ^_^
CreMaker 的生活網誌
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
管理員
註冊日期:
2010/5/7 5:46
所屬群組:
已註冊使用者
討論區管理群
等級: 31
HP : 0 / 755
MP : 434 / 29544
EXP: 23
離線
哪來的純文字檔?
參考看看
自動偵測應該是尋找16進位的特定地方吧

2014/10/9 4:40
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 905
MP : 679 / 30217
EXP: 23
離線
qifong 寫到:
安安,其實我最感興趣的是 "如何能正確的判斷出" 文件的編碼,其在程式設計上是如何判斷出來的,也就是演算方式。

在 Geany 這個文書編輯器官方文件中,曾說過這是很困難而且容易判斷錯誤,但有些文書編輯器,似乎能正確自動判出來,可能我僅僅試用 UTF-8 和 Big5 來測,對於其它 encoding 就沒測了。

大部份這類轉碼工具,都必需指定文字編碼,所以,一個大的問題就是若我不知道這個文件是採用何種文件編碼的呢?



關於編碼自動偵測的問題,昨天為了要利用php那個版本,又再找一次資料了,僅止於找到資料,還沒消化。
關於這部份議題我好像一段時間,就會重新再找一次相關的資料。
誰叫我每次都只是僅止於找到資料,而沒有消化呢 :p

把我昨天找到的相關資料貼出來,給有興趣進一步研究當參考,也請不吝分享你們研究的心得摟。

## 自動偵測編碼的專案。

* chardet - (chardet.github.io)

* python3-chardet 上面fork出來的。

* uchardet - google code,opencc的作者放在github上的一個專案。


上面的應該都跟「Mozilla universalchardet」這個專案有關,相關文章
關於這個議題,我最早以前是從「jserv這篇文章」看到,才開始陸續去找相關的資料的。

剛找 這篇文章的時候,又發現一個專案

* libchardet

用這個「universalchardet」來找,應該還可以再找到一些專案。

* juniversalchardet
* nuniversalchardet

其餘的,族繁不及備載,其實是我懶...


然後在這篇看到php的方案「mb_check_encoding」後來找到另一個「mb_detect_encoding」,
是是屬於「mbstring」這個「extension」。

印象中,以前好像有使用過,但哪時候的感觸,辨識率好像沒有很好,不知道是不是哪時候我誤用了。
不過相信目前應該是有改進。PHP都演進哪麼多版本了。
想要利用「mb_detect_encoding」搭配「這篇文章」提到的「PHP Zip Extension」。
昨天初步測試使用「PHP Zip Extension」和「iconv」,來解壓縮最上面的範例,是OK的。

## 安裝 uchardet

```sh
$ sudo apt-get install uchardet
```

測試你要測試的檔案

```sh
$ uchartdat test.txt
```

或是要測試的字串(可以搭配for,來偵測檔名)


$ echo '測試內容' | uchardet



搭配for,來偵測檔名


        for file_name in ./*; do
                echo "$file_name"
                echo "$file_name" | uchardet
                echo
        done



## 相關的工具

看來跟這些編碼相關的軟體,目前可以善用「convmv」「opencc」「uchartdat」這些工具

```sh
$ sudo apt-get install convmv
```

```sh
$ sudo apt-get install opencc
```

## Wiki
http://en.wikipedia.org/wiki/Character_encoding
http://zh.wikipedia.org/zh-tw/%E5%AD%97%E5%85%83%E7%B7%A8%E7%A2%BC


## 相關的文章和討論

* Dive Into Python 3 / Case Study: Porting chardet to Python 3 (中文版)

## 額外一提

印象中以前看過一篇文章,提到「Wikipedia」對「繁簡轉換」有自己使用的一套系統。

* http://zh.wikipedia.org/zh-tw/%E7%B9%81%E7%B0%A1%E8%BD%89%E6%8F%9B
* http://zh.wikipedia.org/zh-tw/Wikipedia:%E5%AD%97%E8%A9%9E%E8%BD%89%E6%8F%9B%E8%99%95%E7%90%86
* http://zh.wikipedia.org/zh-tw/%E7%B0%A1%E7%B9%81%E8%BD%89%E6%8F%9B%E4%B8%80%E5%B0%8D%E5%A4%9A%E5%88%97%E8%A1%A8
* http://zh.wikipedia.org/zh-tw/Help:%E4%B8%AD%E6%96%87%E7%BB%B4%E5%9F%BA%E7%99%BE%E7%A7%91%E7%9A%84%E7%B9%81%E7%AE%80%E3%80%81%E5%9C%B0%E5%8C%BA%E8%AF%8D%E5%A4%84%E7%90%86

報告完畢!


2014/10/9 9:21
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 905
MP : 679 / 30217
EXP: 23
離線
qifong 寫到:
以前在 DOS 使用的 Big5,問題很多,招人詬病,其中一個最大的原因就是在 Big5 碼中用到當時就在 UNIX 中的這個 "/" 符號。在以前不得不用 Big5 碼時,例如要用 PHP 寫程式,那個經典的 "許功蓋" 問題,這種經驗相信很多人都了解。


釐清一下,應該是「\」,才會導致「字元脫逸」,而非「/」。




剛剛才發現,原來還有這個「|」會引發問題,但這不是跟「脫逸字元」有關,是跟「Unix 指令的命令管線」有關。詳細說明請看「Wiki / 大五碼 - 衝碼問題」。

:-p

2014/10/9 9:24
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2009/10/16 8:57
所屬群組:
已註冊使用者
等級: 22
HP : 0 / 541
MP : 204 / 22060
EXP: 67
離線
samwhelp 寫到:
釐清一下,應該是「\」,才會導致「字元脫逸」,而非「/」。


感謝,已修正該文 ^_^

2014/10/9 11:32
同源一体、感同身受、樂於分享、教學相長!
寬廣的心, 世界不會小 ^_^
CreMaker 的生活網誌
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2009/10/16 8:57
所屬群組:
已註冊使用者
等級: 22
HP : 0 / 541
MP : 204 / 22060
EXP: 67
離線
nana 寫到:
自動偵測應該是尋找16進位的特定地方吧


感謝,有時間我測一下,看看是否能在開檔時自動偵測一些文件的編碼方式 ^_^

2014/10/9 11:34
同源一体、感同身受、樂於分享、教學相長!
寬廣的心, 世界不會小 ^_^
CreMaker 的生活網誌
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 905
MP : 679 / 30217
EXP: 23
離線
samwhelp 寫到:

然後在這篇看到php的方案「mb_check_encoding」後來找到另一個「mb_detect_encoding」,
是是屬於「mbstring」這個「extension」。

印象中,以前好像有使用過,但哪時候的感觸,辨識率好像沒有很好,不知道是不是哪時候我誤用了。
不過相信目前應該是有改進。PHP都演進哪麼多版本了。
想要利用「mb_detect_encoding」搭配「這篇文章」提到的「PHP Zip Extension」。
昨天初步測試使用「PHP Zip Extension」和「iconv」,來解壓縮最上面的範例,是OK的。



剛測試,結果還不賴

看來以前是我誤用了,沒有真的了解「mb_detect_encoding」的用法。
誤會它了,歹勢...

以下是寫好的「範例」,請享用
將下面這段程式存到「~/bin/phpunzip」,然後「chmod u+x ~/bin/phpunzip」。
然後解壓縮,只要執行「phpunzip file_name 」就行了,可以用我一開始提到的範例來玩喔。


$ wget -c https://gist.githubusercontent.com/samwhelp/2f6764561bc3b5f15125/raw/b906bd7892324cc17a30f639c5f504ffcd86f184/phpunzip.php -O ~/bin/phpunzip
$ chmod u+x ~/bin/phpunzip
$ phpunzip Open_Data.zip



注意:
> 有一行定義「UTIL_ZIP_EXTRACT_DETECT_ENCODING_ORDER_LIST」,請改成你要偵測的編碼吧。
檢查的順序結果會有差異喔,可以把順序對調玩玩看。
不過這部份我還沒弄懂,單純就我目前測試的結果來看,把「Big5」放到「UTF-8」之前,就會判斷不出來「Big-5」。
不知道是不是跟font查找的fallback機制是雷同的概念。
:p



#!/usr/bin/env php
<?php
/**
* PHP ZIP 解壓縮,檔名編碼自動轉為Utf-8編碼範例。
*
* @see https://gist.github.com/samwhelp/2f6764561bc3b5f15125
* @see http://www.ubuntu-tw.org/modules/newbb/viewtopic.php?post_id=327124#forumpost327124
* @see http://micy.cn/blog/post/118
* @see http://www.chengcms.com/study/391.html?jdfwkey=wtgln3
* @see http://forum.ubuntu.org.cn/viewtopic.php?f=163&t=325386
* @see http://php.net/manual/en/function.mb-detect-encoding.php
* @see http://php.net/manual/en/function.iconv.php
* @see http://php.net/manual/en/book.iconv.php
* @see http://php.net/manual/en/book.zip.php
* @see http://php.net/manual/en/zip.examples.php
*/

/*
這個是在Xubuntu 14.04 底下測試的。
將檔案存到「~/bin/phpunzip」,然後「chmod u+x ~/bin/phpunzip」。
然後解壓縮,只要執行「phpunzip file_name 」就行了。
*/

if (!extension_loaded('zip')) {
printf("php zip extension is needed. See http://www.php.net/manual/en/zip.installation.php\n");
exit;
}

if (!isset($argv[1])) {
printf("Usage: %s file_name\n\n", basename($argv[0]));
exit;
}

define('UTIL_ZIP_EXTRACT_DETECT_ENCODING_ORDER_LIST', 'UTF-8, BIG5, ISO-8859-1'); //請更改你要檢測的編碼。請參考「http://php.net/manual/en/function.mb-detect-order.php」。
//define('UTIL_ZIP_EXTRACT_DETECT_ENCODING_ORDER_LIST', 'UTF-8, GB2312, BIG-5, SHIFT-JIS, ISO-8859-1');


/**
* ZIP 解壓縮,並偵測檔案名稱編碼,自動轉換成Utf-8。
*
* @param string $source_path zip檔案路徑。
* @param mixed $target_path 解開後的路徑,可以不填。
* @return string 有發生錯誤,會回傳訊息。
*/

function util_zip_extract($source_path, $target_path=null)
{
if ($target_path === null) {
$target_path = substr($source_path, 0, -4);
}

$target_base_path = dirname($target_path);

if (file_exists($target_path)) {
return 'Dir or File is exist!: ' . $target_path;
}

if (!file_exists($source_path)) {
return 'Extract file is not exist!: ' . $source_path;
}

$file = zip_open($source_path);

if (!is_resource($file)) {
return 'Open zip file not ok!: ' . $source_path;
}

while ($entry = zip_read($file)) {
$file_size = zip_entry_filesize($entry);
$file_name = zip_entry_name($entry);

$encode = mb_detect_encoding($file_name, UTIL_ZIP_EXTRACT_DETECT_ENCODING_ORDER_LIST);

//echo $encode . PHP_EOL;

if (strtoupper(trim($encode)) !== 'UTF-8') {
$file_name = iconv($encode, 'UTF-8//TRANSLIT', $file_name);
////$file_name = iconv('Big5', 'UTF-8//TRANSLIT', $file_name);
////$file_name = iconv('Big-5', 'UTF-8//TRANSLIT', $file_name);
}


$target_file_path = $target_base_path . '/' . $file_name;

if (!$file_size) {
if (file_exists($target_file_path)) {
continue;
}
mkdir($target_file_path, 0755, true);
continue;
} else if (!zip_entry_open($file, $entry)) {
continue;
}

file_put_contents($target_file_path, zip_entry_read($entry, $file_size));

zip_entry_close($entry);
}
zip_close($file);
}


////$file = getcwd() . '/' . $argv[1];
$file = $argv[1];

$msg = util_zip_extract($file);

if ($msg) {
echo $msg;
echo PHP_EOL;
}



確保這個套件有裝,就可在terminal執行php。


$ sudo apt-get install php5-cli



先用function的方式寫。
有些地方,只有簡單寫,可能有些例外狀況沒想到,沒有處理,或只是簡單處理。
這只是當個說明的範例。
請改成自己需要的版本吧。


enjoy it!




## 後記 (2016-09-01)

因為我在「Xubuntu 16.04 64位元」「PHP 7.0.8-0ubuntu0.16.04.2 (cli) ( NTS )」測試,解開的檔案還是會亂碼,

所以在「Packagist」找到了一個使用PHP來實做的專案「php-archive」,

然後做了一點簡單的調整,就可以用來解開含有「Big5檔名」的「Zip file」。

詳細說明,請看「這裡」。

2014/10/9 11:41
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 905
MP : 679 / 30217
EXP: 23
離線
剛發現「一篇討論」,使用「Wine + 7zip」。
尚未用過,
先貼上來當參考。


2014/10/9 17:58
應用擴展 工具箱
回覆: [分享] 解壓縮zip檔,產生亂碼,如何解決的心得
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 905
MP : 679 / 30217
EXP: 23
離線
samwhelp 寫到:
剛發現「一篇討論」,使用「Wine + 7zip」。
尚未用過,
先貼上來當參考。



剛用 「wine 7zip」來查詢,看到這一篇的回覆。裡面有一篇,方法和頂樓參考的「那一篇」一樣。呵呵,不過這個是中文說明。

另外還有寫好的「shell script」,以及「Python版」。可以參考。



2014/10/9 23:07
應用擴展 工具箱

(1) 2 »

 [無發表權] 請登錄或者註冊


可以查看帖子.
不可發帖.
不可回覆.
不可編輯自己的帖子.
不可刪除自己的帖子.
不可發起投票調查.
不可在投票調查中投票.
不可上傳附件.
不可不經審核直接發帖.