解決rubyzip使用中遭遇到的中文文件名稱亂碼問題

    最近程序中需要用到rubyzip這個gem進行解壓縮和壓縮,於是就遇到了中文文件名變成亂碼的問題。

    首先,使用rubyzip解壓縮zip文件,代碼參照官網的示例很簡單

def unzip(zip_file, dest_dir)    
    Zip::File.open zip_file do |zf|  
      zf.each do |e|          
        path = File.join dest_dir, e.name
        FileUtils.mkdir_p File.dirname(path)  
        zf.extract(e, path) { true }  
      end  
    end  
  end 

發現中文文件名亂碼後,看文檔發現只需在方法開始加上 ,

Zip.force_entry_names_encoding = 'GBK'

 

經過測試果然解決問題。

應用裏還需要生成zip壓縮包,這裏就不貼代碼了,完全採用官網的示例即可,這次仔細看了說明,在其中加上下面這行即可順利生成包含中文文件名的zip壓縮包

Zip.unicode_names = true

 

好,現在壓縮解壓縮代碼都完成了,可是接下來問題來了,用自己的代碼解壓縮自己打包的zip文件,又出現了中文文件名亂碼問題!
經研究發現,一開始的zip包是在windows下打包的,中文文件名編碼爲gb18030,程序打包的zip文件,中文文件名的編碼是UTF-8,在windows下打開解壓都沒有問題,但是由於解壓代碼中固定設置爲GBK,所以解壓自己打包的zip就再次出現亂碼現象。
多方搜索,仔細看文檔甚至代碼,都沒有好的解決方案,不能自適應編碼是不能接受的。沒辦法只能自己解決編碼探測問題。
在gems網站找到2個編碼探測的gem一個是純ruby編碼的 ’rchardet‘,另一個是依賴ICU庫的 'charlock_holmes', 經測試,兩個庫都可以完成任務,但是'charlock_holmes' 要比 ’rchardet' 快上一個量級。
開始,採用每個文件名探測一次的方式,結果很不理想,誤報率較高,而且置信度維持低水平,尤其charlock_holmes',經常把中文編碼探測爲日文Shift_JIS。後改爲聯合所有文件名爲一個字符串在進行探測,發現置信度大幅度提升,基本已經滿足需要。
因爲GB18030編碼足夠空間,所以如果探測到不是ASCII編碼,就一律轉爲GB18030,經測試完美解決了我的問題。
附上修改後的代碼:
def unzip(zip_file, dest_dir)    
    file_encoding = detect_encoding_v2 zip_file

    Zip::File.open zip_file do |zf|  
      zf.each do |e|          
        name = e.name                
        name = name.encode('GB18030', file_encoding) if file_encoding != 'ASCII'
        path = File.join dest_dir, name
        FileUtils.mkdir_p File.dirname(path)  
        zf.extract(e, path) { true }  
      end  
    end  
  end 

def detect_encoding_v2(zip_file)   
    require 'charlock_holmes' 
    names = []
    Zip::File.open zip_file do |zf|  
      zf.each do |e|
        name = e.name
        names << e.name
      end
    end
    ss = names.join
    cd = CharlockHolmes::EncodingDetector.detect(ss)
    syscoding = name.encoding.to_s.upcase
    coding = cd[:encoding].upcase

    if coding=='ASCII' && syscoding!='ASCII'
      coding = 'GB18030'
    end
   
    return coding
  end
View Code

 

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