Извлечение данных из сжатого файла возвращает случайные данные

Я использую libzip для извлечения содержимого каждого файла в zip-файле в мою собственную структуру данных, неизменный POD C++.

Проблема в том, что каждый раз, когда я извлекаю содержимое файла, я получаю случайные данные с привязкой к концу. Вот мой код:

void Parser::populateFileMetadata() {
int error = 0;
zip *zip = zip_open(this->file_path.c_str(), 0, &error);
if (zip == nullptr) {
  LOG(DEBUG)<< "Could not open zip file.";
  return;
}

const zip_int64_t n_entries = zip_get_num_entries(zip, ZIP_FL_UNCHANGED);
for (zip_int64_t i = 0; i < n_entries; i++) {
  const char *file_name = zip_get_name(zip, i, ZIP_FL_ENC_GUESS);
  struct zip_stat st;
  zip_stat_init(&st);
  zip_stat(zip, file_name, (ZIP_FL_NOCASE|ZIP_FL_UNCHANGED), &st);
  char *content = new char[st.size];
  zip_file *file = zip_fopen(zip, file_name, \
                             (ZIP_FL_NOCASE|ZIP_FL_UNCHANGED));
  const zip_int64_t did_read = zip_fread(file, content, st.size);
  if (did_read <= 0) {
    LOG(WARNING)<< "Could not read contents of " << file_name << ".";
    continue;
  }
  const FileMetadata metadata(string(file_name), -1, string(content));
  this->file_metadata.push_back(metadata);

  zip_fclose(file);
  delete[] content;
}
zip_close(zip);
}

3 ответа

Решение

zip_fread кажется, увеличивает размер contentтак что я просто усекаю content: content[st.size] = '\0';

Вы создаете std:: string из content не сообщая конструктору, как долго это будет продолжаться, поэтому конструктор будет читать с начала буфера, пока не найдет завершающий NUL. Но нет никакой гарантии, что файл содержит его, и поэтому конструктор читает за пределами вашего буфера, пока не обнаружит NUL.

Исправлено: использовать конструктор std:: string с двумя аргументами (string(const char* s, size_t size)) и передать ему длину данных.

Решение @ruipacheco у меня не сработало. Делает content[st.size] = '\0';исправил проблему, но вызвал ошибку "двойное бесплатное или повреждение..." при вызове zip_fclose()и/или delete[] contentИтак, я сделал ниже, и это, кажется, работает

      void ReadZip(std::string &data){

....
....
data.resize(st.size);
for(uint i = 0; i<st.size; ++i)
    data[i] = std::move(content[i]);
}
Другие вопросы по тегам