我希望使用 Go 中的 lz4 算法来压缩和解压文件。有没有可用的包可以实现这一功能?我搜索了一下,找到了一个名叫 https://github.com/pierrec/lz4 的包。
由于我是 Go 的新手,无法确定如何使用该包来完成文件的压缩和解压操作。
我需要使用该包将文件压缩成二进制格式,并使用 Go 将二进制文件解压为原始文件。
由于我是 Go 的新手,无法确定如何使用该包来完成文件的压缩和解压操作。
我需要使用该包将文件压缩成二进制格式,并使用 Go 将二进制文件解压为原始文件。
我认为以下示例可以帮助您正确地进行操作。这是使用github.com/pierrec/lz4
包压缩和解压缩的最简单示例。
//compress project main.go
package main
import "fmt"
import "github.com/pierrec/lz4"
var fileContent = `CompressBlock compresses the source buffer starting at soffet into the destination one.
This is the fast version of LZ4 compression and also the default one.
The size of the compressed data is returned. If it is 0 and no error, then the data is incompressible.
An error is returned if the destination buffer is too small.`
func main() {
toCompress := []byte(fileContent)
compressed := make([]byte, len(toCompress))
//compress
l, err := lz4.CompressBlock(toCompress, compressed, 0)
if err != nil {
panic(err)
}
fmt.Println("compressed Data:", string(compressed[:l]))
//decompress
decompressed := make([]byte, len(toCompress))
l, err = lz4.UncompressBlock(compressed[:l], decompressed, 0)
if err != nil {
panic(err)
}
fmt.Println("\ndecompressed Data:", string(decompressed[:l]))
}
package main
import (
"bufio"
"io"
"os"
"github.com/pierrec/lz4"
)
// Compress a file, then decompress it again!
func main() {
compress("./compress-me.txt", "./compressed.txt")
decompress("./compressed.txt", "./decompressed.txt")
}
func compress(inputFile, outputFile string) {
// open input file
fin, err := os.Open(inputFile)
if err != nil {
panic(err)
}
defer func() {
if err := fin.Close(); err != nil {
panic(err)
}
}()
// make a read buffer
r := bufio.NewReader(fin)
// open output file
fout, err := os.Create(outputFile)
if err != nil {
panic(err)
}
defer func() {
if err := fout.Close(); err != nil {
panic(err)
}
}()
// make an lz4 write buffer
w := lz4.NewWriter(fout)
// make a buffer to keep chunks that are read
buf := make([]byte, 1024)
for {
// read a chunk
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
// write a chunk
if _, err := w.Write(buf[:n]); err != nil {
panic(err)
}
}
if err = w.Flush(); err != nil {
panic(err)
}
}
func decompress(inputFile, outputFile string) {
// open input file
fin, err := os.Open(inputFile)
if err != nil {
panic(err)
}
defer func() {
if err := fin.Close(); err != nil {
panic(err)
}
}()
// make an lz4 read buffer
r := lz4.NewReader(fin)
// open output file
fout, err := os.Create(outputFile)
if err != nil {
panic(err)
}
defer func() {
if err := fout.Close(); err != nil {
panic(err)
}
}()
// make a write buffer
w := bufio.NewWriter(fout)
// make a buffer to keep chunks that are read
buf := make([]byte, 1024)
for {
// read a chunk
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
// write a chunk
if _, err := w.Write(buf[:n]); err != nil {
panic(err)
}
}
if err = w.Flush(); err != nil {
panic(err)
}
}
package main
import (
// "bytes"
"flag"
"fmt"
"io"
"log"
"os"
"path"
"runtime"
"strings"
"github.com/pierrec/lz4"
)
func main() {
// Process command line arguments
var (
blockMaxSizeDefault = 4 << 20
flagStdout = flag.Bool("c", false, "output to stdout")
flagDecompress = flag.Bool("d", false, "decompress flag")
flagBlockMaxSize = flag.Int("B", blockMaxSizeDefault, "block max size [64Kb,256Kb,1Mb,4Mb]")
flagBlockDependency = flag.Bool("BD", false, "enable block dependency")
flagBlockChecksum = flag.Bool("BX", false, "enable block checksum")
flagStreamChecksum = flag.Bool("Sx", false, "disable stream checksum")
flagHighCompression = flag.Bool("9", false, "enabled high compression")
)
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage:\n\t%s [arg] [input]...\n\tNo input means [de]compress stdin to stdout\n\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
fmt.Println("output to stdout ", *flagStdout)
fmt.Println("Decompress", *flagDecompress)
// Use all CPUs
runtime.GOMAXPROCS(runtime.NumCPU())
zr := lz4.NewReader(nil)
zw := lz4.NewWriter(nil)
zh := lz4.Header{
BlockDependency: *flagBlockDependency,
BlockChecksum: *flagBlockChecksum,
BlockMaxSize: *flagBlockMaxSize,
NoChecksum: *flagStreamChecksum,
HighCompression: *flagHighCompression,
}
worker := func(in io.Reader, out io.Writer) {
if *flagDecompress {
fmt.Println("\n Decompressing the data")
zr.Reset(in)
if _, err := io.Copy(out, zr); err != nil {
log.Fatalf("Error while decompressing input: %v", err)
}
} else {
zw.Reset(out)
zw.Header = zh
if _, err := io.Copy(zw, in); err != nil {
log.Fatalf("Error while compressing input: %v", err)
}
}
}
// No input means [de]compress stdin to stdout
if len(flag.Args()) == 0 {
worker(os.Stdin, os.Stdout)
os.Exit(0)
}
// Compress or decompress all input files
for _, inputFileName := range flag.Args() {
outputFileName := path.Clean(inputFileName)
if !*flagStdout {
if *flagDecompress {
outputFileName = strings.TrimSuffix(outputFileName, lz4.Extension)
if outputFileName == inputFileName {
log.Fatalf("Invalid output file name: same as input: %s", inputFileName)
}
} else {
outputFileName += lz4.Extension
}
}
inputFile, err := os.Open(inputFileName)
if err != nil {
log.Fatalf("Error while opening input: %v", err)
}
outputFile := os.Stdout
if !*flagStdout {
outputFile, err = os.Create(outputFileName)
if err != nil {
log.Fatalf("Error while opening output: %v", err)
}
}
worker(inputFile, outputFile)
inputFile.Close()
if !*flagStdout {
outputFile.Close()
}
}
}
示例输入
运行 compress.go 文件,使用 -9=true 参数压缩 sample.txt 文件。
我也是Go的新手,使用github.com/pierrec/lz4
时遇到了一些困难。
我的误解在于,在NewWriter
上调用Close()
是不可选的,如果不这样做,将导致错误的结果。(我花了很多时间来思考这是否是可选的和最佳实践,就像关闭文件处理程序、网络连接等一样)
我编写了两个压缩/解压缩的包装器版本。
首先,是通用的读取器/写入器方法(类似于README上的示例,但没有管道)[playground]:
func compress(r io.Reader, w io.Writer) error {
zw := lz4.NewWriter(w)
_, err := io.Copy(zw, r)
if err != nil {
return err
}
// Closing is *very* important
return zw.Close()
}
func decompress(r io.Reader, w io.Writer) error {
zr := lz4.NewReader(r)
_, err := io.Copy(w, zr)
return err
}
func compress(in []byte) ([]byte, error) {
r := bytes.NewReader(in)
w := &bytes.Buffer{}
zw := lz4.NewWriter(w)
_, err := io.Copy(zw, r)
if err != nil {
return nil, err
}
// Closing is *very* important
if err := zw.Close(); err != nil {
return nil, err
}
return w.Bytes(), nil
}
func decompress(in []byte) ([]byte, error) {
r := bytes.NewReader(in)
w := &bytes.Buffer{}
zr := lz4.NewReader(r)
_, err := io.Copy(w, zr)
if err != nil {
return nil, err
}
return w.Bytes(), nil
}
decompressed := make([]byte, len(toCompress))
并且我从中得到了短缓冲区错误,我理解缓冲区不够。请帮帮我... - Dharani Dharanl,err:= lz4.CompressBlock(toCompress,compressed,[]int {0})
|compressed = compressed [: l]
然后您可以按原样使用它进行解压缩l,err = lz4.UncompressBlock(compressed,decompressed)
。 - Tullochgorum