zlib 包
介绍
提供流式压缩和解压功能,支持从输入流读取数据,将其压缩或解压,并写入字节数组,或从字节数组中读取数据,将其压缩或解压,并写入输出流。
压缩和解压使用自研 deflate 算法,压缩和解压数据格式支持 gzip 格式和 deflate raw 格式。
压缩时可指定压缩等级,支持默认快速、默认、高压缩率三个等级,压缩速度依次下降,压缩率依次提升。
主要接口
enum WrapType
public enum WrapType {
| DeflateFormat
| GzipFormat
}
该枚举类用于表示压缩数据格式,目前支持 DeflateFormat
和 GzipFormat
两种格式。
DeflateFormat
DeflateFormat
功能:构造一个表示 Deflate
压缩数据格式的枚举实例。
GzipFormat
GzipFormat
功能:构造一个表示 Gzip
压缩数据格式的枚举实例。
enum CompressLevel
public enum CompressLevel {
| BestSpeed
| DefaultCompression
| BestCompression
}
该枚举类用于表示压缩等级,压缩等级决定了压缩率和压缩速度,目前支持三种压缩等级,压缩率由小到大,压缩速度由快到慢依次为:BestSpeed
、DefaultCompression
、 BestCompression
。
BestSpeed
BestSpeed
功能:构造一个压缩等级枚举实例,表示压缩速度最快,压缩率相对较低。
DefaultCompression
DefaultCompression
功能:构造一个压缩等级枚举实例,表示默认压缩等级。
BestCompression
BestCompression
功能:构造一个压缩等级枚举实例,表示压缩率最高,压缩速度相对降低。
class CompressInputStream
public class CompressInputStream <: InputStream {
public init(inputStream: InputStream, wrap!: WrapType = DeflateFormat, compressLevel!: CompressLevel = DefaultCompression, bufLen!: Int64 = 512)
}
该类实现了一个压缩输入流。可将其绑定到指定的 InputStream
类型输入流,读取、压缩其中的数据,并将压缩后数据输出到指定字节数组。
init
public init(inputStream: InputStream, wrap!: WrapType = DeflateFormat, compressLevel!: CompressLevel = DefaultCompression, bufLen!: Int64 = 512)
功能:构造一个压缩输入流。需绑定一个输入流,可设置压缩数据格式、压缩等级、内部缓冲区大小(每次从输入流中读取多少数据进行压缩)。
参数:
inputStream
:待压缩的输入流wrap
:压缩数据格式,默认值为DeflateFormat
compressLevel
:压缩等级,默认值为DefaultCompression
bufLen
:输入流缓冲区的大小,默认 512 字节
异常:
ZlibException
:如果bufLen
小于等于 0,输入流分配内存失败,或压缩资源初始化失败,抛出异常
func read
public func read(outBuf: Array<Byte>): Int64
功能:从绑定的输入流中读取数据并压缩,压缩后数据放入指定的字节数组中。
参数:
outBuf
:用来存放压缩后数据的缓冲区
返回值:如果压缩成功,返回压缩后字节数,如果绑定的输入流中数据已经全部压缩完成,或者该压缩输入流被关闭,返回 0
异常:
ZlibException
:当outBuf
为空,或压缩数据失败,抛出异常
func close
public func close(): Unit
功能:关闭压缩输入流。当前 CompressInputStream 实例使用完毕后必须调用此接口来释放其所占内存资源,以免造成内存泄漏。调用该函数前需确保 read 函数已返回 0,否则可能导致绑定的 InputStream 并未被全部压缩。
异常:
ZlibException
:如果释放压缩资源失败,抛出异常
class CompressOutputStream
public class CompressOutputStream <: OutputStream {
public init(outputStream: OutputStream, wrap!: WrapType = DeflateFormat, compressLevel!: CompressLevel = DefaultCompression, bufLen!: Int64 = 512)
}
该类实现了一个压缩输出流。可将其绑定到指定的 OutputStream
类型输出流,读取、压缩指定字节数组中的数据,并将压缩后数据输出到绑定的输出流。
init
public init(outputStream: OutputStream, wrap!: WrapType = DeflateFormat, compressLevel!: CompressLevel = DefaultCompression, bufLen!: Int64 = 512)
功能:构造一个压缩输出流,需绑定一个输出流,可设置压缩数据类型、压缩等级、内部缓冲区大小(每得到多少压缩后数据往输出流写一次)
参数:
outputStream
:绑定的输出流,压缩后数据将写入该输出流wrap
:压缩数据格式,默认值为DeflateFormat
compressLevel
:压缩等级,默认值为DefaultCompression
bufLen
:输出流缓冲区的大小,默认 512 字节
异常:
ZlibException
:如果bufLen
小于等于 0,输出流分配内存失败,或压缩资源初始化失败,抛出异常
func write
public func write(inBuf: Array<Byte>): Unit
功能:将指定字节数组中的数据进行压缩,并写入输出流,当数据全部压缩完成并写入输出流,函数返回。
参数:
inBuf
:待压缩的字节数组
异常:
ZlibException
:如果当前压缩输出流已经被关闭,或压缩数据失败,抛出异常
func flush
public func flush(): Unit
功能:刷新压缩输出流。将内部缓冲区里已压缩的数据刷出并写入绑定的输出流,然后刷新绑定的输出流。
异常:
ZlibException
:如果当前压缩输出流已经被关闭,抛出异常
func close
public func close(): Unit
功能:关闭当前压缩输出流实例。写入剩余压缩数据(包括缓冲区中数据,以及压缩尾部信息),并释放其所占内存资源。当前压缩输出流使用完毕后必须调用此接口来释放其所占内存资源,以免造成内存泄漏。在调用 close 函数前,绑定的输出流里已写入的数据并不是一段完整的压缩数据,调用 close 函数后,才会把剩余压缩数据写入绑定的输出流,使其完整。
异常:
ZlibException
:如果当前压缩输出流已经被关闭,或释放压缩资源失败,抛出异常
class DecompressInputStream
public class DecompressInputStream <: InputStream {
public init(inputStream: InputStream, wrap!: WrapType = DeflateFormat, bufLen!: Int64 = 512)
}
该类实现了一个解压输入流。可将其绑定到指定的 InputStream
类型输入流,读取、解压其中的数据,并将解压后数据输出到指定字节数组。
init
public init(inputStream: InputStream, wrap!: WrapType = DeflateFormat, bufLen!: Int64 = 512)
功能:构造一个解压输入流。需绑定一个输入流,可设置待解压数据格式、内部缓冲区大小(每次从输入流中读取多少数据进行解压)。
参数:
inputStream
:待压缩的输入流wrap
:待解压数据格式,默认值为DeflateFormat
bufLen
:输入流缓冲区的大小,默认 512 字节
异常:
ZlibException
:如果bufLen
小于等于 0,输入流分配内存失败,或待解压资源初始化失败,抛出异常
func read
public func read(outBuf: Array<Byte>): Int64
功能:从绑定的输入流中读取数据并解压,解压后数据放入指定的字节数组中。
参数:
outBuf
:用来存放解压后数据的缓冲区
返回值:如果解压成功,返回解压后字节数,如果绑定的输入流中数据已经全部解压完成,或者该解压输入流被关闭,返回 0
异常:
ZlibException
:当outBuf
为空,或解压数据失败,抛出异常
func close
public func close(): Unit
功能:关闭解压输入流。当前 DecompressInputStream
实例使用完毕后必须调用此接口来释放其所占内存资源,以免造成内存泄漏。调用该函数前需确保 read
函数已返回 0,否则可能导致绑定的 InputStream
并未被全部解压。
异常:
ZlibException
,如果释放解压资源失败,抛出异常
class DecompressOutputStream
public class DecompressOutputStream <: OutputStream {
public init(outputStream: OutputStream, wrap!: WrapType = DeflateFormat, bufLen!: Int64 = 512)
}
该类实现了一个解压输出流。可将其绑定到指定的 OutputStream
类型输出流,读取、解压指定字节数组中的数据,并将解压后数据输出到绑定的输出流。
init
public init(outputStream: OutputStream, wrap!: WrapType = DeflateFormat, bufLen!: Int64 = 512)
功能:构造一个解压输出流,需绑定一个输出流,可设置压缩数据类型、压缩等级、内部缓冲区大小(解压后数据会存入内部缓冲区,缓冲区存满后再写到输出流)。
参数:
outputStream
:绑定的输出流,解压后数据将写入该输出流wrap
:待解压数据格式,默认值为DeflateFormat
bufLen
:输出流缓冲区的大小,默认 512 字节
异常:
ZlibException
:如果bufLen
小于等于 0,输出流分配内存失败,或解压资源初始化失败,抛出异常
func write
public func write(inBuf: Array<Byte>): Unit
功能:将指定字节数组中的数据进行解压,并写入输出流,当数据全部解压完成并写入输出流,函数返回。
参数:
inBuf
:待解压的字节数组
异常:
ZlibException
:如果当前解压输出流已经被关闭,或解压数据失败,抛出异常
func flush
public func flush(): Unit
功能:刷新解压输出流。将内部缓冲区里已解压的数据刷出并写入绑定的输出流,然后刷新绑定的输出流。
异常:
ZlibException
:如果当前解压输出流已经被关闭,抛出异常
func close
public func close(): Unit
功能:关闭当前解压输出流实例。写入剩余解压后数据,并释放其所占内存资源。当前压缩输出流使用完毕后必须调用此接口来释放其所占内存资源,以免造成内存泄漏。如果之前 write
函数已处理的压缩数据不完整,调用 close
函数时会因为解压数据不全而抛出异常。
异常:
ZlibException
:如果当前压缩输出流已经被关闭,通过write
函数传入的待解压数据不完整,或释放压缩资源失败,抛出异常
class ZlibException
public class ZlibException <: Exception {
public init(message: String)
}
zlib
包的异常类。
init
public init(message: String)
功能:创建 ZlibException
实例。
参数:
message
:异常提示信息
示例
Gzip 格式数据的压缩和解压
from compress import zlib.*
from std import fs.*
main() {
var arr: Array<Byte> = Array<Byte>(1024 * 1024, {i => UInt8(i % 256)})
File.writeTo("./zlib.txt", arr, openOption: Create(false))
if (compressFile("./zlib.txt", "./zlib_copmressed.zlib") <= 0) {
println("Failed to compress file!")
}
if (decompressFile("./zlib_copmressed.zlib", "./zlib_decopmressed.txt") != arr.size) {
println("Failed to decompress file!")
}
if (compareFile("./zlib.txt", "./zlib_decopmressed.txt")) {
println("success")
} else {
println("failed")
}
File.delete("./zlib.txt")
File.delete("./zlib_copmressed.zlib")
File.delete("./zlib_decopmressed.txt")
return 0
}
func compressFile(srcFileName: String, destFileName: String): Int64 {
var count: Int64 = 0
var srcFile: File = File(srcFileName, OpenOption.Open(true, false))
var destFile: File = File(destFileName, OpenOption.Create(false))
var tempBuf: Array<UInt8> = Array<UInt8>(1024, item: 0)
var compressOutputStream: CompressOutputStream = CompressOutputStream(destFile, wrap: GzipFormat, bufLen: 10000)
while (true) {
var readNum = srcFile.read(tempBuf)
if (readNum > 0) {
compressOutputStream.write(tempBuf.slice(0, readNum).toArray())
count += readNum
} else {
break
}
}
compressOutputStream.flush()
compressOutputStream.close()
srcFile.close()
destFile.close()
return count
}
func decompressFile(srcFileName: String, destFileName: String): Int64 {
var count: Int64 = 0
var srcFile: File = File(srcFileName, OpenOption.Open(true, false))
var destFile: File = File(destFileName, OpenOption.Create(false))
var tempBuf: Array<UInt8> = Array<UInt8>(1024, item: 0)
var decompressInputStream: DecompressInputStream = DecompressInputStream(srcFile, wrap: GzipFormat, bufLen: 10000)
while (true) {
var readNum = decompressInputStream.read(tempBuf)
if (readNum <= 0) {
break
}
destFile.write(tempBuf.slice(0, readNum).toArray())
count += readNum
}
decompressInputStream.close()
srcFile.close()
destFile.close()
return count
}
func compareFile(fileName1: String, fileName2: String): Bool {
return File.readFrom(fileName1) == File.readFrom(fileName2)
}
运行结果:
success
Deflate 格式数据的压缩和解压
from compress import zlib.*
from std import fs.*
main() {
var arr: Array<Byte> = Array<Byte>(1024 * 1024, {i => UInt8(i % 256)})
File.writeTo("./zlib1.txt", arr, openOption: Create(false))
if (compressFile("./zlib1.txt", "./zlib_copmressed1.zlib") <= 0) {
println("Failed to compress file!")
}
if (decompressFile("./zlib_copmressed1.zlib", "./zlib_decopmressed1.txt") != arr.size) {
println("Failed to decompress file!")
}
if (compareFile("./zlib1.txt", "./zlib_decopmressed1.txt")) {
println("success")
} else {
println("failed")
}
File.delete("./zlib1.txt")
File.delete("./zlib_copmressed1.zlib")
File.delete("./zlib_decopmressed1.txt")
return 0
}
func compressFile(srcFileName: String, destFileName: String): Int64 {
var count: Int64 = 0
var srcFile: File = File(srcFileName, OpenOption.Open(true, false))
var destFile: File = File(destFileName, OpenOption.Create(false))
var tempBuf: Array<UInt8> = Array<UInt8>(1024, item: 0)
var compressOutputStream: CompressOutputStream = CompressOutputStream(destFile, wrap: DeflateFormat)
while (true) {
var readNum = srcFile.read(tempBuf)
if (readNum > 0) {
compressOutputStream.write(tempBuf.slice(0, readNum).toArray())
count += readNum
} else {
break
}
}
compressOutputStream.flush()
compressOutputStream.close()
srcFile.close()
destFile.close()
return count
}
func decompressFile(srcFileName: String, destFileName: String): Int64 {
var count: Int64 = 0
var srcFile: File = File(srcFileName, OpenOption.Open(true, false))
var destFile: File = File(destFileName, OpenOption.Create(false))
var tempBuf: Array<UInt8> = Array<UInt8>(1024, item: 0)
var decompressInputStream: DecompressInputStream = DecompressInputStream(srcFile, wrap: DeflateFormat)
while (true) {
var readNum = decompressInputStream.read(tempBuf)
if (readNum <= 0) {
break
}
destFile.write(tempBuf.slice(0, readNum).toArray())
count += readNum
}
decompressInputStream.close()
srcFile.close()
destFile.close()
return count
}
func compareFile(fileName1: String, fileName2: String): Bool {
return File.readFrom(fileName1) == File.readFrom(fileName2)
}
运行结果
success