
鸿蒙-ArkTS和Native之间的交互使用11使用libarchive创建getExtractFi-
前言:
使用 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 等常见格式。
