When I first needed to read a
.7z archive from Go, I used the external
7z program. Today,
github.com/bodgit/sevenzip provides a pure Go reader, so an external executable is no longer the only option.
Read an archive in pure Go
Add the dependency to your module:
go get github.com/bodgit/sevenzip
This complete program streams each regular file to stdout. It does not create files using archive-controlled paths or load each entire file into memory.
package main
import (
"fmt"
"io"
"log"
"os"
"github.com/bodgit/sevenzip"
)
func readArchive(path string) error {
archive, err := sevenzip.OpenReader(path)
if err != nil {
return err
}
defer archive.Close()
for _, file := range archive.File {
if !file.FileInfo().Mode().IsRegular() {
continue
}
fmt.Fprintf(os.Stderr, "reading %s\n", file.Name)
reader, err := file.Open()
if err != nil {
return err
}
_, copyErr := io.Copy(os.Stdout, reader)
closeErr := reader.Close()
if copyErr != nil {
return copyErr
}
if closeErr != nil {
return closeErr
}
}
return nil
}
func main() {
if err := readArchive("foo.7z"); err != nil {
log.Fatal(err)
}
}
Close each entry before moving on; deferring all entry closes until the end can retain resources unnecessarily. See the
package documentation for supported compression methods, encrypted archives, and the
io/fs interface.
For untrusted archives, impose limits on total decompressed bytes, entry count, and processing time. Streaming avoids a large output buffer, but does not by itself prevent decompression bombs. If you extract to disk, reject absolute paths and traversal components, and prevent symlinks from escaping the destination. Go’s
os.Root, introduced in Go 1.24 and expanded in Go 1.25, provides operations confined to a directory tree.
Use the external 7-Zip program
My original lzmadec wrapper exposed an io.ReadCloser backed by a 7z child process. That was a practical workaround in 2015, but its old examples should not be used as current library installation instructions.
The same technique can still be implemented with
exec.Cmd from
os/exec: 7-Zip’s
-so option sends decompressed data to stdout. Install the
7-Zip command-line tools, start the process, stream its stdout, and call
Wait to check its exit status and release resources. Read stderr concurrently if using a separate pipe. If the caller stops reading early, cancel the process and still wait for it.
See
Advanced command execution in Go for subprocess handling. Pure Go is simpler to deploy when the reader supports the archive’s compression and encryption methods.