Go如何處理zip中的中文檔案名稱

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Go的標準庫已經內建了zip的庫.

不過zip包在處理內部檔案名稱時, 預設是utf8編碼的.
對於Windows中文使用者, 產生和讀取zip內部檔案名稱預設是GBK編碼的.
因此, 在處理涉及GBK的檔案名稱時需要做一個轉換.

Go語言官方的 go.text 子標準庫已經支援各種編碼, 下面是utf8轉GBK的函數:

import "golang.org/x/text/encoding/simplifiedchinese"func utf8ToGBK(text string) (string, error) {    dst := make([]byte, len(text)*2)    tr := simplifiedchinese.GB18030.NewEncoder()    nDst, _, err := tr.Transform(dst, []byte(text), true)    if err != nil {        return text, err    }    return string(dst[:nDst]), nil}

在產生zip檔案時, 用 utf8ToGBK 處理檔案名稱:

func main() {    file, err := os.Create("中文-測試.zip")    if err != nil {        log.Fatal(err)    }    defer file.Close()    wzip := zip.NewWriter(file)    defer func() {        if err := wzip.Close(); err != nil {            log.Fatal(err)        }    }()    // 壓縮檔    var files = []struct{ Name, Body string }{        {"11/1/readme.txt", "UTF8 字串."},        {"11/1/readme2.txt", "This archive contains some text files."},        {"漢字/2/gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},        {"11/中文.txt", "中文Get animal handling licence.\nWrite more examples."},        {"空目錄/", ""},    }    for _, file := range files {        name, _ := utf8ToGBK(file.Name) // 檔案名稱轉換為 GBK編碼        f, err := wzip.Create(name)        if err != nil {            log.Fatal(err)        }        _, err = f.Write([]byte(file.Body))        if err != nil {            log.Fatal(err)        }    }}

這樣就可以產生Windows下帶簡體中文的檔案名稱壓縮檔了.

2014年補充:

其實在新的 zip規範 中,
已經對UTF8編碼的檔案名稱提供了支援.

File:    APPNOTE.TXT - .ZIP File Format SpecificationVersion: 6.3.34.4.4 general purpose bit flag: (2 bytes)Bit 11: Language encoding flag (EFS).  If this bit is set,    the filename and comment fields for this file    MUST be encoded using UTF-8. (see APPENDIX D)

具體來說, 在每個檔案的頭資訊的Flags欄位的11bit位.
如果該bit位為0則表用本地編碼(本地編碼是GBK嗎?), 如果是1則表示用UTF8編碼.

頭資訊對應zip庫的 archive/zip.FileHeader 結構的 Flags 成員:

type FileHeader struct {    // Name is the name of the file.    // It must be a relative path: it must not start with a drive    // letter (e.g. C:) or leading slash, and only forward slashes    // are allowed.    Name string    CreatorVersion     uint16    ReaderVersion      uint16    Flags              uint16    Method             uint16    ModifiedTime       uint16 // MS-DOS time    ModifiedDate       uint16 // MS-DOS date    CRC32              uint32    CompressedSize     uint32 // deprecated; use CompressedSize64    UncompressedSize   uint32 // deprecated; use UncompressedSize64    CompressedSize64   uint64    UncompressedSize64 uint64    Extra              []byte    ExternalAttrs      uint32 // Meaning depends on CreatorVersion    Comment            string}

如果想產生UTF8編碼的檔案名稱, 可以手工指定該欄位:

func main() {

file, err := os.Create("中文-測試.zip")if err != nil {    log.Fatal(err)}defer file.Close()wzip := zip.NewWriter(file)defer func() {    if err := wzip.Close(); err != nil {        log.Fatal(err)    }}()// 壓縮檔var files = []struct{ Name, Body string }{    {"11/1/readme.txt", "UTF8 字串."},    {"11/1/readme2.txt", "This archive contains some text files."},    {"漢字/2/gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},    {"11/中文.txt", "中文Get animal handling licence.\nWrite more examples."},    {"空目錄/", ""},}for _, file := range files {    header := &zip.FileHeader{        Name:   file.Name,        Flags:  1 << 11, // 使用utf8編碼        Method: zip.Deflate,    }    f, err := wzip.CreateHeader(header)    if err != nil {        log.Fatal(err)    }    _, err = f.Write([]byte(file.Body))    if err != nil {        log.Fatal(err)    }}

}

其實, zip.Create 預設應該是假設檔案名稱採用UTF8編碼, 這樣可以避免不同機器間本地編碼不同導致的解碼的問題.
針對該修改已經提交了 CL54360043, 目前還不清楚是否能夠被接受.

不過比較遺憾的是Win7內建的zip瀏覽器始終是忽略該欄位的(始終用本地編碼處理).

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.