鸿蒙-ArkTS和Native之间的交互使用9使用libarchive创建Decompress

仿佛云烟
发布于 2025-6-28 16:51
浏览
0收藏
前言:

鸿蒙-ArkTS和Native之间的交互使用9使用libarchive创建Decompress-鸿蒙开发者社区


libarchive 凭借其全面的格式支持、高效的流式处理以及宽松的许可证,成为处理存档文件的优选方案。对于需要兼容历史格式或开发跨平台工具的项目,建议优先评估此库。


  1. 流式处理与低内存占用
    采用流式读写设计,支持逐块处理大文件,避免内存溢出问题。例如,解压 10GB 的 tar.gz 文件时,内存占用可稳定在数 MB 级别。
  2. 符号链接与权限保留
    在解压文件时自动还原 POSIX 文件权限、符号链接及时间戳,确保存档完整性,适用于系统备份工具开发。
  3. 加密与安全性
    支持 ZIP 格式的 AES-256 加密和传统加密算法,但需注意 RAR 格式的解密功能依赖第三方库。


 解压方法Decompress:


在鸿蒙的cpp代码中添加如下:


//Index.d.ts文件中添加
export const decompress: (inFile: string, outFile: string) => object


鸿蒙-ArkTS和Native之间的交互使用9使用libarchive创建Decompress-鸿蒙开发者社区


然后添加c代码:


static napi_value Decompress(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value argv[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

    size_t in_file_size;
    char in_file_buf[256];
    napi_get_value_string_utf8(env, argv[0], in_file_buf, sizeof(in_file_buf), &in_file_size);
    std::string in_file(in_file_buf, in_file_size);

    size_t out_file_size;
    char out_file_buf[256];
    napi_get_value_string_utf8(env, argv[1], out_file_buf, sizeof(out_file_buf), &out_file_size);
    std::string out_file(out_file_buf, out_file_size);

    if (in_file.empty() || out_file.empty()) {
        return create_result(env, ErrorCode::FILE_NOT_FOUND);
    }

    // Ensure the output directory ends with a slash
    if (!out_file.empty() && out_file.back() != '/') {
        out_file += '/';
    }

    struct archive *a;
    struct archive *out;
    struct archive_entry *entry;
    int r;

    a = archive_read_new();
    archive_read_support_format_all(a);
    archive_read_support_filter_all(a);

    out = archive_write_disk_new();
    archive_write_disk_set_options(out, ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS);
    archive_write_disk_set_standard_lookup(out);

    int fd = open(in_file.c_str(), O_RDONLY);
    if (fd == -1) {
        return create_result(env, ErrorCode::FILE_NOT_FOUND);
    }

    struct stat statbuf;
    if (fstat(fd, &statbuf) == -1) {
        close(fd);
        return create_result(env, ErrorCode::FILE_READ_ERROR);
    }

    off_t len = statbuf.st_size;
    std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(len);

    ssize_t bytes_read = read(fd, data.get(), len);
    if (bytes_read != len) {
        close(fd);
        return create_result(env, ErrorCode::FILE_READ_ERROR);
    }
    close(fd);

    r = archive_read_open_memory(a, data.get(), len);
    if (r != ARCHIVE_OK) {
        return create_result(env, ErrorCode::ARCHIVE_ERROR);
    }

    const char *original_locale = setlocale(LC_CTYPE, nullptr);
    setlocale(LC_CTYPE, "en_US.UTF-8");

    const char *error_string;

    while (true) {
        r = archive_read_next_header(a, &entry);
        if (r != ARCHIVE_OK) {
            error_string = archive_error_string(a);
            if (error_string) {
                OH_LOG_ERROR(LOG_APP, "Unable to read next header: %{public}s", error_string);
            }
            break;
        }

        const char *current_path = archive_entry_pathname(entry);
        std::string full_output_path = out_file + current_path;
        archive_entry_set_pathname(entry, full_output_path.c_str());

        r = archive_write_header(out, entry);
        if (r != ARCHIVE_OK) {
            error_string = archive_error_string(a);
            OH_LOG_ERROR(LOG_APP, "Unable to write header for file: %{public}s, error: %{public}s", current_path, error_string);
        } else {
            const void *buff;
            size_t size;
            int64_t offset;
            while ((r = archive_read_data_block(a, &buff, &size, &offset)) == ARCHIVE_OK) {
                r = archive_write_data_block(out, buff, size, offset);
                if (r != ARCHIVE_OK) {
                    error_string = archive_error_string(a);
                    OH_LOG_ERROR(LOG_APP, "Unable to write data for file: %{public}s, error: %{public}s", current_path, error_string);
                    break;
                }
            }
            if (r == ARCHIVE_EOF) {
                r = ARCHIVE_OK; // Reset error code if EOF reached
            }
        }
        archive_entry_clear(entry);
    }

    archive_read_close(a);
    archive_read_free(a);
    archive_write_close(out);
    archive_write_free(out);

    setlocale(LC_CTYPE, original_locale);
    
    return create_result(env, r == ARCHIVE_EOF ? ErrorCode::SUCCESS : ErrorCode::ARCHIVE_ERROR, error_string);
}


在ArkTS中调用该方法:


export async function decompress(inFile: string, outFile: string): Promise {
    return archive.decompress(inFile, outFile) as Result
  }




分类
收藏
回复
举报
回复
    相关推荐