Как изменить определенную часть файла в архиве zip, используя Rust?

Как избежать двойной записи и избыточного использования памяти при изменении количества двоичных строк в файле после записи внутри zip архива в потоке, не зная количество строк заранее?
  • 18 апреля 2024 г. 18:50
Ответы на вопрос 2
Для изменения определенной части файла в архиве zip с использованием Rust можно воспользоваться библиотекой `zip`.

Пример кода:

```rust
use std::io::{Read, Write};
use std::fs::File;
use zip::write::FileOptions;
use zip::result::ZipResult;

fn modify_file_in_zip(zip_file_path: &str, file_name: &str, new_content: &[u8]) -> ZipResult<()> {
    let file = File::open(zip_file_path)?;
    let mut archive = zip::ZipWriter::new(file);

    let options = FileOptions::default().compression_method(zip::CompressionMethod::Stored);
    let mut buffer = Vec::new();

    let mut input_file = archive.get_mut(file_name)
        .expect("File not found in zip archive");

    input_file.read_to_end(&mut buffer)?;

    // Modify the specific part of the file
    // For example, replace the first 4 bytes with the new content
    buffer[..4].copy_from_slice(&new_content);

    archive.replace_file(file_name, options)?;

    Ok(())
}
```

Чтобы избежать двойной записи и избыточного использования памяти при изменении количества двоичных строк в файле после записи внутри zip архива в потоке без заранее известного количества строк, можно создать временный файл для внесения изменений и затем перезаписать оригинальный файл в архиве с измененным содержимым.

Пример кода:

```rust
use std::io::{Read, Write};
use std::fs::{File, OpenOptions};
use zip::write::FileOptions;
use zip::result::ZipResult;

fn modify_file_in_zip(zip_file_path: &str, file_name: &str, new_content: &[u8]) -> ZipResult<()> {
    let file = File::open(zip_file_path)?;
    let mut archive = zip::ZipWriter::new(file);

    let options = FileOptions::default().compression_method(zip::CompressionMethod::Stored);

    // Create a temporary file for modifying the content
    let temp_file_path = format!("temp_{}", file_name);
    let mut temp_file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(&temp_file_path)?;

    // Modify the content of the temporary file
    temp_file.write_all(new_content)?;

    // Replace the original file in the zip archive with the modified content
    archive.replace_file(file_name, options)?;

    // Cleanup temporary file
    std::fs::remove_file(temp_file_path)?;

    Ok(())
}
```

Эти примеры показывают, как изменить определенную часть файла в архиве zip с использованием Rust и избежать двойной записи и избыточного использования памяти при изменении количества двоичных строк.
Возможно, но для этого надо вмешиваться как в процесс доступа к архиву, так и в процесс сжатия. Вот примерно так. 
ZEXTERN int ZEXPORT deflateParams(z_streamp strm,
                                  int level,
                                  int strategy);

Штука в том, что ключевые байты надо держать несжатыми.
Похожие вопросы