C++使用libarchive和archive_write_open_memory..如何清除缓冲区

C++ using libarchive and archive_write_open_memory... how to clear the buffer?

本文关键字:何清除 清除 缓冲区 open libarchive 使用 archive C++ write memory      更新时间:2023-10-16

我正在编写一个服务器,它将压缩文件并通过http套接字发送文件。

不幸的是,它们并不是真正的文件,它们更像是来自远程源的数据库条目。

我想压缩内存中的每个条目,然后通过http服务器将它们发送出去,每个条目都可能很大,比如每个1GB。

我以块的形式从源接收数据,例如16mb(但可以是任何有意义的块大小(。

从概念上讲,这就是正在发生的事情,尽管这是一点伪代码:

archive *_archive = archive_write_new();
//set to zip format
bool ok = true;
ok |= archive_write_set_format( _archive, ARCHIVE_FORMAT_ZIP );
ok |= archive_write_add_filter( _archive, ARCHIVE_FILTER_NONE );
char *_archiveBuffer = malloc(8192);
size_t _used;
ok = archive_write_open_memory( _archive, _archiveBuffer, 8192, &_used );
if (!ok) return ERROR;
archive_entry *_archiveEntry = archive_entry_new();
//fetch metadata about the object by id
QString id = "123456789";
QJsonObject metadata = database.fetchMetadata(id);
int size = metadata["size"].toInt();
//write the http header
httpd.writeHeader(size);
archive_entry_set_pathname( _archiveEntry, "entries/"+id );
archive_entry_set_size( entry, size );
archive_entry_set_filetype( _archiveEntry, AE_IFREG );
//archive_entry_set_perm( entry, ... );
archive_write_header( _archive, _archiveEntry );
int chunksize = 16777216;
for (int w = 0; w < size; w+=chunksize)
{
QByteArray chunk = database.fetchChunk(id,chunksize);
archive_write_data( _archive, chunk.data(), (size_t) chunk.size() );
//accumulate data, then fetch compressed data from _archiveBuffer and write to httpd
if (_used > 0)
{
httpd.writeData(_archiveBuffer);
//clear archive buffer?
}
}
archive_entry_free(_archiveEntry);
archive_write_close(_archive);
httpd.writeData(_archiveBuffer);
archive_write_free(_archive);

问题是,我如何知道数据何时被压缩到_archiveBuffer,何时被压缩,我如何读取缓冲区,然后清除它,重置_used计数器。我假设如果是_used>0,则表示发生了压缩/刷新。

另外,_archiveBuffer是否需要大于我的chunksize?

看起来我可能需要使用回调,但不清楚如何使用带有回调和内存缓冲区的archive_write_open。

我似乎在网上找不到例子。

任何帮助都将不胜感激!

解决方案比我想象的要简单得多。。。只是花了一分钟才意识到。

我相信,对于熟悉库和流的人来说,这是显而易见的。

使用回调就是答案。不要在意在内存中打开,因为这会创建一个无用的额外层,因为库已经在管理自己了。

根据多线程的配置方式,回调将在存档流上发生有趣的事情时执行,因此例如,您可以反复向存档写入单个字节,但只有当它饱和时才会发生回调。此时您可以向网络或回调中的任何位置写入。所以void *client_data是关键,因为它链接回您的主类和API。

在我的例子中,在(归档(数据可用之前,我不想写http头,因为在获取时可能会发生任何错误,这可能会导致不同的http头。

当数据完成时,closefree函数也将使用回调来完成它们的工作,因此析构函数需要在这些回调完成后发生。

现在的任务是对这些请求进行多线程处理。。。现在我有了图书馆,这似乎很简单。

如果有人感兴趣,我可以发布新的伪代码。