天天看點

"中文系統下打的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 [email protected]

如何知道一個編碼對應的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