
回复
libarchive 凭借其全面的格式支持、高效的流式处理以及宽松的许可证,成为处理存档文件的优选方案。对于需要兼容历史格式或开发跨平台工具的项目,建议优先评估此库。
解压方法Decompress:
在鸿蒙的cpp代码中添加如下:
//Index.d.ts文件中添加
export const decompress: (inFile: string, outFile: string) => object
然后添加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
}