2015-05-04 155 views
4
package main 

import (
    "archive/zip" 
    "fmt" 
    "io" 
    "os" 
    "path/filepath" 
    "strings" 
) 

func main() { 
    var (
     Path = os.Args[1] 
     Name = os.Args[2] 
    ) 

    File, _ := os.Create(Name) 
    PS := strings.Split(Path, "\\") 
    PathName := strings.Join(PS[:len(PS)-1], "\\") 
    os.Chdir(PathName) 
    Path = PS[len(PS)-1] 
    defer File.Close() 
    Zip := zip.NewWriter(File) 
    defer Zip.Close() 
    walk := func(Path string, info os.FileInfo, err error) error { 
     if err != nil { 
      fmt.Println(err) 
      return err 
     } 
     if info.IsDir() { 
      return nil 
     } 
     Src, _ := os.Open(Path) 
     defer Src.Close() 
     fmt.Println(Path) 
     FileName, _ := Zip.Create(Path) 
     io.Copy(FileName, Src) 
     Zip.Flush() 
     return nil 
    } 
    if err := filepath.Walk(Path, walk); err != nil { 
     fmt.Println(err) 
    } 
} 

這MYDIR路徑:創建使用Go的存檔Unicode文件名zip存檔/ ZIP

-----root 
    |---2015-05(dir) 
     |---中文.go 
    |---package(dir) 
    |---你好.go 

當我使用此代碼目錄,中國會出現亂碼。誰可以幫我解決問題。

回答

8

的問題是,默認情況下在壓縮條目名稱只有ASCII字符由Zip specification,更明確允許的:(來源:APPENDIX D

附錄D.1 ZIP格式歷來支持只有原始IBM PC字符 編碼集(通常稱爲IBM代碼頁437)。這限制將 文件名字符存儲爲僅限於原始MS-DOS範圍值 內的那些字符,並且不能正確支持其他字符編碼中的文件名,或 語言。爲了解決這個限制,這個規範將支持 下面的變化。

後來增加了對Unicode名稱的支持。這可以打上一個特殊位被稱爲general purpose bit 11,也叫Language encoding flag (EFS)

第4.4.4節 - 通用標誌位 - 第11位 - 語言編碼標誌(EFS)。如果這個位被設置,這個文件的文件名和註釋字段必須使用UTF-8編碼。

附錄D.2如果未設置通用位11,則文件名和註釋應符合原始ZIP字符編碼的 。如果設置了通用第11位,則 文件名和註釋必須使用由UTF-8存儲 規範定義的字符編碼格式支持Unicode標準,版本4.1.0或 。 Unicode標準由Unicode 聯盟(www.unicode.org)發佈。存儲在ZIP文件 內的UTF-8編碼數據預計不包含字節順序標記(BOM)。

general purpose bit flag存在並且支持轉到:它是FileHeader結構的Flags字段。不幸的是,Go沒有設置這個位的方法,默認情況下它是0.

所以添加對Unicode名稱支持的最簡單的方法是簡單地將bit 11設置爲1。

h := &zip.FileHeader{Name:Path, Method: zip.Deflate, Flags: 0x800} 
FileName, _ := Zip.CreateHeader(h) 

第一行創建一個FileHeader其中0x800bit 11)值設置爲Flags現場告訴該文件的名稱將被編碼:用相反的

FileName, _ := Zip.Create(Path) 

啓動ZIP條目使用UTF-8(這是Go在將string寫入io.Writer時執行的操作)。

注:

這樣,UTF-8的文件名會被保留,但不是所有的拉鍊讀/提取支持它。例如,在Windows上,Windows文件處理程序,Windows資源管理器不會將其解碼爲UTF-8,但例如更嚴重的Zip處理程序(例如SecureZip)將會看到UTF-8文件名並且將正確提取文件名使用UTF-8解碼)。

-2
package main 

import (
    "archive/zip" 
    "fmt" 
    "io" 
    "os" 
    "path/filepath" 
    "strings" 
) 

func main() { 
    var (
     Path = os.Args[1] 
     Name = os.Args[2] 
    ) 

    File, _ := os.Create(Name) 
    PS := strings.Split(Path, "\\") 
    PathName := strings.Join(PS[:len(PS)-1], "\\") 
    os.Chdir(PathName) 
    Path = PS[len(PS)-1] 
    defer File.Close() 
    Zip := zip.NewWriter(File) 
    defer Zip.Close() 
    walk := func(Path string, info os.FileInfo, err error) error { 
     if err != nil { 
      fmt.Println(err) 
      return err 
     } 
     if info.IsDir() { 
      return nil 
     } 
     Src, _ := os.Open(Path) 
     defer Src.Close() 
     //FileName, _ := Zip.Create(Path) 
     h := &zip.FileHeader{Name: Path, Method: zip.Deflate, Flags: 0x800} 
     FileName, _ := Zip.CreateHeader(h) 
     io.Copy(FileName, Src) 
     Zip.Flush() 
     return nil 
    } 
    if err := filepath.Walk(Path, walk); err != nil { 
     fmt.Println(err) 
    } 
} 
+0

如果您可以添加關於如何解決問題的解釋將會很有幫助。 – Carpetsmoker