1. 程式人生 > >跨平臺中文檔名亂碼的解決

跨平臺中文檔名亂碼的解決

事情的起因是這樣的~~

在很久很久以前——大約是2年多年前,我整了一臺P3的機器裝了FreeBSD做伺服器,經常用Filezilla的SFTP往裡面備份本地的檔案,當然也包括一些中文名的檔案。一切都很正常,上傳下載都沒問題,即使是用 SSH連過去用Tar打包再Gzip壓縮以後下載下來解開都沒問題。

但是好日子在前幾天到頭了。我前一陣又弄了一臺P3的機器裝了Ubuntu。問題出現了:

首先是在Windows上用Filezilla連線Ubuntu時看到的中文檔名全是亂碼,但是用Putty通過SSH連線Ubuntu卻是正常 的(原先是亂碼,後來改設定為UTF-8編碼就好了,不過Filezilla沒有類似的設定可改)。如果用Filezilla向Ubuntu上傳本地的中 文檔案,則在Filezilla裡看到Remote端的檔名是正確的,但在Putty裡看到是亂碼。

然後更嚴重的問題是:當我在Ubuntu上用Filezilla的SFTP從FreeBSD上下載檔案時發現那些中文檔名都成了亂碼。只好改用 tar/tar.gz再試,結果還是亂。最後問了Google,但是結果並不理想,試過很多方法都無法解決,甚至為此特地在FreeBSD和Ubuntu 上都裝了p7zip試驗,也還是不行。

折騰了好幾天之後,我才想到應該研究一下幾個系統上的locale設定究竟是如何的——坦白說,要不是因為搜到的資料裡有提到這方面,我從前還真沒注意到這回事。在FreeBSD和Ubuntu上分別運行了locale命令檢查的結果是:

FreeBSD的LC_ALL為“C”,即”POSIX”的別名,似乎是一種無固定編碼的方案,或者可以認為就是本地編碼,預設的設定。
Ubuntu的LC_ALL為“zh_CN.UTF-8”,這個是我設定的。
Windows不必說了,肯定是本地編碼——只是我沒有想到的是,公司裡用的英文版Windows居然也是本地編碼,我一直以為是Unicode的,看來是為了保持相容。

這樣就好理解了,Filezilla不改變編碼方式,所以當Remote端與本機的編碼不一致時,必然亂碼。所以在Windows上用 Filezilla連線Ubuntu看到亂碼,而我的Putty因為是設定為UTF-8編碼,所以看到的是正確的——因為Ubuntu一端是UTF-8。 而如果用Filezilla上傳中文檔案,則因為Windows是本地編碼,所以上傳以後仍然為本地編碼(GB系),而Ubuntu是UTF-8所以是亂 碼。

FreeBSD那邊的問題也是一樣的,因為那些檔案都是以前從Windows上傳上去的,用的都是GB系編碼,而早年我用Putty都是用預設的本 地編碼方案,所以一直沒有發現問題。這樣的話,因為FreeBSD是本地編碼,與Ubuntu的UTF-8不一致,所以怎麼弄都是亂碼。

但是據說用7zip這樣的工具打包以後是可以解決這樣的編碼不一致問題的,我試了卻沒有成功。後來才想明白,因為7zip是根據系統的locale設定來對檔名進行相應的處理,因為原來我處理的時候檔名是GB系的編碼,而系統是設定為UTF-8,所以總也不對。

最後的解決方案是:

在ubuntu上用以下命令:

export LC_ALL="zh_CN.GBK"
scp raptor@freebsdserver:/home/raptor/myfiles/*.* .
export LC_ALL="zh_CN.UTF-8"
convmv -f GBK -t UTF-8 --notest *.*

原理就是先把ubuntu的locale改為GBK,然後用SSH COPY檔案過來,再改locale為UTF-8,然後用convmv來轉換檔名的編碼。

不過經過試驗表明,不改變locale直接scp也是可以的,因為scp並不會改變檔名的編碼方式,不過改了locale以後便於在轉編碼之前檢查scp過來的內容(否則scp過來是亂碼,要到轉編碼後才正常)。

這樣做的結果就是,這些檔案在ubuntu上是正常了,以後要再弄回windows就比較麻煩,需要用7zip之類的工具打包下載再解開。

歸根到底這些問題都是因為該死的Windows用本地編碼來記錄檔名,Unicode化做得不夠徹底。