platform language Cocoapods Cocoapods SwiftPM compatible GitHub release node-current Build Status Build status

PLzmaSDK 是 (Portable, Patched, Package, cross-P-latform) Lzma SDK。(可移植的、已打补丁的、包,跨平台)Lzma SDK。 基于原始的 LZMA SDK 24.09 版本,并已针对 Unix 平台进行了修补。 适用于所有 Apple 平台(iOS、macOS、tvOS、watchOS)、Android、Windows、Linux 和任何 Unix 系统。

特性/详细描述


可选功能

默认情况下启用所有可选功能,但在构建过程中可以禁用它们,以减小二进制文件的大小,当然,如果您不打算使用它们。

安装


Swift Package Manager

.package(url: "https://github.com/OlehKulykov/PLzmaSDK.git", .exact("1.5.0"))

CocoaPods Podfile (Swift)

use_frameworks!
platform :ios, '11.0'

target '<REPLACE_WITH_YOUR_TARGET>' do
    pod 'PLzmaSDK', '1.5.0'
end

CocoaPods Podfile (Objective-C)

use_frameworks!
platform :ios, '9.0'

target '<REPLACE_WITH_YOUR_TARGET>' do
    pod 'PLzmaSDK-ObjC', '1.5.0'
end

npm 通过 'package.json'

{
  "engines": {
    "node": ">=13.0.0",
    "npm": ">=6.0.0"
  },
  "dependencies": {
    "plzmasdk": "1.5.0"
  }
}

Android NDK

cd <PATH_TO_ANDROID_NDK>
./ndk-build NDK_PROJECT_PATH=<PATH_TO_PLZMASDK>/PLzmaSDK/android

CMake Unix

cd PLzmaSDK
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j4

CMake Windows (MSVC)

cd PLzmaSDK
md build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --config Release --parallel 4

CMake Windows (MinGW)

...
cmake -G"MinGW Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --config Release --parallel 4

示例


提取或测试

打开、列出和选择存档项目以进行提取或测试。

该过程包括四个步骤

  1. 创建一个源输入流,用于读取存档文件内容。 输入流可以使用以下方式创建:
    1. 存档文件的路径。
    2. 内存中的存档文件内容,即使用 const 内存或其副本供内部使用。
    3. 自定义读取/查找回调(仅限 C/C++)。
  2. 创建具有源输入流、存档类型和可选进度代理的解码器。
    1. 可选地,提供密码以打开和列出加密存档,以及用于将来的提取或测试。
  3. 选择存档项目以进行提取或测试。 如果您想处理所有项目(整个存档),则可以跳过此步骤,请参阅下文。
    1. 按原样选择所有存档项目。
    2. 检索项目数,按索引迭代它们,进行过滤和/或选择。
  4. 提取或测试选定的存档项目。 提取过程可以是
    1. 将所有项目提取到目录。 在这种情况下,您可以跳过步骤 3。
    2. 将选定的项目提取到目录。
    3. 将每个项目提取到自定义输出流。 输出流可以是文件或内存。 即,将“项目#1”提取到文件流,将“项目#2”提取到内存流(然后获取提取的内存),依此类推。
