一个简单、零依赖的 Swift 包,用于读取和写入 cpio
归档文件。灵感来源于 go-cpio。
由 gh-md-toc 创建
文档在此处 查阅。
将此添加到 Package.swift
文件中的 dependencies
数组
.package(url: "https://github.com/LebJe/CPIOArchiveKit.git", from: "0.0.2")
也将其添加到上述文件中的 targets
数组
.product(name: "CPIOArchiveKit", package: "CPIOArchiveKit")
要写入归档文件,你需要一个 CPIOArchiveWriter
var writer = CPIOArchiveWriter()
一旦你有了 writer,你必须创建一个 Header
,来描述你想要添加到归档文件中的文件
var time: Int = 1615929568
// You can also use date
let date: Date = ...
time = Int(date.timeIntervalSince1970)
// File
let header = Header(
name: "hello.txt",
mode: FileMode(0o644, modes: [.regular]),
modificationTime: time
)
// Directory
let header = Header(
name: "dir/",
mode: FileMode(0o644, modes: [.directory]),
modificationTime: time
)
如果你想为上面创建的 Header
提供一个 cpio 校验和,有两种方法可以做到。
// Compute the checksum.
let fileContents: [UInt8] = ...
let checksum = Checksum(bytes: fileContents)
let preComputedChecksum = 123
let checksum = Checksum(sum: preComputedChecksum)
l
一旦你有了 checksum
,将其添加到你的 Header
的 checksum 参数中
Header(..., checksum: checksum, ...)
一旦你有了你的 Header
,你可以将其连同你的文件内容一起写入归档文件
// Without Foundation
var contents = Array("Hello".utf8)
// With Foundation
let myData: Data = "Hello".data(using .utf8)!
contents = Array<UInt8>(myData)
writer.addFile(header: header, contents: contents)
如果你有一个文本文件,请使用 addFile
的重载版本
writer.addFile(header: header, contents: "Hello")
对于目录,省略
addFile
中的contents
参数。对于符号链接,将contents
参数设置为链接指向的文件或目录。
一旦你添加了你的文件,你必须调用 finalize()
来创建归档文件并返回数据
// The binary representation (Array<UInt8>) of the created archive.
let bytes = writer.finalize()
// You convert it to `Data` like this:
let data = Data(bytes)
// And write it:
try data.write(to: URL(fileURLWithPath: "myArchive.cpio"))
如果你想重用 writer
,请调用 finalize(clear: true)
,这将清除 writer
内部的状态。
要读取归档文件,你需要一个 CPIOArchiveReader
// myData is the bytes of the archive.
let myData: Data = ...
let reader = CPIOArchiveReader(archive: Array<UInt8>(myData))
一旦你有了 reader,你可以通过几种方式检索数据
你可以像这样迭代归档文件中的所有文件
for (header, data) in reader {
// `data` is `Array<UInt8>` that contains the raw bytes of the file in the archive.
// `header` is the `Header` that describes the `data`.
// if you know `data` is a `String`, then you can use this initializer:
let str = String(data)
}
当你只需要访问大型归档文件中的少数项目时,通过 subscript
访问数据非常有用
// The subscript provides you with random access to any file in the archive:
let firstFile = reader[0]
let fifthFile = reader[6]
你也可以使用接受 Header
的 subscript 版本 - 当你有一个 Header
,但没有该 header 的索引时非常有用。
let header = reader.headers.first(where: { $0.name.contains(".swift") })!
let data = reader[header: header]
一旦你从 CPIOArchiveReader
中的 Header
中检索到 FileMode
,你就可以访问文件的类型和 UNIX 权限。
let type = header.mode.type
switch type {
case .regular: // Regular file.
case .directory: // Directory.
case .symlink: // Symbolic link.
...
}
要访问 UNIX 权限,请使用 FileMode
中的 permissions
变量。
Examples/CreateReadWrite
:此示例展示了如何使用 CPIOArchiveKit 读取、创建或提取归档文件;或者仅使用 Darwin.C
(macOS)、Glibc
(Linux) 或 ucrt
(Windows(未测试)) 计算归档文件的校验和。CPIOArchiveKit 不依赖于任何库、Foundation
或 Darwin
/Glibc
/ucrt
- 仅依赖于 Swift 标准库。它应该可以在标准库编译的任何平台上编译。
CPIOArchiveKit 目前正在 Windows 上构建,但未经过测试,因为 Swift Package Manager Resources 似乎在 Windows 上不起作用(或不可用)。
在提交之前,请安装 pre-commit、swift-format 和 Prettier,然后安装 pre-commit 钩子
$ brew bundle # install the packages specified in Brewfile
$ pre-commit install
# Commit your changes.
要在其他平台上安装 pre-commit,请参阅文档。