我是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