2015-05-04 115 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