Swift
do {
    // 1. Create a source input stream for reading archive file content.
    //  1.1. Create a source input stream with the path to an archive file.
    let archivePath = try Path("path/to/archive.7z")
    let archivePathInStream = try InStream(path: archivePath)

    //  1.2. Create a source input stream with the file content.
    let archiveData = Data(...)
    let archiveDataInStream = try InStream(dataNoCopy: archiveData) // also available Data(dataCopy: Data)

    // 2. Create decoder with source input stream, type of archive and optional delegate.
    let decoder = try Decoder(stream: archiveDataInStream /* archivePathInStream */, fileType: .sevenZ, delegate: self)
    
    //  2.1. Optionaly provide the password to open/list/test/extract encrypted archive items.
    try decoder.setPassword("1234")
    
    let opened = try decoder.open()
    
    // 3. Select archive items for extracting or testing.
    //  3.1. Select all archive items.
    let allArchiveItems = try decoder.items()
    
    //  3.2. Get the number of items, iterate items by index, filter and select items.
    let numberOfArchiveItems = try decoder.count()
    let selectedItemsDuringIteration = try ItemArray(capacity: numberOfArchiveItems)
    let selectedItemsToStreams = try ItemOutStreamArray()
    for itemIndex in 0..<numberOfArchiveItems {
        let item = try decoder.item(at: itemIndex)
        try selectedItemsDuringIteration.add(item: item)
        try selectedItemsToStreams.add(item: item, stream: OutStream()) // to memory stream
    }
    
    // 4. Extract or test selected archive items. The extract process might be:
    //  4.1. Extract all items to a directory. In this case, you can skip the step #3.
    let extracted = try decoder.extract(to: Path("path/outdir"))
    
    //  4.2. Extract selected items to a directory.
    let extracted = try decoder.extract(items: selectedItemsDuringIteration, to: Path("path/outdir"))
    
    //  4.3. Extract each item to a custom out-stream. 
    //       The out-stream might be a file or memory. I.e. extract 'item #1' to a file stream, extract 'item #2' to a memory stream(then take extacted memory) and so on.
    let extracted = try decoder.extract(itemsToStreams: selectedItemsToStreams)
} catch let exception as Exception {
    print("Exception: \(exception)")
}
JavaScript
const plzma = require('plzmasdk');

try {
    // 1. Create a source input stream for reading archive file content.
    //  1.1. Create a source input stream with the path to an archive file.
    const archivePath = plzma.Path(__dirname).append('path/to/archive.7z');
    const archivePathInStream = new plzma.InStream(archivePath /* 'path/to/archive.7z' */);

    //  1.2. Create a source input stream with the file content.
    const archiveData = new ArrayBuffer(...);
    const archiveDataInStream = new plzma.InStream(archiveData);

    // 2. Create decoder with source input stream, type of archive and optional delegate.
    const decoder = new plzma.Decoder(archivePathInStream, plzma.FileType.sevenZ);
    decoder.setProgressDelegate((path, progress) => console.log(`Delegating progress, path: ${path}, progress: ${progress}`) );

    //  2.1. Optionaly provide the password to open/list/test/extract encrypted archive items.
    decoder.setPassword('1234');

    const opened = await decoder.openAsync(); // also available sync. version 'decoder.open()'

    // 3. Select archive items for extracting or testing.
    //  3.1. Select all archive items.
    const allArchiveItems = decoder.items;

    //  3.2. Get the number of items, iterate items by index, filter and select items.
    const selectedItemsDuringIteration = [];
    const selectedItemsToStreams = new Map();
    for (let itemIndex = 0, numberOfArchiveItems = decoder.count; itemIndex <  numberOfArchiveItems; itemIndex++) {
        const item = decoder.itemAt(itemIndex);
        selectedItemsDuringIteration.push(item);
        selectedItemsToStreams.set(item, plzma.OutStream()); // to memory stream
    }
    
    // 4. Extract or test selected archive items. The extract process might be:
    //  4.1. Extract all items to a directory. In this case, you can skip the step #3.
    const extracted = await decoder.extractAsync('path/outdir'); // also available sync. version 'decoder.extract()'
    
    //  4.2. Extract selected items to a directory.
    const extracted = await decoder.extractAsync(selectedItemsDuringIteration, 'path/outdir'); // also available sync. version 'decoder.extract()'
    
    //  4.3. Extract each item to a custom out-stream. 
    //       The out-stream might be a file or memory. I.e. extract 'item #1' to a file stream, extract 'item #2' to a memory stream(then take extacted memory) and so on.
    const extracted = await decoder.extractAsync(selectedItemsToStreams); // also available sync. version 'decoder.extract()'
} catch (error) {
    console.log(`Exception: ${error}`);
}
C++
try {
    // 1. Create a source input stream for reading archive file content.
    //  1.1. Create a source input stream with the path to an archive file.
    Path archivePath("path/to/archive.7z"); // Path(L"C:\\\\path\\to\\archive.7z");
    auto archivePathInStream = makeSharedInStream(archivePath /* std::move(archivePath) */);
    
    //  1.2. Create a source input stream with the file content.
    auto archiveDataInStream = makeSharedInStream(<FILE DATA>, <FILE SIZE>);
    
    // 2. Create decoder with source input stream, type of archive and provide optional delegate.
    auto decoder = makeSharedDecoder(archiveDataInStream, plzma_file_type_7z);
    decoder->setProgressDelegate(this);
    
    //  2.1. Optionaly provide the password to open/list/test/extract encrypted archive items.
    decoder->setPassword("1234"); // decoder->setPassword(L"1234");
        
    bool opened = decoder->open();
    
    // 3. Select archive items for extracting or testing.
    //  3.1. Select all archive items.
    auto allArchiveItems = decoder->items();

    //  3.2. Get the number of items, iterate items by index, filter and select items.
    size_t numberOfArchiveItems = decoder->count();
    auto selectedItemsDuringIteration = makeShared<ItemArray>(numberOfArchiveItems);
    auto selectedItemsToStreams = makeShared<ItemOutStreamArray>();
    for (size_t itemIndex = 0; itemIndex < numberOfArchiveItems; itemIndex++) {
        auto item = decoder->itemAt(itemIndex);
        selectedItemsDuringIteration->push(item /* std::move(item) */);
        selectedItemsToStreams->push(Pair<SharedPtr<Item>, SharedPtr<OutStream> >(item, makeSharedOutStream())); // to memory stream
    }
    
    // 4. Extract or test selected archive items. The extract process might be:
    //  4.1. Extract all items to a directory. In this case, you can skip the step #3.
    bool extracted = decoder->extract(Path("path/outdir"));
    
    //  4.2. Extract selected items to a directory.
    bool extracted = decoder->extract(selectedItemsDuringIteration, Path("path/outdir"));
    
    //  4.3. Extract each item to a custom out-stream. 
    //       The out-stream might be a file or memory. I.e. extract 'item #1' to a file stream, extract 'item #2' to a memory stream(then take extacted memory) and so on.
    bool extracted = decoder->extract(selectedItemsToStreams);
} catch (const Exception & exception) {
    std::cout << "Exception: " << exception.what() << std::endl;
}
C
// 1. Create a source input stream for reading archive file content.
//  1.1. Create a source input stream with the path to an archive file.
plzma_path archivePath = plzma_path_create_with_utf8_string("path/to/archive.7z"); // plzma_path_create_with_wide_string(L"C:\\\\path\\to\\archive.7z");
plzma_in_stream archivePathInStream = plzma_in_stream_create_with_path(&archivePath); // plzma_in_stream_create_with_pathm(...);
plzma_path_release(&archivePath);
plzma_in_stream_release(&archivePathInStream); // when no longer needed

