Записать буфер памяти в Zip без копий с помощью Chilkat - PullRequest
0 голосов
/ 28 марта 2019

Я ищу библиотеку Chilkat Zip для выгрузки двоичных данных на диск для последующего повторного использования.Капли, которые я хочу выбросить, могут быть очень большими (10+ ГиБ), поэтому копирование любого из них будет пустой тратой времени и пространства.

Я уже нашел метод CkByteData::borrowData, который позволяет мне разрешить Chilkatиспользуйте буферы, выделенные приложением, вместо того, чтобы копировать его во внутренний буфер.Однако при добавлении этого CkByteData к CkZipEntry (используя CkZipEntry::AppendData) я замечаю, что мое приложение внезапно потребляет вдвое больше памяти;явный признак того, что Чилкат все-таки выполнил копию.После CkZip::WriteZip потребление памяти возвращается к нормальному.

Фрагмент, который я использовал для тестирования:

int main(int, char**)
{
    CkZip zip;
    zip.UnlockComponent(/* hidden */);
    zip.NewZip("data.zip");

    constexpr auto size = 20'000'000; // ~= 20 MiB
    auto data = new char[size];

    for (auto i = 0; i < size; ++i)
       data[i] = static_cast<char>(i);

    CkByteData bd;
    bd.borrowData(data, size);

    auto entry = zip.AppendNew("blob");
    entry->AppendData(bd);
    // --> Memory consumption jumps to ~40 MiB

    delete entry;

    zip.WriteZip();
    // --> Memory consumption drops to ~20 MiB

    delete[] data;
    return 0;
}

Мои вопросы:

  • Есть ли способ избежать копий моих больших двоичных объектов при записи их в Zip-файл с использованием Chilkat?
  • Кроме того, CkByteData::borrowData работает только для ввода данных Chilkat не позволит Chilkat выводить данные обратно в приложение.Таким образом, даже если все копии удаляются при записи, можно ли также избегать копий при чтении данных из файла?
  • Если копии неизбежны, существуют ли масштабируемые обходные пути, которые ограничивают скопированные байты частью данных (например, многократно добавляют часть большого двоичного объекта в Zip и записывают это в файл)?

Примечание: на самом деле я делаюне нужно сжимать данные (но это хороший плюс).Поэтому, если для решения необходимо отключить сжатие, это нормально.

1 Ответ

1 голос
/ 29 марта 2019

Если новый файл в zip-файле может быть огромным, единственным решением будет удалить существующую запись, а затем вызвать AppendOneFileOrDir для добавления нового файла. Вы не хотели бы пытаться прочитать 10GB файл в память и добавить его. Когда вы вызываете AppendOneFileOrDir, он фактически не считывает файл в память. Вместо этого он создает запись zip, которая ссылается на файл (см. http://www.chilkatsoft.com/refdoc/csZipEntryRef.html#prop10) Когда вызывается WriteZipAndClose, данные для сжатия передаются из файла в поток, поэтому они никогда полностью не сохраняются в памяти.

...