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路径:
-----root
|---2015-05(dir)
|---中文.go
|---package(dir)
|---你好.go
当我使用这个代码目录时,中文会出现乱码。谁能帮我解决问题。
答案 0 :(得分:9)
问题是默认情况下,在zip条目名称中Zip specification只允许使用ASCII字符,更具体地说:(来源: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,则 文件名和注释必须支持Unicode标准版本4.1.0或 使用UTF-8存储定义的字符编码格式更大 规格。 Unicode标准由The Unicode发布 联盟(www.unicode.org)。存储在ZIP文件中的UTF-8编码数据 预计不包括字节顺序标记(BOM)。
Go出现并支持general purpose bit flag
:它是FileHeader
结构的Flags
字段。遗憾的是Go没有设置此位的方法,默认情况下为0。
因此,添加对Unicode名称的支持的最简单方法是将bit 11
设置为1。而不是
FileName, _ := Zip.Create(Path)
使用以下命令启动您的zip条目:
h := &zip.FileHeader{Name:Path, Method: zip.Deflate, Flags: 0x800}
FileName, _ := Zip.CreateHeader(h)
第一行创建FileHeader
,其中为0x800
字段设置bit 11
(Flags
)值,告知文件名将使用{{ 1}}(这是Go将UTF-8
写入string
时的行为。)
注意:强>
通过这样做,将保留UTF-8文件名,但并非所有zip阅读器/提取器都支持它。例如,在Windows上,Windows文件处理程序,Windows资源管理器不会将其解码为UTF-8,但是例如更严重的Zip处理程序(例如SecureZip)将看到UTF-8文件名并将提取文件名正确(使用UTF-8解码)。
答案 1 :(得分:-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)
}
}