强大的跨平台归档工具:Archiver 4.0

强大的跨平台归档工具:Archiver 4.0

archiverEasily create & extract archives, and compress & decompress files of various formats项目地址:https://gitcode.com/gh_mirrors/ar/archiver

Archiver 4.0 是一款卓越的跨平台、多格式存档工具和Go语言库,为您提供了一个通用的替代方案,可以取代多种特定于平台或格式的存档工具。尽管当前处于ALPHA阶段,但其核心库API已经相当稳定。

功能概览

  • 基于流的API设计
  • 自动识别档案和压缩格式:
    • 通过文件名
    • 通过头部信息
  • 使用统一的方式遍历目录、存档文件和任何其他作为io/fs文件系统操作的对象:
    • DirFS
    • FileFS
    • ArchiveFS
  • 文件压缩和解压
  • 创建和提取档案文件
  • 深入到档案文件中进行遍历
  • 从档案中仅提取所需文件
  • 向.tar和.zip档案插入(追加)内容
  • 读取受密码保护的7-Zip文件
  • 支持多种存档和压缩格式
  • 可扩展性(只需注册即可添加更多格式)
  • 跨平台静态二进制
  • 纯Go实现(无cgo)
  • 多线程Gzip
  • 调整压缩级别
  • 在不重新压缩的情况下将已压缩文件添加到zip档案
  • 打开密码保护的RAR档案

支持的压缩格式

  • brotli (.br)
  • bzip2 (.bz2)
  • flate (.zip)
  • gzip (.gz)
  • lz4 (.lz4)
  • lzip (.lz)
  • snappy (.sz)
  • xz (.xz)
  • zlib (.zz)
  • zstandard (.zst)

支持的档案格式

  • .zip
  • .tar(包括任何压缩变体如.tar.gz)
  • .rar(只读)
  • .7z(只读)

tar文件可以选择使用任何压缩格式进行压缩。

命令行使用

即将在v4版本提供。现在您可以查看最后一个v3版本的文档以了解更多信息。

库使用

要获取Archiver 4.0库,请执行以下命令:

$ go get github.com/mholt/archiver/v4

创建归档

创建归档时,您不需要实际的磁盘或存储设备,只需要一个File结构体列表。不过,从磁盘上创建归档非常常见,您可以使用FilesFromDisk()函数从磁盘映射文件到归档中的路径。然后定义并自定义格式类型。

例如,我们将4个文件和一个目录(及其所有内容递归地包含)添加到.tar.gz文件中:

// 映射磁盘上的文件到归档中的路径
files, err := archiver.FilesFromDisk(nil, map[string]string{
	"/path/on/disk/file1.txt": "file1.txt",
	"/path/on/disk/file2.txt": "subfolder/file2.txt",
	"/path/on/disk/file3.txt": "",              // 放在根目录下为file3.txt
	"/path/on/disk/file4.txt": "subfolder/",    // 放在子文件夹内为file4.txt
	"/path/on/disk/folder":    "Custom Folder", // 内容递归添加
})
if err != nil {
	return err
}

// 创建输出文件
out, err := os.Create("example.tar.gz")
if err != nil {
	return err
}
defer out.Close()

// 使用CompressedArchive类型来gzip一个tarball
// (压缩不是必需的;你可以直接使用Tar)
format := archiver.CompressedArchive{
	Compression: archiver.Gz{},
	Archival:    archiver.Tar{},
}

// 创建归档
err = format.Archive(context.Background(), out, files)
if err != nil {
	return err
}

FilesFromDisk()的第一个参数是一个可选的选项结构,用于定制如何添加文件。

提取归档

提取归档、从归档中提取以及遍历归档都使用相同的功能。

只需使用您的格式类型(如Zip)调用Extract()。传入上下文(用于取消),输入流,您希望从归档中提取的文件列表,以及处理每个文件的回调函数。

如果要提取所有文件,将文件路径列表设置为nil。

// 将要用来读取输入流的类型
format := archiver.Zip{}

// 我们想从归档中提取哪些文件;
// 目录会包含所有内容,除非我们的处理器返回fs.SkipDir
// (将其设置为nil以从归档中遍历所有文件)
fileList := []string{"file1.txt", "subfolder"}

handler := func(ctx context.Context, f archiver.File) error {
	// 对文件进行操作
	return nil
}

err := format.Extract(ctx, input, fileList, handler)
if err != nil {
	return err
}

格式识别

对于具有未知内容的输入流,无需担心。Archiver可以为您识别。它基于文件名和/或头信息进行匹配:

format, input, err := archiver.Identify("filename.tar.zst", input)
if err != nil {
	return err
}
// 现在可以根据需要断言format;
// 请确保使用返回的流重新读取Identify期间消耗的字节

// 想要提取某些东西吗?
if ex, ok := format.(archiver.Extractor); ok {
	// ... 继续提取
}

// 或者可能是压缩的,你想解压缩?
if decom, ok := format.(archiver.Decompressor); ok {
	rc, err := decom.OpenReader(unknownFile)
	if err != nil {
		return err
	}
	defer rc.Close()

	// 从rc读取以获得解压缩数据
}

Identify()通过从流的开头读取任意数量的字节(足以检查文件头)。它缓冲这些字节,并返回一个新的读取器,让您重新读取它们。

虚拟文件系统

这是我最喜欢的功能。

假设您有一个文件。它可以是磁盘上的一个目录,一个归档,一个压缩归档,或者一个普通的文件。您并不关心它的具体类型,只想统一地使用它。

只需使用Archiver创建一个文件系统:

// filename可以是:
// - 目录("/home/you/Desktop")
// - 归档("example.zip")
// - 压缩归档("example.tar.gz")
// - 普通文件("example.txt")
// - 压缩的普通文件("example.txt.gz")
fsys, err := archiver.FileSystem(filename)
if err != nil {
	return err
}

这是一个完整的fs.FS,因此无论输入是什么类型的文件,您都可以打开文件和读取目录。

例如,打开特定文件:

f, err := fsys.Open("file")
if err != nil {
	return err
}
defer f.Close()

如果是常规文件,可以从它那里读取。如果是压缩文件,读取会自动解压缩。

如果是目录,可以列出其内容:

if dir, ok := f.(fs.ReadDirFile); ok {
	// 0获取所有条目,但可以传> 0进行分页
	entries, err := dir.ReadDir(0)
	if err != nil {
		return err
	}
	for _, e := range entries {
		fmt.Println(e.Name())
	}
}

或者通过这种方式获取目录列表:

entries, err := fsys.ReadDir("Playlists")
if err != nil {
	return err
}
for _, e := range entries {
	fmt.Println(e.Name())
}

或者,如果您想要遍历整个文件系统,但跳过名为.git的目录:

err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
	if err != nil {
		return err
	}
	if path == ".git" {
		return fs.SkipDir
	}
	fmt.Println("Walking:", path, "Dir?", d.IsDir())
	return nil
})
if err != nil {
	return err
}
结合http.FileServer使用

它可以与http.FileServer一起使用,在浏览器中浏览归档和目录。但是,由于http.FileServer的工作方式,直接使用http.FileServer与压缩文件一起使用是不可行的;应像下面这样包裹:

fileServer := http.FileServer(http.FS(archiveFS))
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
	// 禁用范围请求
	writer.Header().Set("Accept-Ranges", "none")
	request.Header.Del("Range")

	// 禁用内容类型嗅探
	ctype :=

archiverEasily create & extract archives, and compress & decompress files of various formats项目地址:https://gitcode.com/gh_mirrors/ar/archiver

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单迅秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值