"中文系統下打的zip壓縮包, 日文系統下查看時文件名亂碼問題"的解決方案

標題:

"中文系統下打的zip壓縮包, 日文系統下查看時文件名亂碼問題"解決方案:

   -  在壓縮/解壓縮zip包時, 指定文件名的編碼方式

 

正文開始......

我們公司使用的操作系統是中文, 我們經常需要把一些文件壓成zip包, 然後發給日本總公司,

當然, 日本同事使用的是日文操作系統.

這個時候, 如果zip包中所有文件都是ascii字符, 那麼沒問題,

否則, 如果zip包中包含漢語或者日語字符那麼對方看到便會出現亂碼.

 

原因在於:

無論是windows默認的zip壓縮工具, 還是7-zip, 在zip壓縮或者解壓縮的時候,使用的都是系統默認編碼來表示文件名,

也就是說windows上面是gb2312, 而日文windows上面用的是shift-jis

使用gb2312編碼的zip文件名, 在日文windows上面使用shift-jis來查看, 自然是亂碼的.

 

還有一類人, 應該也受這個問題所苦.

他們(也包括我)有時候會從日本的站點(share等)下載一些壓縮包(漫畫之類),

這些壓縮包是在日文系統下壓縮的, 如果文件名包含日語, 在我們中文的系統上解壓就會出現亂碼.

 

我以前的解決辦法是弄一個日文的虛擬機,

無論是解壓還是壓縮都在虛擬機上進行.

(前一個公司, 日本和中國都使用日文的windows, 便沒有這個問題)

 

然而爲了一個壓縮包就開要打開一個虛擬機,難免有些麻煩

所以我的期望是:

在壓縮zip包,或者解壓縮zip包時, 能夠制定對文件名的編碼方案.

比如我在中文系統上製作一個壓縮包, 我可以指定: 對文件名使用日文編碼進行編碼.

這樣以來, 在日文os上查看時,變不會產生亂碼.

 

調查了一下, 這個問題可以通過DotNetZip 來解決,

DotNetZip對自己的介紹是: Zip and Unzip in C#, VB, any .NET language

給我們提供的資源也很貼心:

有源代碼, dll, 還有基於這些源代碼和dll的工具, 有命令行的, 也有GUI的zip工具,

這些工具也有源代碼, 同時還提供了C#,VB等語言的例子(我看了一下, 集成到自己的程序中也很方便).

download 頁面在這裏.

 

我下載的是: DotNetZipLib-DevKit-v1.9.zip

解壓縮之後在DotNetZipLib-DevKit-v1.9\Tools\路徑下面,會有兩個命令行工具: Zipit.exe 和 UnZip.exe

(其實還包括一個GUI工具,叫DotNetZip-WinFormsTool.exe, 不喜歡命令行的移步這裏)

zipit.exe是壓縮的命令行, UnZip.exe是解壓縮, 他的參數類似, 都支持指定編碼.
這次我使用的工具就是他們. 他們的命令行參數在這裏 .

也可以從這個鏈接導航進來: DotNetZip - Zip file manipulation in .NET languages

 

使用這個命令行工具, 指定編碼打zip包的方法如下:

 

Zipit.exe "C:\_TryZipIt\測試文件夾.zip" -r+ -cp 932 "C:\_TryZipIt\測試文件夾"

 

上面的命令是壓縮文件夾, 壓縮文件的方式類似.

其中cp這個參數指的是code page. 不同系統對於同一種編碼的code page可能會不同, 詳參Code page@wikipedia

如何知道一個編碼對應的code page呢?

