rust zip库使用

Cargo.toml增加依赖

zip = "0.5.5"
#压缩目录使用
walkdir = "2"
use std::fs;
use std::fs::File;
use std::io::{copy, Read, Seek, Write};
use std::path::Path;
use std::str;

use walkdir::{DirEntry, WalkDir};
use zip::write::FileOptions;
/// 都没有进行错误处理,本例子是参考官方例子,其中压缩目录也是看官方例子使用了walkdir库
fn main() {
    compress_dir(Path::new("d:/tmp"), Path::new("d:/tmp.zip"));
    // compress_file(Path::new("d:/企业微信截图_15792418969249.png"), Path::new("d:/test.zip"));
    extract(Path::new("d:/tmp.zip"), Path::new("d:/tmp1"));
}


/// 压缩文件夹
/// test文件夹下有a.jpg和b.txt 两个文件
/// 压缩成test.zip文件
fn compress_dir(src_dir: &Path, target: &Path) {
    let zipfile = std::fs::File::create(target).unwrap();
    let dir = WalkDir::new(src_dir);
    zip_dir(&mut dir.into_iter().filter_map(|e| e.ok()), src_dir.to_str().unwrap(), zipfile);
}
/// 压缩文件
fn compress_file(src_dir: &Path, target: &Path) {
    let zipfile = std::fs::File::create(target).unwrap();
    let dir = WalkDir::new(src_dir);

    // src_dir.parent().map( |p| println!("{:?}",p.to_str().unwrap()));
    let prefix = src_dir.parent().map_or_else(||"/",|p|p.to_str().unwrap());
    zip_dir(&mut dir.into_iter().filter_map(|e| e.ok()), prefix, zipfile);
}


fn zip_dir<T>(it: &mut dyn Iterator<Item=DirEntry>, prefix: &str, writer: T) -> zip::result::ZipResult<()>
    where T: Write + Seek {
    let mut zip = zip::ZipWriter::new(writer);
    let options = FileOptions::default()
        .compression_method(zip::CompressionMethod::Bzip2)//直接用了bzip2压缩方式,其它参看枚举
        .unix_permissions(0o755);//unix系统权限

    let mut buffer = Vec::new();
    for entry in it {
        let path = entry.path();
        //zip压缩一个文件时,会把它的全路径当成文件名(在下面的解压函数中打印文件名可知)
        //这里是去掉目录前缀
        println!("prefix  {:?} ...", prefix);
        let name = path.strip_prefix(Path::new(prefix)).unwrap();
        println!("name  {:?} ...", name);
        // Write file or directory explicitly
        // Some unzip tools unzip files with directory paths correctly, some do not!
        if path.is_file() {
            println!("adding file {:?} as {:?} ...", path, name);
            zip.start_file_from_path(name, options)?;
            let mut f = File::open(path)?;

            f.read_to_end(&mut buffer)?;
            zip.write_all(&*buffer)?;
            buffer.clear();
        } else if name.as_os_str().len() != 0 {//目录
            // Only if not root! Avoids path spec / warning
            // and mapname conversion failed error on unzip
            println!("adding dir {:?} as {:?} ...", path, name);
            zip.add_directory_from_path(name, options)?;
        }
    }
    zip.finish()?;
    Result::Ok(())
}


///解压
/// test.zip文件解压到d:/test文件夹下
///
fn extract(test: &Path, mut target: &Path) {
    let zipfile = std::fs::File::open(&test).unwrap();
    let mut zip = zip::ZipArchive::new(zipfile).unwrap();

    if !target.exists() {
        fs::create_dir_all(target).map_err(|e| {
            println!("{}", e);
        });
    }
    for i in 0..zip.len() {
        let mut file = zip.by_index(i).unwrap();
        println!("Filename: {} {:?}", file.name(), file.sanitized_name());
        if file.is_dir() {
            println!("file utf8 path {:?}", file.name_raw());//文件名编码,在windows下用winrar压缩的文件夹,中文文夹件会码(发现文件名是用操作系统本地编码编码的,我的电脑就是GBK),本例子中的压缩的文件再解压不会出现乱码
            let target = target.join(Path::new(&file.name().replace("\\", "")));
            fs::create_dir_all(target).unwrap();
        } else {
            let file_path = target.join(Path::new(file.name()));
            let mut target_file = if !file_path.exists() {
                println!("file path {}", file_path.to_str().unwrap());
                fs::File::create(file_path).unwrap()
            } else {
                fs::File::open(file_path).unwrap()
            };
            copy(&mut file, &mut target_file);
            // target_file.write_all(file.read_bytes().into());
        }
    }
}


fn create_dir(path: &Path) -> Result<(), std::io::Error> {
    fs::create_dir_all(path)
}




 

使用 GTK-rs 需要先安装 GTK+3,可以在 Linux 系统下通过包管理器安装,也可以在 Windows 和 macOS 下从官网下载安装程序进行安装。 安装 GTK+3 后,可以在 Rust 项目中添加 gtk 和 gdk 两个依赖: ```toml [dependencies] gtk = "0.9" gdk = "0.9" ``` 然后在 Rust 代码中引入 gtk 和 gdk : ```rust extern crate gtk; extern crate gdk; ``` 在 GTK-rs 中,主要有两种方式创建 GUI 窗口:Builder 和手动创建。下面分别介绍这两种方式。 ### 使用 Builder 创建 GUI 窗口 使用 Builder 可以通过 XML 文件描述 GUI 界面,然后使用 Rust 代码加载并显示窗口。以下是一个简单的例子: ```xml <?xml version="1.0" encoding="UTF-8"?> <interface> <object class="GtkWindow" id="main_window"> <property name="title">Hello, World!</property> <property name="default-width">400</property> <property name="default-height">300</property> <child> <object class="GtkLabel" id="label"> <property name="label">Hello, World!</property> </object> </child> </object> </interface> ``` 在 Rust 代码中,可以使用 gtk::Builder 加载并显示窗口: ```rust use gtk::prelude::*; use gtk::{Builder, Window}; fn main() { if let Err(err) = gtk::init() { eprintln!("Failed to initialize GTK: {}", err); return; } let glade_src = include_str!("path/to/glade/file.glade"); let builder = Builder::from_string(glade_src); let window: Window = builder.get_object("main_window").unwrap(); window.show_all(); gtk::main(); } ``` ### 手动创建 GUI 窗口 手动创建 GUI 窗口需要在 Rust 代码中定义窗口和窗口中的组件,以下是一个简单的例子: ```rust use gtk::prelude::*; use gtk::{Window, WindowType, Label}; fn main() { if let Err(err) = gtk::init() { eprintln!("Failed to initialize GTK: {}", err); return; } let window = Window::new(WindowType::Toplevel); window.set_title("Hello, World!"); window.set_default_size(400, 300); let label = Label::new(Some("Hello, World!")); window.add(&label); window.show_all(); gtk::main(); } ``` 以上代码中,创建了一个顶层窗口和一个标签组件,将标签添加到窗口中并显示窗口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值