RUST日常使用.md
RUST日常使用
Log日志
依赖:
[dependencies]
log = "0.4.20"
env_logger = "0.10.0"
一般使用:
// 使用RUST_LOG默认或环境变量
env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
log::warn!("This is an example message.");
自定义日志格式化实现:
use env_logger::{Builder, Env};
use std::io::Write;
/// 初始化日志输出
/// json_format: 是否使用json格式进行输出
pub fn init_log() {
let mut builder = Builder::from_env(Env::default().default_filter_or("info"));
builder.format(|buf, record| {
let message = record.args().to_string();
let level = recors.level.as_str();
writeln!(buf, "{} -- {}", level, message)
});
builder.init();
}
// 使用
#[cfg(test)]
mod tests {
use log::{error};
use crate::logs::init_log;
#[test]
fn test_log() {
init_log();
error!("测试");
}
}
Clap命令行解析
依赖:
[dependencies]
clap = { version = "4.4.6", features = ["derive"] }
基本使用:
use clap::Parser;
use clap::ValueEnum;
/// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// 源目录
#[arg(short, long)]
src_path: String,
/// 目的目录
#[arg(short, long)]
dest_path: String,
/// 支持的格式 为空表示支持所有格式
#[arg(short, long)]
format: Vec<PhotoSuffix>,
/// 当图片没有exif时,是否使用文件的create time进行时间处理
#[arg(short, long, default_value_t = false)]
allow_no_exif: bool,
}
// 图片格式枚举
#[derive(Debug, Eq, Hash, PartialEq, ValueEnum, Clone)]
pub enum PhotoSuffix {
WEBP,
JPG,
JPEG,
PNG,
TIFF,
HEIF,
}
// 使用
fn main() {
// 1. 命令行解析
let arg = Args::parse();
}
条件编译
/// 判断两个文件是否为同一分区
/// 如果文件不存在,则会判断此文件所在的文件夹
/// 任何错误,都将返回false
/// 如果为同一分区,则返回true;否则,返回false
#[cfg(not(target_os = "linux"))]
fn same_partition(mut file1: PathBuf, mut file2: PathBuf) -> bool {
// something
}
fn same_partition2(mut file1: PathBuf, mut file2: PathBuf) -> bool {
if cfg!(target_os = "linux") {
// something
}
}
图片读取
依赖:
[dependencies]
image = { version = "0.24.8", features = ["webp-encoder"] }
使用:
use image::codecs::webp::{WebPEncoder, WebPQuality};
use image::EncodableLayout;
use image::io::Reader as ImageReader;
/// 转换图片为webp格式
pub fn convert(img_path: &str, tmp_file: &mut File) -> Result<()> {
// 1. 解码图片数据
let image = if img_path.starts_with("http") {
let vec = Self::downloads_file(img_path)?;
ImageReader::new(Cursor::new(vec)).with_guessed_format()?.decode()?
} else {
// 解码图片文件
ImageReader::open(img_path)?.decode()?
};
// 2. 转换图片为webp格式
let mut buf_writer = BufWriter::new(&tmp_file);
let img_webp = WebPEncoder::new_with_quality(&mut buf_writer, WebPQuality::default());
img_webp.encode(image.as_bytes(), image.width(), image.height(), image.color())?;
// 3. 返回
Ok(())
}
http客户端 - Curl
依赖:
[dependencies]
curl = "0.4.44"
简单下载:
use curl::easy::Easy;
fn downloads_file(url: &str) -> Result<Vec<u8>> {
let mut buf = Vec::new();
let mut handle = Easy::new();
handle.url(url)?;
handle.show_header(false)?;
{
let mut transfer = handle.transfer();
transfer.write_function(|data| {
buf.extend_from_slice(data);
Ok(data.len())
})?;
transfer.perform()?;
}
Ok(buf)
}
图片exif读取
依赖:
[dependencies]
kamadak-exif = "0.5.5"
使用:
use exif::{DateTime, In, Reader, Tag, Value};
use chrono::{Local};
use anyhow::{Error, Result};
// 读取给定图片文件的exif信息,返回图片的创建时间 格式 2023-10-17
// allow_no_exif: 如果没有exif信息,是否使用图片文件的创建信息
pub fn read_datetime(img: &mut File, allow_no_exif: bool) -> Result<(String, String)> {
// 1. 打开文件
let metadata = img.metadata();
let mut buf_reader = BufReader::new(img);
// 2. 加载exif
if let Ok(exif) = Reader::new().read_from_container(&mut buf_reader) {
// 3. 读取datetime
if let Some(field) = exif.get_field(Tag::DateTime, In::PRIMARY) {
if let Value::Ascii(ref data) = field.value {
if !data.is_empty() {
let datetime = DateTime::from_ascii(&data[0])?;
return Ok((datetime.year.to_string() ,format!("{}-{:02}-{:02}", datetime.year, datetime.month, datetime.day)));
}
}
}
}
// 4. 否则返回文件最后修改时间
let date = metadata?.created()?;
if allow_no_exif {
let dt: chrono::DateTime<Local> = date.into();
return Ok((dt.format("%Y").to_string(), dt.format("%Y-%m-%d").to_string()));
}
return Err(Error::msg("无法获取图片拍摄信息!"));
}