//  1.2. Create a source input stream with the file content in memory.
plzma_in_stream archiveDataInStream = plzma_in_stream_create_with_memory_copy(<FILE DATA>, <FILE SIZE>); // plzma_in_stream_create_with_memory(...);

// 2. Create decoder with source input stream, type of archive, context for optional delegate and provide optional delegate callback.
plzma_decoder decoder = plzma_decoder_create(&archiveDataInStream, plzma_file_type_7z, plzma_context{ nullptr, nullptr }); // C2059 = { .context = nullptr, .deinitializer = nullptr }
plzma_in_stream_release(&archiveDataInStream); // when no longer needed

plzma_decoder_set_progress_delegate_utf8_callback(&decoder, <UTF8 C CALLBACK>);  // plzma_decoder_set_progress_delegate_wide_callback(...);

//  2.1. Optionaly provide the password to open/list/test/extract encrypted archive items.
plzma_decoder_set_password_utf8_string(&decoder, "1234"); // plzma_decoder_set_password_wide_string(&decoder, L"1234");

bool opened = plzma_decoder_open(&decoder);    

// 3. Select archive items for extracting or testing.
//  3.1. Select all archive items.
plzma_item_array allArchiveItems = plzma_decoder_items(&decoder);

//  3.2. Get the number of items, iterate items by index, filter and select items.
size_t numberOfArchiveItems = plzma_decoder_count(&decoder);
plzma_item_array selectedItemsDuringIteration = plzma_item_array_create(numberOfArchiveItems);
plzma_item_out_stream_array selectedItemsToStreams = plzma_item_out_stream_array_create(numberOfArchiveItems);
for (size_t itemIndex = 0; itemIndex < numberOfArchiveItems; itemIndex++) {
    plzma_item item = plzma_decoder_item_at(&decoder, itemIndex);
    plzma_item_array_add(&selectedItemsDuringIteration, &item);
    
    plzma_out_stream outItemStream = plzma_out_stream_create_memory_stream(); // to memory stream
    plzma_item_out_stream_array_add(&selectedItemsToStreams, &item, &outItemStream);
    plzma_out_stream_release(&outItemStream);
    
    plzma_item_release(&item);
}

