我是golang的新手,無法弄清楚如何使用golang的「compress/gzip」包對我有利。基本上,我只想寫一些東西到一個文件,gzip它,並通過另一個腳本直接從壓縮格式讀取它。我真的很感激,如果有人可以給我一個例子如何做到這一點。如何使用golang的「compress/gzip」軟件包來gzip文件?
回答
所有壓縮包都實現相同的接口。你會使用這樣的壓縮:
var b bytes.Buffer
w := gzip.NewWriter(&b)
w.Write([]byte("hello, world\n"))
w.Close()
這解壓:
r, err := gzip.NewReader(&b)
io.Copy(os.Stdout, r)
r.Close()
謝謝!這有幫助。 – pymd
幾乎相同的答案洛朗,但文件IO:
import (
"bytes"
"compress/gzip"
"io/ioutil"
)
// ...
var b bytes.Buffer
w := gzip.NewWriter(&b)
w.Write([]byte("hello, world\n"))
w.Close() // You must close this first to flush the bytes to the buffer.
err := ioutil.WriteFile("hello_world.txt.gz", b.Bytes(), 0666)
您應該使用os.Open創建文件並將其傳遞給gzip.NewWriter,並且對該gzip寫入器的每次寫入都會將壓縮數據寫入該文件。 – Giacomo
對於閱讀部分,有用ioutil.ReadFile爲.gz文件可能是:
func ReadGzFile(filename string) ([]byte, error) {
fi, err := os.Open(filename)
if err != nil {
return nil, err
}
defer fi.Close()
fz, err := gzip.NewReader(fi)
if err != nil {
return nil, err
}
defer fz.Close()
s, err := ioutil.ReadAll(fz)
if err != nil {
return nil, err
}
return s, nil
}
我決定結合其他人的想法,並提供一個完整的示例程序。顯然有很多不同的方法來做同樣的事情。這只是一種方式:
package main
import (
"compress/gzip"
"fmt"
"io/ioutil"
"os"
)
var zipFile = "zipfile.gz"
func main() {
writeZip()
readZip()
}
func writeZip() {
handle, err := openFile(zipFile)
if err != nil {
fmt.Println("[ERROR] Opening file:", err)
}
zipWriter, err := gzip.NewWriterLevel(handle, 9)
if err != nil {
fmt.Println("[ERROR] New gzip writer:", err)
}
numberOfBytesWritten, err := zipWriter.Write([]byte("Hello, World!\n"))
if err != nil {
fmt.Println("[ERROR] Writing:", err)
}
err = zipWriter.Close()
if err != nil {
fmt.Println("[ERROR] Closing zip writer:", err)
}
fmt.Println("[INFO] Number of bytes written:", numberOfBytesWritten)
closeFile(handle)
}
func readZip() {
handle, err := openFile(zipFile)
if err != nil {
fmt.Println("[ERROR] Opening file:", err)
}
zipReader, err := gzip.NewReader(handle)
if err != nil {
fmt.Println("[ERROR] New gzip reader:", err)
}
defer zipReader.Close()
fileContents, err := ioutil.ReadAll(zipReader)
if err != nil {
fmt.Println("[ERROR] ReadAll:", err)
}
fmt.Printf("[INFO] Uncompressed contents: %s\n", fileContents)
// ** Another way of reading the file **
//
// fileInfo, _ := handle.Stat()
// fileContents := make([]byte, fileInfo.Size())
// bytesRead, err := zipReader.Read(fileContents)
// if err != nil {
// fmt.Println("[ERROR] Reading gzip file:", err)
// }
// fmt.Println("[INFO] Number of bytes read from the file:", bytesRead)
closeFile(handle)
}
func openFile(fileToOpen string) (*os.File, error) {
return os.OpenFile(fileToOpen, openFileOptions, openFilePermissions)
}
func closeFile(handle *os.File) {
if handle == nil {
return
}
err := handle.Close()
if err != nil {
fmt.Println("[ERROR] Closing file:", err)
}
}
const openFileOptions int = os.O_CREATE | os.O_RDWR
const openFilePermissions os.FileMode = 0660
有這樣一個完整的例子應該有助於未來的參考。
我不認爲這是一個好例子; 'openFile'應該返回'error'; 「Stat」沒有意義(也可能是沒有價值的!);來自'Write'和'Close'的任何錯誤都被忽略;等等等等。 –
是的,錯誤處理可能會變得有點緊張,但它似乎是被問到的問題的有效答案。 @DaveC – mdwhatcott
@DaveC,在審查了代碼並考慮了您的建議之後,我做了一些重寫。這僅僅是一個例子,但希望編輯改進了最佳實踐。感謝您的反饋。 – SunSparc
這裏的FUNC鍵解壓gzip文件到目標文件:
func UnpackGzipFile(gzFilePath, dstFilePath string) (int64, error) {
gzFile, err := os.Open(gzFilePath)
if err != nil {
return 0, fmt.Errorf("Failed to open file %s for unpack: %s", gzFilePath, err)
}
dstFile, err := os.OpenFile(dstFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660)
if err != nil {
return 0, fmt.Errorf("Failed to create destination file %s for unpack: %s", dstFilePath, err)
}
ioReader, ioWriter := io.Pipe()
go func() { // goroutine leak is possible here
gzReader, _ := gzip.NewReader(gzFile)
// it is important to close the writer or reading from the other end of the
// pipe or io.copy() will never finish
defer func(){
gzFile.Close()
gzReader.Close()
ioWriter.Close()
}()
io.Copy(ioWriter, gzReader)
}()
written, err := io.Copy(dstFile, ioReader)
if err != nil {
return 0, err // goroutine leak is possible here
}
ioReader.Close()
dstFile.Close()
return written, nil
}
我想了解解決方案,你能否詳細說明爲什麼我們需要io.Pipe在這裏? – Sairam
@Sairam io.Pipe允許讀取源文件,gzip源字節和動態寫入目標,無需爲源和字節分配額外的內存。 –
- 1. 軟件包如何在golang中工作
- 2. 如何在golang中更新軟件包?
- 3. 使用crontab來gzip文件
- 4. 如何在獲取golang軟件包時修復錯誤消息「不允許使用內部軟件包」?
- 5. 我如何使用包含額外數據的Gzip文件?
- 6. 更換Golang標準軟件包並在
- 7. Golang - 錯誤'無法找到軟件包'
- 8. Golang 1.6在供應商文件夾中找不到軟件包
- 9. 如何使用Go的openpgp軟件包?
- 10. 如何安裝使用頭文件(RJSONIO,Rcpp)的R軟件包?
- 11. 如何使用僅包含工具的軟件包進行軟件包恢復?
- 12. Golang如何導入沒有gopath的本地軟件包?
- 13. 如何使用GZIP文件在Asp.net中?
- 14. 如何保護iOS軟件包文件
- 15. 如何在使用NuGet安裝軟件包後包含軟件包?
- 16. 如何使用NuGet讀取本地軟件包文件夾?
- 17. 如何使用CPack將文件添加到debian軟件包?
- 18. 如何使用Dockerfile文件運行軟件包安裝
- 19. 如何使用py2exe將軟件包添加到.exe文件中?
- 20. 如何使用軟件包laravel分析?
- 21. 如何使用軟件包:intl
- 22. 如何使用django-registration軟件包?
- 23. 如何使用wx.lib.docview軟件包?
- 24. 如何通過require.js使用軟件包
- 25. 如何使用Monkeyrunner卸載軟件包?
- 26. 如何使用puppet卸載軟件包
- 27. 如何在Erlang中使用軟件包?
- 28. 如何使用aeson-schema軟件包?
- 29. 如何使用「內部」軟件包?
- 30. 如何使用gloss-examples軟件包?
@Nicolai感謝編輯的問題。 – pymd