From 56a20dc6b1e5bd589c44a3c487ad318f0893407e Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 12 Sep 2022 22:34:17 +0300 Subject: [PATCH] zip to zip --- .gitignore | 1 + src/main.rs | 68 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 6f6826e..0c4ead2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ **/*.rs.bk baza*.zip /json/ +json.zip diff --git a/src/main.rs b/src/main.rs index e2549fc..390d928 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,13 +3,15 @@ extern crate json; extern crate tokio; use async_zip::read::fs::ZipFileReader; +use async_zip::write::{EntryOptions, ZipFileWriter}; +use async_zip::Compression; use std::path::PathBuf; use std::str::FromStr; +use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWrite, BufReader}; use tokio::{fs, task}; -use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}; -const BASE_FILENAME: &str = "baza_utf8.zip"; -const OUTPUT_PATH: &str = "json"; +const INPUT_FILENAME: &str = "baza_utf8.zip"; +const OUTPUT_FILENAME: &str = "json.zip"; #[derive(Debug, Clone, Copy)] enum KeywordType { @@ -219,59 +221,69 @@ async fn parse_file( Ok(ctx.data.clone()) } -async fn process_file( +async fn process_file( archive: &ZipFileReader, + writer: &mut ZipFileWriter, index: usize, name: String, ) -> Result<(), Box> { let entry_reader = archive.entry_reader(index).await?; - // make output filename - let mut outfilename = PathBuf::from(OUTPUT_PATH); - outfilename.push(name); - outfilename.set_extension("json"); - - // save json to file + // parse file to json let new_data = parse_file(entry_reader).await?; - let data_str = task::spawn_blocking(move || { - new_data.pretty(2) - }).await?; - let mut outfile = fs::File::create(outfilename).await?; - outfile.write_all(data_str.as_bytes()).await?; + // dump json to str + let data_str = task::spawn_blocking(move || new_data.pretty(2)).await?; + + // make output filename + let mut outfilename = PathBuf::from(name); + outfilename.set_extension("json"); + let outfilename = outfilename.to_str().unwrap().to_string(); + let opts = EntryOptions::new(outfilename, Compression::Deflate); + + // write new zip entry + writer.write_entry_whole(opts, data_str.as_bytes()).await?; + Ok(()) } #[tokio::main] async fn main() -> Result<(), Box> { // open archive just to list files - let archive = ZipFileReader::new(String::from(BASE_FILENAME)).await?; + let archive = ZipFileReader::new(String::from(INPUT_FILENAME)).await?; let source_files: Vec<(usize, String)> = archive .entries() .iter() .enumerate() - .filter(|item| !item.1.dir()) - .filter(|item| { + .filter(|(_, entry)| !entry.dir()) + .filter(|(_, entry)| { // skip files without "txt" extension - item.1.name().ends_with(".txt") + entry.name().ends_with(".txt") }) - .map(|item| (item.0, item.1.name().to_string())) + .map(|(index, entry)| (index, entry.name().to_string())) .collect(); - // check output directory - match fs::metadata(OUTPUT_PATH).await { - Err(_) => fs::create_dir_all(OUTPUT_PATH).await?, - Ok(x) if x.is_file() => return Err("output directory is file!".into()), + // check output filename + match fs::metadata(OUTPUT_FILENAME).await { + Ok(x) if x.is_dir() => return Err("output file is a directory!".into()), _ => (), }; - println!("processing {} files ...", source_files.len()); + println!( + r#" 【 "{}" ➡ "{}" 】 processing {} files 💾⏳ ..."#, + INPUT_FILENAME, + OUTPUT_FILENAME, + source_files.len() + ); - for i in source_files { - process_file(&archive, i.0, i.1).await?; + let mut file = fs::File::create(OUTPUT_FILENAME).await?; + let mut writer = ZipFileWriter::new(&mut file); + for (index, name) in source_files { + process_file(&archive, &mut writer, index, name).await?; } + writer.close().await?; - println!("done"); + println!("done ✅"); Ok(()) }