// 4. Extract or test selected archive items. The extract process might be:
//  4.1. Extract all items to a directory. In this case, you can skip the step #3.
plzma_path extractPath = plzma_path_create_with_utf8_string("path/outdir");
bool extracted = plzma_decoder_extract_all_items_to_path(&decoder, &extractPath, true);
plzma_path_release(&extractPath);

//  4.2. Extract selected items to a directory.
plzma_path extractPath = plzma_path_create_with_utf8_string("path/outdir");
bool extracted = plzma_decoder_extract_items_to_path(&decoder, &selectedItemsDuringIteration, &extractPath, true);
plzma_path_release(&extractPath);

//  4.3. Extract each item to a custom out-stream. 
//       The out-stream might be a file or memory. I.e. extract 'item #1' to a file stream, extract 'item #2' to a memory stream(then take extacted memory) and so on.
bool extracted = plzma_decoder_extract_item_out_stream_array(&decoder, &selectedItemsToStreams);

plzma_item_array_release(&selectedItemsDuringIteration); // when no longer needed 
plzma_item_array_release(&allArchiveItems); // when no longer needed
plzma_item_out_stream_array_release(&selectedItemsToStreams); // when no longer needed
plzma_decoder_release(&decoder); // when no longer needed

压缩

创建输出,设置编码器/存档,添加内容,打开并压缩。

该过程包括 4 个步骤

  1. 创建输出流,用于写入存档的文件内容。 输出流可以使用以下方式创建:
    1. 存档文件的路径。
    2. 创建没有参数的内存流。
  2. 创建具有输出流、存档类型、压缩方法和可选进度代理的编码器。
    1. 可选地,在标头和/或内容加密的情况下提供密码。
    2. 设置存档属性。
  3. 添加要存档的内容。 内容可以是:
    1. 单个文件路径,以及存档内的可选路径。
    2. 单个目录路径,以及可选的目录迭代选项和存档内的可选路径。
    3. 任何输入流,以及存档内所需的路径。
  4. 打开并压缩。
Swift
do {
    // 1. Create output stream for writing archive's file content.
    //  1.1. Using file path.
    let archivePath = Path("path/out.7z");
    let archivePathOutStream = try OutStream(path: archivePath)
    
    // 2. Create encoder with output stream, type of the archive, compression method and optional progress delegate.
    let encoder = try Encoder(stream: archivePathOutStream, fileType: .sevenZ, method: .LZMA2, delegate: self)
    
    //  2.1. Optionaly provide the password in case of header and/or content encryption.
    try encoder.setPassword("1234")
    
    //  2.2. Setup archive properties.
    try encoder.setShouldEncryptHeader(true)  // use this option with password.
    try encoder.setShouldEncryptContent(true) // use this option with password.
    try encoder.setCompressionLevel(9)
    
    // 3. Add content for archiving.
    //  3.1. Single file path with optional path inside the archive.
    try encoder.add(path: Path("dir/my_file1.txt")) // store as "dir/my_file1.txt", as is.
    try encoder.add(path: Path("dir/my_file2.txt"), mode: .default, archivePath: Path("renamed_file2.txt")) // store as "renamed_file2.txt"
    
    //  3.2. Single directory path with optional directory iteration option and optional path inside the archive.
    try encoder.add(path: Path("dir/dir1")) // store as "dir1/..."
    try encoder.add(path: Path("dir/dir2"), mode: .followSymlinks, archivePath: Path("renamed_dir2")) // store as "renamed_dir2/..."
    
    //  3.3. Any input stream with required path inside the archive.
    let itemStream = try InStream(dataCopy: <Data>) // InStream(dataNoCopy: <Data>)
    try encoder.add(stream: itemStream, archivePath: Path("my_file3.txt")) // store as "my_file3.txt"
    
    // 4. Open.
    let opened = try encoder.open()
    
    // 4. Compress.
    let compressed = try encoder.compress()
} catch let exception as Exception {
    print("Exception: \(exception)")
}
JavaScript
const plzma = require('plzmasdk');

