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
当我使用此代码目录时,中文将被乱七八糟。谁可以帮助我解决问题。
问题是,默认情况下,zip输入名称中只允许zip规范允许ASCII字符,更具体地说:(来源:附录D)
附录D.1 ZIP格式历史上仅支持原始IBM PC字符 编码集,通常称为IBM代码第437页。这限制了存储 文件名字符仅针对原始MS-DOS范围内的文件字符 并且没有正确支持其他字符编码中的文件名,或 语言。为了解决此限制,此规范将支持 以下更改。
后来添加了对Unicode名称的支持。可以用一个特殊的位标记为general purpose bit 11
,也称为Language encoding flag (EFS)
:
第4.4.4.4节 - 通用位数标志 - 位11-语言编码标志(EFS)。如果设置了此位,则必须使用UTF-8编码此文件的文件名和注释字段。
附录D.2 如果通用位11尚未设置,则文件名和评论应符合 到原始的zip字符编码。如果设置了通用位11, 文件名和评论必须支持Unicode标准版本4.1.0或 使用UTF-8存储定义的字符编码表格更大 规格。Unicode标准由Unicode发布 财团(www.unicode.org)。UTF-8编码数据存储在zip文件中 预计不包括字节订单标记(BOM)。
general purpose bit flag
是由GO出现并支持的:它是FileHeader
结构的Flags
字段。不幸的是,GO没有设置此位的方法,默认情况下它是0。
因此,添加对Unicode名称的支持的最简单方法就是将bit 11
设置为一个。而不是
FileName, _ := Zip.Create(Path)
以:
开始您的ZIP条目h := &zip.FileHeader{Name:Path, Method: zip.Deflate, Flags: 0x800}
FileName, _ := Zip.CreateHeader(h)
第一行创建一个FileHeader
,其中为Flags
字段设置了0x800
(bit 11
)值,该字段告诉该文件名将使用UTF-8
编码文件名(这是将string
写入io.Writer
时GO所做的。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<)/p>
注意:
这样做,将保留UTF-8文件名,但并非所有ZIP读取器/提取器都支持它。例如,在Windows,Windows文件处理程序上,Windows Explorer不会将其解码为UTF-8,但是例如,更严肃的Zip处理程序(例如SecureZip)将看到UTF-8文件名并将其正确提取文件名(使用UTF-8解码)。
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)
}
}