Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zip_file_replace command is compressing the data when the compression is set to store uncompressed #484

Open
dillof opened this issue Feb 14, 2025 · 0 comments
Labels
bug libzip doesn't behave as expected.

Comments

@dillof
Copy link
Member

dillof commented Feb 14, 2025

Discussed in #483

Originally posted by KRaggett February 14, 2025
Hi,
I am investigating using libzip to create and modify files containing chunks of data. In my test case my chunks of data are vectors of doubles. I want to create an archive file and at a later date be able to read one of the files from the archive, modify it and replace it with updated data.

I create a zipfile with one directory and within this directory are 10 files containing my data.

I create the file using the following code and it correctly contains all the data uncompressed. (I have removed all error checking for brevity.)

void writeLibzipFile(const std::filesystem::path& zipFilePath, const std::string& folderName, const std::vector<std::vector<double>>& dataBuffers, int numDataPackets)
{
   auto zipFile = zipFilePath;
   zipFile += ".zip";

   int errorp;
   zip_t* archive = zip_open(reinterpret_cast<const char*>(zipFile.u8string().c_str()), ZIP_CREATE | ZIP_EXCL | ZIP_FL_ENC_UTF_8, &errorp);

   // Add the directory to the zip archive
   zip_dir_add(archive, folderName.c_str(), ZIP_FL_ENC_UTF_8);

   // Add files to the directory from the buffer of data
   for (size_t i = 0; i < numDataPackets; ++i) 
   {
      std::string fileName = folderName + "/data" + std::to_string(i) + ".bin";

      zip_source_t* source = zip_source_buffer(archive, dataBuffers[i].data(), dataBuffers[i].size() * sizeof(double), 0);

      // add the file to the zip file
      zip_uint64_t fileIndex = zip_file_add(archive, fileName.c_str(), source, ZIP_FL_ENC_UTF_8);

      // set the file compression to uncompressed
      zip_set_file_compression(archive, fileIndex, ZIP_CM_STORE, 0);
   }
   // Write any changes to the archive
   zip_close(archive);
}

I then open this file and replace the 3rd file of data (data2.bin) with new data using the following code:

void replaceExistingDataset(const std::filesystem::path& inputFilepath, std::string_view datasetName, const std::vector<double>& newDataPacket)
{
   std::filesystem::path zipfile = inputFilepath;

   int zipError;
   // open the existing zip file
   zip_t* archive = zip_open(reinterpret_cast<const char*>(zipfile.u8string().c_str()), ZIP_FL_ENC_UTF_8, &zipError);

   // Read the stats from the zip file
   int fileInZip = zip_get_num_entries(archive, 0);
   zip_stat_t zipStat;
   zip_stat_init(&zipStat);
   
   // create a source buffer from the new data
   zip_source_t* source = zip_source_buffer(archive, newDataPacket.data(), newDataPacket.size() * sizeof(double), 0);

   for (zip_uint64_t fileIndex = 0; fileIndex < fileInZip; ++fileIndex)
   {
      zip_stat_index(archive, fileIndex, 0, &zipStat);

      if (zipStat.name == datasetName)
      {
         // Replace the data in the file with the new data
         zip_file_replace(archive, zipStat.index, source, ZIP_FL_ENC_UTF_8);

         // set the file compression to uncompressed
         zip_set_file_compression(archive, zipStat.index, ZIP_CM_STORE, 0);
      }
   }
   // Write any changes to the archive
   zip_close(archive);
}

When I open the archive in Windows explorer the updated file in the archive has been compressed.

image

I have tried replacing the compression type with ZIP_CM_DEFAULT; if I do this just in the file replace code then it makes no difference, if I set it in both the file create and the file replace code then when the file is replaced all the files in my archive are compressed.

I have verified the index I am passing to the zip_file_replace() and zip_set_file_compression() functions is the same and the correct index for the file being replaced.
I don't get any errors returned from any of the calls to the libzip functions.

If anyone knows what I am doing wrong or if I am missing a step which will allow me to replace files in an existing archive and set the compression to uncompressed I would really appreciate your help.
Thanks, Kate

@dillof dillof added the bug libzip doesn't behave as expected. label Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug libzip doesn't behave as expected.
Projects
None yet
Development

No branches or pull requests

1 participant