try {
    // 1. Create output stream for writing archive's file content.
    //  1.1. Using file path.
    const archivePathOutStream = new plzma.OutStream('path/out.7z');

    // 2. Create encoder with output stream, type of the archive, compression method and optional progress delegate.
    const encoder = plzma.Encoder(archivePathOutStream, plzma.FileType.sevenZ, plzma.Method.LZMA2);
    encoder.setProgressDelegate((path, progress) => console.log(`Delegating progress, path: ${path}, progress: ${progress}`) );
    
    //  2.1. Optionaly provide the password in case of header and/or content encryption.
    encoder.setPassword('1234');

    //  2.2. Setup archive properties.
    encoder.shouldEncryptHeader = true;  // use this option with password.
    encoder.shouldEncryptContent = true; // use this option with password.
    encoder.compressionLevel = 9;
    
    // 3. Add content for archiving.
    //  3.1. Single file path with optional path inside the archive.
    encoder.add('dir/my_file1.txt'); // store as "dir/my_file1.txt", as is.
    encoder.add('dir/my_file2.txt', 0, 'renamed_file2.txt'); // store as "renamed_file2.txt"
    
    //  3.2. Single directory path with optional directory iteration option and optional path inside the archive.
    encoder.add('dir/dir1'); // store as "dir1/..."
    encoder.add('dir/dir2', plzma.OpenDirMode.followSymlinks, 'renamed_dir2'); // store as "renamed_dir2/..."

    //  3.3. Any input stream with required path inside the archive.
    const itemStream = plzma.InStream(new ArrayBuffer(...));
    encoder.add(itemStream, 'my_file3.txt'); // store as "my_file3.txt"
    
    // 4. Open.
    const opened = await encoder.openAsync(); // also available sync. version 'encoder.open()'
    
    // 4. Compress.
    const compressed = await encoder.compressAsync(); // also available sync. version 'encoder.compress()'
} catch (error) {
    console.log(`Exception: ${error}`);
}
C++
try {
    // 1. Create output stream for writing archive's file content.
    //  1.1. Using file path.
    const auto archivePathOutStream = makeSharedOutStream(Path("path/out.7z"));

    // 2. Create encoder with output stream, type of the archive, compression method and optional progress delegate.
    auto encoder = makeSharedEncoder(archivePathOutStream, plzma_file_type_7z, plzma_method_LZMA2);
    encoder->setProgressDelegate(_progressDelegate);

    //  2.1. Optionaly provide the password in case of header and/or content encryption.
    encoder->setPassword("1234");
    
    //  2.2. Setup archive properties.
    encoder->setShouldEncryptHeader(true);   // use this option with password.
    encoder->setShouldEncryptContent(true);  // use this option with password.
    encoder->setCompressionLevel(9);

    // 3. Add content for archiving.
    //  3.1. Single file path with optional path inside the archive.
    encoder->add(Path("dir/my_file1.txt"));  // store as "dir/my_file1.txt", as is.
    encoder->add(Path("dir/my_file2.txt"), 0, Path("renamed_file2.txt")); // store as "renamed_file2.txt"

    //  3.2. Single directory path with optional directory iteration option and optional path inside the archive.
    encoder->add(Path("dir/dir1")); // store as "dir1/..."
    encoder->add(Path("dir/dir2"), plzma_open_dir_mode_follow_symlinks, Path("renamed_dir2")); // store as "renamed_dir2/..."

    //  3.3. Any input stream with required path inside the archive.
    auto itemStream = makeSharedInStream(<DATA>, <DATA_SIZE>);
    encoder->add(itemStream, Path("my_file3.txt")); // store as "my_file3.txt"
    
    // 4. Open.
    bool opened = encoder->open();

    // 4. Compress.
    bool compressed = encoder->compress();
} catch (const Exception & exception) {
    std::cout << "Exception: " << exception.what() << std::endl;
}
C
// 1. Create output stream for writing archive's file content.
//  1.1. Using file path.
plzma_path archivePath = plzma_path_create_with_utf8_string("path/out.7z");
plzma_out_stream archivePathOutStream = plzma_out_stream_create_with_path(&archivePath);

