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

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

前言:

使用 libarchive 库提取压缩包内的单个指定文件,需通过遍历条目、匹配文件名并提取数据实现。

初始化并配置libarchive读取对象。
打开压缩包文件。
遍历每个条目,检查路径名是否匹配目标文件。
如果找到,读取数据并写入输出文件。
处理未找到的情况,释放资源。

初始化读取对象并配置格式

创建 libarchive 读取对象,启用支持的压缩格式和过滤器:

#include <archive.h>
#include <archive_entry.h>

struct archive *a = archive_read_new();
archive_read_support_filter_all(a); // 支持所有解压过滤器
archive_read_support_format_all(a); // 支持所有归档格式

打开压缩包文件

通过 archive_read_open_filename 打开目标文件,并检查是否成功:

if (archive_read_open_filename(a, “example.zip”, 10240) != ARCHIVE_OK) {
fprintf(stderr, “Error: %s\n”, archive_error_string(a));
return;
}

遍历条目并匹配目标文件

循环读取每个条目,检查文件名是否与目标匹配:

const char *target_file = “path/to/file.txt”; // 目标文件路径
struct archive_entry *entry;
int found = 0;

while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
const char *pathname = archive_entry_pathname(entry);

// 匹配文件名(区分大小写)
if (strcmp(pathname, target_file) == 0) {
    found = 1;
    break;
}
archive_read_data_skip(a);  // 跳过非目标文件的数据

}

提取文件数据

若找到目标文件,将其内容写入本地文件:

if (found) {
FILE *out = fopen(“output.txt”, “wb”);
if (!out) {
perror(“Failed to open output file”);
return;
}

const void *buff;
size_t size;
la_int64_t offset;

// 逐块读取数据并写入文件
while (archive_read_data_block(a, &buff, &size, &offset) == ARCHIVE_OK) {
    fwrite(buff, 1, size, out);
}
fclose(out);
printf("File extracted successfully.\n");

} else {
printf(“File not found in the archive.\n”);
}

错误处理与资源释放

确保释放资源并处理潜在错误:

if (archive_errno(a) != 0) {
fprintf(stderr, “Error: %s\n”, archive_error_string(a));
}
archive_read_free(a); // 释放读取对象

完整示例代码

#include <stdio.h>
#include <string.h>
#include <archive.h>
#include <archive_entry.h>

void getExtractFile(const char *archive_path, const char *target_path) {
struct archive *a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);

if (archive_read_open_filename(a, archive_path, 10240) != ARCHIVE_OK) {
    fprintf(stderr, "Error opening archive: %s\n", archive_error_string(a));
    return;
}

struct archive_entry *entry;
int found = 0;

while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
    const char *pathname = archive_entry_pathname(entry);
    if (strcmp(pathname, target_path) == 0) {
        found = 1;
        break;
    }
    archive_read_data_skip(a);
}

if (found) {
    FILE *out = fopen("output.bin", "wb");
    if (!out) {
        perror("Failed to create output file");
        archive_read_free(a);
        return;
    }

    const void *buff;
    size_t size;
    la_int64_t offset;

    while (archive_read_data_block(a, &buff, &size, &offset) == ARCHIVE_OK) {
        fwrite(buff, 1, size, out);
    }
    fclose(out);
    printf("Extracted: %s\n", target_path);
} else {
    printf("File '%s' not found.\n", target_path);
}

archive_read_free(a);

}

说明:

路径匹配逻辑

需确保 target_file 的路径与压缩包内条目路径完全一致(包括大小写和相对路径格式)。

若需模糊匹配(如仅匹配文件名),可使用 strstr 或正则表达式。

数据提取优化

使用 archive_read_data_block 逐块读取数据,避免内存溢出。

若需直接获取数据到内存,可替换 fwrite 为自定义缓冲逻辑。

格式兼容性

通过 archive_read_support_format_all,支持 ZIP、TAR、7z 等常见格式。

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