use std::collections::{LinkedList, VecDeque};
use std::future::Future;
use std::io::ErrorKind;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::pin::Pin;
use tokio::fs;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[allow(dead_code)]
pub async fn is_file_exist(file_path: &str) -> bool {
match fs::metadata(file_path).await {
Ok(metadata) => metadata.is_file(),
Err(_) => false,
}
}
#[allow(dead_code)]
pub async fn is_dir_exist(dir_path: &str) -> bool {
match fs::metadata(dir_path).await {
Ok(metadata) => metadata.is_dir(),
Err(_) => false,
}
}
#[allow(dead_code)]
pub async fn create_dir(dir_path: &str) -> bool {
match fs::create_dir_all(dir_path).await {
Ok(_) => true,
Err(_) => false,
}
}
#[allow(dead_code)]
pub fn get_file_path_dir(file_path: &str) -> Option<String> {
if let Some(parent) = Path::new(file_path).parent() {
if let Some(dir) = parent.to_str() {
Some(dir.to_owned())
} else {
None
}
} else {
None
}
}
#[allow(dead_code)]
pub fn get_absoule_path(file_path: &str) -> Option<String> {
let relative_path = Path::new(file_path);
if relative_path.is_relative() {
let current_dir = std::env::current_dir().unwrap();
let full_path = current_dir.join(relative_path).canonicalize().unwrap();
let mut path_buf = PathBuf::new();
for component in full_path.components() {
if let Some(str_component) = component.as_os_str().to_str() {
path_buf.push(str_component);
}
}
let full_path = path_buf.to_string_lossy().into_owned();
Some(full_path.replace("\\\\?\\", ""))
} else {
Some(file_path.to_string())
}
}
#[allow(dead_code)]
pub async fn create_file(file_path: &str) -> bool {
if is_file_exist(file_path).await {
return true;
}
let dir_path = get_file_path_dir(file_path);
if dir_path.is_none() {
return false;
}
let dir_path = dir_path.expect("获取文件夹路径失败!");
if !create_dir(&dir_path).await {
return false;
}
match File::create(file_path).await {
Ok(_) => true,
Err(_) => false,
}
}
#[allow(dead_code)]
pub fn create_dir_sync(dir_path: &str) -> bool {
std::fs::create_dir_all(dir_path).unwrap();
true
}
#[allow(dead_code)]
pub fn create_file_path_sync(file_path: &str) -> bool {
let dir_path = get_file_path_dir(file_path);
if dir_path.is_none() {
return false;
}
let dir_path = dir_path.unwrap();
if Path::new(&dir_path).exists() {
return true;
}
return create_dir_sync(&dir_path);
}
#[allow(dead_code)]
pub async fn write_content_to_file(file_path: &str, content: &str) -> std::io::Result<()> {
fs::write(file_path, content).await
}
#[allow(dead_code)]
pub async fn read_file_as_string(file_path: &str) -> std::io::Result<String> {
fs::read_to_string(file_path).await
}
#[allow(dead_code)]
pub async fn get_file_list(dir_path: &str) -> std::io::Result<LinkedList<String>> {
let mut file_list = LinkedList::new();
let mut entries = fs::read_dir(dir_path).await?;
while let Some(entry) = entries.next_entry().await? {
let file_name = entry.file_name();
let file_name = file_name.to_string_lossy().to_string();
file_list.push_back(file_name);
}
Ok(file_list)
}
#[allow(dead_code)]
pub async fn get_file_list_recursively(
dir_path: &str,
is_add_path: bool,
) -> std::io::Result<LinkedList<String>> {
let mut dirs_to_explore = VecDeque::new();
let mut file_list = LinkedList::new();
let base_path = PathBuf::from(dir_path);
dirs_to_explore.push_back(base_path.clone());
while let Some(current_dir) = dirs_to_explore.pop_front() {
let mut dir_entries = fs::read_dir(current_dir).await?;
while let Some(entry) = dir_entries.next_entry().await? {
let path = entry.path();
if path.is_dir() {
dirs_to_explore.push_back(path);
} else {
if is_add_path {
if let Ok(stripped_path) = path.strip_prefix(&base_path) {
file_list.push_back(stripped_path.display().to_string());
}
} else {
let file_name = entry.file_name();
let file_name = file_name.to_string_lossy().to_string();
file_list.push_back(file_name);
}
}
}
}
Ok(file_list)
}
#[allow(dead_code)]
pub async fn copy_file(source_path: &str, destination_path: &str) -> std::io::Result<()> {
let mut source_file = File::open(source_path).await?;
if !create_file(destination_path).await {
return Err(io::Error::new(ErrorKind::Other, "创建目标文件失败!"));
}
let mut destination_file = File::create(destination_path).await?;
let mut buffer = vec![0; 4096];
loop {
let bytes_read = source_file.read(&mut buffer).await?;
if bytes_read == 0 {
break;
}
destination_file.write_all(&buffer[..bytes_read]).await?;
}
Ok(())
}
#[allow(dead_code)]
pub fn get_file_name_from_path(file_path: &str) -> Option<String> {
let path = Path::new(file_path);
if let Some(file_name) = path.file_name() {
if let Some(file_name_str) = file_name.to_str() {
return Some(String::from(file_name_str));
}
}
None
}
#[allow(dead_code)]
pub async fn remove_all_dir(dir_path: &str) -> std::io::Result<()> {
if !is_dir_exist(dir_path).await {
return Ok(());
}
fs::remove_dir_all(dir_path).await?;
Ok(())
}
#[allow(dead_code)]
pub fn get_md5(file_path: &str) -> std::io::Result<String> {
let file = std::fs::File::open(file_path)?;
let mut reader = std::io::BufReader::new(file);
let mut context = md5::Context::new();
let mut buffer = vec![0u8; 4 * 1024 * 1024];
loop {
let bytes_read = reader.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
context.consume(&buffer[..bytes_read]);
}
let digest = context.compute();
Ok(format!("{:x}", digest))
}