可以通過如下代碼取得(C#爲例), 或者google吧.

根據結果, 日文windows的默認編碼shift-jis對應的code page是932.

            var cp_shiftjis  = System.Text.Encoding.GetEncoding("shift-jis").CodePage;
            var cp_eucjp    = System.Text.Encoding.GetEncoding("euc-jp").CodePage;
            var cp_gbk      = System.Text.Encoding.GetEncoding("GBK").CodePage;
            var cp_gb2312 = System.Text.Encoding.GetEncoding("gb2312").CodePage;

 

 

 

然而使用上面的命令行, 每次輸入的參數還是太多,於是我寫了一個ruby腳本包裝了一下上面的命令行.

這個腳本每次只接受一個參數, 他代表一個文件或者文件夾.

他的功能是, 在跟輸入參數相同的文件夾下, 創建一個同名的.zip文件.

相當於7-zip郵件菜單中的: 添加到 "XXX.zip"

使用這個腳本的前提是你要將zipit.exe放到path中

 

# encoding : utf-8

def show_usage_and_exit(msg)
  puts "please input the path to zip"
  puts "error msg: #{msg}"
  exit 0
end

show_usage_and_exit("no path to zip") unless ARGV.length == 1

#puts ARGV[0].dup.force_encoding("GBK").encode('utf-8')
zip_input = ARGV[0].dup.encode('utf-8')
show_usage_and_exit("path does not exist") unless File.exist? zip_input

if File.directory? zip_input
  zip_output = zip_input + ".zip"
else
  zip_output = zip_input.gsub(/\.\w{2,4}\z/,".zip")
end
File.delete zip_output if File.exist? zip_output

zip_cmd =   "#{%Q<Zipit.exe "#{zip_output.encode("GBK")}" -r+ -cp 932 "#{zip_input.encode("GBK")}">}"

puts "the path to zip is:\n\t" +  zip_input;
puts "the target path is:\n\t" +  zip_output;
puts "the zip command is:\n\t" +  zip_cmd.encode("utf-8");

puts "\n------------------------------ zip process start...---------------------\n\n"
#puts `#{zip_cmd}`
puts `#{zip_cmd}`.encode("utf-8")



 

 

在windows上面, 除了7-zip, 和DotNetZip以外,

還可以使用一些其他的命令和腳本, 來製作zip包.

參下面這些鏈接:

Can you zip a file from the command prompt using ONLY Windows' built-in capability to zip files?

Does Windows have a built-in ZIP command for the command line?

Can Windows' built-in ZIP compression be scripted?

Zip and UnZip Files Using the Windows Shell (XP, Vista, 2003 and 2008) and VBScript

 

 

-----------------------------------------------------------------------------------------------------------------------------

追記:2012.07.02

-----------------------------------------------------------------------------------------------------------------------------

重新新封裝了一下這個ruby腳本,
在一個腳本中同時支持zip和unzip.
如果輸入參數不是以.zip擴展名結尾, 那麼使用日文系統的編碼, 將其在當前文件夾中壓縮.
如果輸入參數是以.zip擴展名結尾, 那麼使用日文系統的編碼, 將其在當前文件夾中解壓.
其中用到zipit和unzipit兩個命令
zipit是把DotNetZipLib的命令行工具直接拷貝path中,
unzipit是把DotNetZipLib的叫做unzip.exe的命令改名而來.

 

# encoding : utf-8

def show_usage_and_exit(msg)
  puts "please input the path to zip"
  puts "error msg: #{msg}"
  exit 0
end

def check_parameter
  show_usage_and_exit("no path to zip") unless ARGV.length == 1
  show_usage_and_exit("path does not exist") unless File.exist? ARGV[0].dup.encode('utf-8')
  puts "===your input is===:\n" +  ARGV[0].dup.encode('utf-8')
end

def run_cmd(cmd)
  puts "===the command is===:\n" +  cmd.encode("utf-8") + "\n\n---------- command start...------------\n"
  puts `#{cmd}`.encode("utf-8")   #puts `#{cmd}`
end

def to_zip_cmd(input_str)
  if File.directory? input_str
    zip_output = input_str + ".zip"
  else
    zip_output = input_str.gsub(/\.\w{2,4}\z/,".zip")
  end
  File.delete zip_output if File.exist? zip_output

  "#{%Q<Zipit.exe "#{zip_output.encode("GBK")}" -r+ -cp 932 "#{input_str.encode("GBK")}">}"
end

def to_unzip_cmd(input_str)
  "#{%Q<Unzipit.exe -cp 932 -d "#{File.dirname(input_str).encode("GBK")}"  "#{input_str.encode("GBK")}">}"
end

check_parameter
input_str = ARGV[0].dup.encode('utf-8')     # ;puts ARGV[0].dup.force_encoding("GBK").encode('utf-8')
if input_str.end_with?  '.zip'
  run_cmd(to_unzip_cmd input_str)
else
  run_cmd(to_zip_cmd input_str)
end

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章