它不是围绕着 LZMA SDK C 部分的又一次包装,有着它的所有限制。
基于 C++ LZMA SDK 版本 19.00(1900 - 目前的最新版本)并针对 iOS 和 Mac OS 平台进行了修补。
可以与 Swift 和 Objective-C 一起使用。
描述
它不是围绕着 LZMA SDK C 部分的又一次包装,有着它的所有限制。它基于 C++ LZMA SDK 版本 19.00(1900 - 目前的最新版本)并针对 iOS 和 Mac OS 平台进行了修补。
主要优点是
- 列出、提取 7z 文件(Lzma & Lzma2 压缩方法)。
- 列出、提取 加密的(受密码保护的)7z 文件(Lzma & Lzma2 压缩方法)。
- 列出、提取 加密的(受密码保护的)+ 加密头部(无可见内容,文件列表,无密码)7z 文件(Lzma & Lzma2 压缩方法)。
- 创建 7z 归档(Lzma & Lzma2 压缩方法)。
- 创建 加密的(受密码保护的)7z 归档(Lzma & Lzma2 压缩方法)。
- 创建 加密的(受密码保护的)+ 加密头部(无可见内容,文件列表,无密码)7z 归档(Lzma & Lzma2 压缩方法)。
- 在列出/提取过程中管理内存分配。请参见以下部分:调整速度、性能和磁盘 IO 操作。
- 针对小于 500Kb 的列出/提取进行优化,可以轻松地更改运行时(无硬编码定义)。请参见以下部分:调整速度、性能和磁盘 IO 操作。
- 管理 IO 读写操作,也可以轻松地更改运行时(无硬编码定义)。请参见以下部分:调整速度、性能和磁盘 IO 操作。
- 跟踪平滑的进度,这是通过先前的操作成为可能的。
- 支持读取和提取大于 4GB 大小的存档文件。
- UTF8 支持。
- 使用 Lzma2 对单个 NSData 对象提供额外的压缩/解压缩功能。
CocoaPods 安装
使用Podfile
use_frameworks!
platform :ios, '9.0'
target '<REPLACE_WITH_YOUR_TARGET>' do
pod 'LzmaSDK-ObjC', :inhibit_warnings => true
end
使用框架(动态链接)将 Lzma 编解码器代码包含到您的应用程序中。
示例 Swift 和 Objective-C
列出和提取
使用归档路径和/或归档类型创建和配置读取器,可选代理和可选密码获取器块,在加密归档的情况下
Swift
import LzmaSDK_ObjC
...
// select full path to archive file with 7z extension
let archivePath = "path to archive"
// 1.1 Create reader object.
let reader = LzmaSDKObjCReader(fileURL: NSURL(fileURLWithPath: archivePath)
// 1.2 Or create with predefined archive type if path doesn't containes suitable extension
let reader = LzmaSDKObjCReader(fileURL: NSURL(fileURLWithPath: archivePath), andType: LzmaSDKObjCFileType7z)
// Optionaly: assign delegate for tracking extract progress.
reader.delegate = self
// If achive encrypted - define password getter handler.
// NOTES:
// - Encrypted file needs password for extract process.
// - Encrypted file with encrypted header needs password for list(iterate) and extract archive items.
reader.passwordGetter = {
return "password to my achive"
}
...
// Delegate extension
extension ReaderDelegateObject: LzmaSDKObjCReaderDelegate {
func onLzmaSDKObjCReader(reader: LzmaSDKObjCReader, extractProgress progress: Float) {
print("Reader progress: \(progress) %")
}
}
Objective-C
// select full path to archive file with 7z extension
NSString * archivePath = <path to archive>;
// 1.1 Create and hold strongly reader object.
self.reader = [[LzmaSDKObjCReader alloc] initWithFileURL:[NSURL fileURLWithPath:archivePath]];
// 1.2 Or create with predefined archive type if path doesn't containes suitable extension
self.reader = [[LzmaSDKObjCReader alloc] initWithFileURL:[NSURL fileURLWithPath:archivePath]
andType:LzmaSDKObjCFileType7z];
// Optionaly: assign weak delegate for tracking extract progress.
_reader.delegate = self;
// If achive encrypted - define password getter handler.
// NOTES:
// - Encrypted file needs password for extract process.
// - Encrypted file with encrypted header needs password for list(iterate) and extract archive items.
_reader.passwordGetter = ^NSString*(void){
return @"password to my achive";
};
打开存档,例如找出存档类型、定位解码器并读取存档标题
Swift
// Try open archive.
do {
try reader.open()
}
catch let error as NSError {
print("Can't open archive: \(error.localizedDescription) ")
}
Objective-C
// Open archive, with or without error. Error can be nil.
NSError * error = nil;
if (![_reader open:&error]) {
NSLog(@"Open error: %@", error);
}
NSLog(@"Open error: %@", _reader.lastError);
遍历存档项,选择并存储所需的物品以供未来处理
Swift
var items = [LzmaSDKObjCItem]() // Array with selected items.
// Iterate all archive items, track what items do you need & hold them in array.
reader.iterateWithHandler({(item: LzmaSDKObjCItem, error: NSError?) -> Bool in
items.append(item) // if needs this item - store to array.
return true // true - continue iterate, false - stop iteration
})
Objective-C
NSMutableArray * items = [NSMutableArray array]; // Array with selected items.
// Iterate all archive items, track what items do you need & hold them in array.
[_reader iterateWithHandler:^BOOL(LzmaSDKObjCItem * item, NSError * error){
NSLog(@"\n%@", item);
if (item) [items addObject:item]; // if needs this item - store to array.
return YES; // YES - continue iterate, NO - stop iteration
}];
NSLog(@"Iteration error: %@", _reader.lastError);
提取或测试存档项
Swift
// Extract selected items from prev. step.
// true - create subfolders structure for the items.
// false - place item file to the root of path(in this case items with the same names will be overwrited automaticaly).
if reader.extract(items, toPath: "/Volumes/Data/1/", withFullPaths: true) {
print("Extract failed: \(reader.lastError?.localizedDescription)")
}
// Test selected items from prev. step.
if reader.test(items) {
print("Test failed: \(reader.lastError?.localizedDescription)")
}
Objective-C
// Extract selected items from prev. step.
// YES - create subfolders structure for the items.
// NO - place item file to the root of path(in this case items with the same names will be overwrited automaticaly).
[_reader extract:items
toPath:@"/extract/path"
withFullPaths:YES];
NSLog(@"Extract error: %@", _reader.lastError);
// Test selected items from prev. step.
[_reader test:items];
NSLog(@"test error: %@", _reader.lastError);
创建7z存档
Swift
// Create writer
let writer = LzmaSDKObjCWriter(fileURL: NSURL(fileURLWithPath: "/Path/MyArchive.7z"))
// Add file data's or paths
writer.addData(NSData(...), forPath: "MyArchiveFileName.txt") // Add file data
writer.addPath("/Path/somefile.txt", forPath: "archiveDir/somefile.txt") // Add file at path
writer.addPath("/Path/SomeDirectory", forPath: "SomeDirectory") // Recursively add directory with all contents
// Setup writer
writer.delegate = self // Track progress
writer.passwordGetter = { // Password getter
return "1234"
}
// Optional settings
writer.method = LzmaSDKObjCMethodLZMA2 // or LzmaSDKObjCMethodLZMA
writer.solid = true
writer.compressionLevel = 9
writer.encodeContent = true
writer.encodeHeader = true
writer.compressHeader = true
writer.compressHeaderFull = true
writer.writeModificationTime = false
writer.writeCreationTime = false
writer.writeAccessTime = false
// Open archive file
do {
try writer.open()
} catch let error as NSError {
print(error.localizedDescription)
}
// Write archive within current thread
writer.write()
// or
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
writer.write()
}
Objective-C
// Create writer
LzmaSDKObjCWriter * writer = [[LzmaSDKObjCWriter alloc] initWithFileURL:[NSURL fileURLWithPath:@"/Path/MyArchive.7z"]];
// Add file data's or paths
[writer addData:[NSData ...] forPath:@"MyArchiveFileName.txt"]; // Add file data
[writer addPath:@"/Path/somefile.txt" forPath:@"archiveDir/somefile.txt"]; // Add file at path
[writer addPath:@"/Path/SomeDirectory" forPath:@"SomeDirectory"]; // Recursively add directory with all contents
// Setup writer
writer.delegate = self; // Track progress
writer.passwordGetter = ^NSString*(void) { // Password getter
return @"1234";
};
// Optional settings
writer.method = LzmaSDKObjCMethodLZMA2; // or LzmaSDKObjCMethodLZMA
writer.solid = YES;
writer.compressionLevel = 9;
writer.encodeContent = YES;
writer.encodeHeader = YES;
writer.compressHeader = YES;
writer.compressHeaderFull = YES;
writer.writeModificationTime = NO;
writer.writeCreationTime = NO;
writer.writeAccessTime = NO;
// Open archive file
NSError * error = nil;
[writer open:&error];
// Write archive within current thread
[writer write];
// or
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[writer write];
});
压缩/解压缩单个数据缓冲区
Swift
// Compress data with compression maximum compression ratio.
let compressedData = LzmaSDKObjCBufferCompressLZMA2(sourceData, 1)
// Decompress previvously compressed data.
let decompressedData = LzmaSDKObjCBufferDecompressLZMA2(compressedData)
Objective-C
// Compress data with compression maximum compression ratio.
NSData * compressedData = LzmaSDKObjCBufferCompressLZMA2(sourceData, 1);
// Decompress previvously compressed data.
NSData * decompressedData = LzmaSDKObjCBufferDecompressLZMA2(compressedData);
调整速度、性能和磁盘IO操作
对LZMA SDK的原始C++部分进行了修补,以获得调整默认(《硬编码》)设置的可能性。对于列表和解压缩功能定义了以下全局变量:kLzmaSDKObjCStreamReadSize
、kLzmaSDKObjCStreamWriteSize
、kLzmaSDKObjCDecoderReadSize
和kLzmaSDKObjCDecoderWriteSize
。这些变量以字节数存储大小值,因此,对于单个读取对象,将分配这4个值的总和。
请注意:与内存操作相比,磁盘IO操作要慢得多,所以请阅读以下情况
switch (<what do I need ?>) {
case <I need faster list and extract>:
//TODO: Increase stream and decoder size of buffers
Result:
1. more allocated memory
2. less IO read/write operations and less delays
3. less smoothed progress
4. more CPU load (do a job, not distracted to read/write data)
break;
case <I need use less memory or more smoothed progress>:
//TODO: Decrease stream and decoder size of buffers
Result:
1. less allocated memory
2. more IO read/write operations and more delays
3. more smoothed progress
4. less CPU load (wait for read/write data)
break;
default:
//TODO: use current settings
break;
};
注意:在创建和使用读取对象之前修改全局变量。
注意:此分配大小不会影响为存档字典分配的内存。
特性列表(待办/完成)
- Lzma/*.7z
- 列表
- 普通存档。《code>tests/files/lzma.7z
- 使用AES256加密的存档。
tests/files/lzma_aes256.7z
- 加密存档 + 加密标题(《无可见内容,无密码》)使用AES256。
tests/files/lzma_aes256_encfn.7z
- 提取
- 普通存档。《code>tests/files/lzma.7z
- 使用AES256加密的存档。
tests/files/lzma_aes256.7z
- 加密存档 + 加密标题(《无可见内容,无密码》)使用AES256。
tests/files/lzma_aes256_encfn.7z
- 创建
- 普通存档。
- 使用AES256加密的存档。
- 加密存档 + 加密标题(《无可见内容,无密码》)使用AES256。
- 列表
- Lzma2/*.7z
- 列表
- 普通存档。《code>tests/files/lzma2.7z
- 使用AES256加密的存档。
tests/files/lzma2_aes256.7z
- 加密存档 + 加密标题(《无可见内容,无密码》)使用AES256。
tests/files/lzma2_aes256_encfn.7z
- 提取
- 普通存档。《code>tests/files/lzma2.7z
- 使用AES256加密的存档。
tests/files/lzma2_aes256.7z
- 加密存档 + 加密标题(《无可见内容,无密码》)使用AES256。
tests/files/lzma2_aes256_encfn.7z
- 创建
- 普通存档。
- 使用AES256加密的存档。
- 加密存档 + 加密标题(《无可见内容,无密码》)使用AES256。
- 列表
- 删除未使用的代码,减少可构建,原始代码的大小。
许可协议
通过使用本软件和相关的文档文件,您同意接受原始LZMA SDK和MIT许可协议(《见下文》)
MIT许可协议(MIT)
版权(c)2015 - 2019 Kulykov Oleh [电子邮箱地址被隐藏]
本协议下任何人可免费获得此软件及其相关的文档文件(统称为“软件”),以无限制地使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许提供软件给他人,以便他们这样做,但受以下条件限制
上述版权声明和本许可声明应包含在软件的所有副本或实质部分中。
软件按“现状”提供,不提供任何类型的保证,无论是明示的还是隐示的,包括但不限于约专卖性、针对特定目的的适用性和非侵权性保证。在任何情况下,无论作者或版权所有者因软件或其使用或其他交易而产生的任何索赔、损害或其他责任,无论是否构成合同、侵权或其他,均不应承担责任。