// 2. Create encoder with output stream, type of the archive, compression method and optional progress delegate.
plzma_context context;
plzma_encoder encoder = plzma_encoder_create(&archivePathOutStream, plzma_file_type_7z, plzma_method_LZMA2, context);
plzma_encoder_set_progress_delegate_utf8_callback(&encoder, <C_CALLBACK_FUNCTION>);

//  2.1. Optionaly provide the password in case of header and/or content encryption.
plzma_encoder_set_password_utf8_string(&encoder, "1234");

//  2.2. Setup archive properties.
plzma_encoder_set_should_encrypt_header(&encoder, true);   // use this option with password.
plzma_encoder_set_should_encrypt_content(&encoder, true);  // use this option with password.
plzma_encoder_set_compression_level(&encoder, 9);

// 3. Add content for archiving.
//  3.1. Single file path with optional path inside the archive.
plzma_path itemPath = plzma_path_create_with_utf8_string("dir/my_file1.txt");
plzma_encoder_add_path(&encoder, &itemPath, 0, NULL); // store as "dir/my_file1.txt", as is.
plzma_path_release(&itemPath);

itemPath = plzma_path_create_with_utf8_string("dir/my_file2.txt");
plzma_path itemArchivePath = plzma_path_create_with_utf8_string("renamed_file2.txt");
plzma_encoder_add_path(&encoder, &itemPath, 0, &itemArchivePath); // store as "renamed_file2.txt"
plzma_path_release(&itemPath);
plzma_path_release(&itemArchivePath);

//  3.2. Single directory path with optional directory iteration option and optional path inside the archive.
itemPath = plzma_path_create_with_utf8_string("dir/dir1");
plzma_encoder_add_path(&encoder, &itemPath, 0, NULL); // store as "dir1/..."
plzma_path_release(&itemPath);

itemPath = plzma_path_create_with_utf8_string("dir/dir2");
itemArchivePath = plzma_path_create_with_utf8_string("renamed_dir2");
plzma_encoder_add_path(&encoder, &itemPath, plzma_open_dir_mode_follow_symlinks, &itemArchivePath); // store as "renamed_dir2/..."
plzma_path_release(&itemPath);
plzma_path_release(&itemArchivePath);

//  3.3. Any input stream with required path inside the archive.
itemArchivePath = plzma_path_create_with_utf8_string("my_file3.txt");
plzma_in_stream itemStream = plzma_in_stream_create_with_memory(<DATA>, <DATA_SIZE>);
plzma_encoder_add_stream(&encoder, &itemStream, &itemArchivePath); // store as "my_file3.txt"
plzma_in_stream_release(&itemStream);
plzma_path_release(&itemArchivePath);

// 4. Open.
bool opened = plzma_encoder_open(&encoder);

// 4. Compress.
bool compressed = plzma_encoder_compress(&encoder);

plzma_out_stream_release(&archivePathOutStream); // when no longer needed
plzma_path_release(&archivePath); // when no longer needed
plzma_encoder_release(&encoder); // when no longer needed

许可


通过使用所有这些,您将接受原始的 LZMA SDK 和 MIT 许可证(*见下文*)

MIT 许可证 (MIT)

版权所有 (c) 2015 - 2025 Oleh Kulykov olehkulykov@gmail.com

特此授予任何人免费获得本软件及其相关文档文件(“软件”)副本的许可,以处理本软件,不受限制,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许向提供本软件的人员授予此类许可,但须符合以下条件:

上述版权声明和本许可声明应包含在本软件的所有副本或实质性部分中。

本软件按“原样”提供,不提供任何形式的明示或暗示保证,包括但不限于适销性、特定用途适用性和非侵权性的保证。在任何情况下,作者或版权持有者均不对任何索赔、损害或其他责任承担任何责任,无论是在合同诉讼、侵权诉讼或其他诉讼中,因本软件或本软件的使用或其他处理而产生、由此产生或与之相关的责任。