xCommonLib/utils/
file_utils.rs1use std::collections::{LinkedList, VecDeque};
2
3use std::future::Future;
4use std::io::ErrorKind;
5use std::io::{self, Read};
6use std::path::{Path, PathBuf};
7use std::pin::Pin;
8use tokio::fs;
9use tokio::fs::File;
10use tokio::io::{AsyncReadExt, AsyncWriteExt};
11
12#[allow(dead_code)]
13pub async fn is_file_exist(file_path: &str) -> bool {
14 match fs::metadata(file_path).await {
15 Ok(metadata) => metadata.is_file(),
16 Err(_) => false,
17 }
18}
19
20#[allow(dead_code)]
21pub async fn is_dir_exist(dir_path: &str) -> bool {
22 match fs::metadata(dir_path).await {
23 Ok(metadata) => metadata.is_dir(),
24 Err(_) => false,
25 }
26}
27
28#[allow(dead_code)]
32pub async fn create_dir(dir_path: &str) -> bool {
33
34 match fs::create_dir_all(dir_path).await {
35 Ok(_) => true,
36 Err(_) => false,
37 }
38}
39
40
41
42
43
44#[allow(dead_code)]
45pub fn get_file_path_dir(file_path: &str) -> Option<String> {
46 if let Some(parent) = Path::new(file_path).parent() {
47 if let Some(dir) = parent.to_str() {
48 Some(dir.to_owned())
49 } else {
50 None
51 }
52 } else {
53 None
54 }
55}
56
57#[allow(dead_code)]
58pub fn get_absoule_path(file_path: &str) -> Option<String> {
59 let relative_path = Path::new(file_path);
60
61 if relative_path.is_relative() {
62 let current_dir = std::env::current_dir().unwrap();
63 let full_path = current_dir.join(relative_path).canonicalize().unwrap();
64
65 let mut path_buf = PathBuf::new();
66
67 for component in full_path.components() {
68 if let Some(str_component) = component.as_os_str().to_str() {
69 path_buf.push(str_component);
70 }
71 }
72 let full_path = path_buf.to_string_lossy().into_owned();
73
74 Some(full_path.replace("\\\\?\\", ""))
75 } else {
76 Some(file_path.to_string())
77 }
78}
79
80#[allow(dead_code)]
81pub async fn create_file(file_path: &str) -> bool {
82 if is_file_exist(file_path).await {
83 return true;
84 }
85 let dir_path = get_file_path_dir(file_path);
86 if dir_path.is_none() {
87 return false;
88 }
89 let dir_path = dir_path.expect("获取文件夹路径失败!");
90 if !create_dir(&dir_path).await {
91 return false;
92 }
93 match File::create(file_path).await {
94 Ok(_) => true,
95 Err(_) => false,
96 }
97}
98
99#[allow(dead_code)]
100pub fn create_dir_sync(dir_path: &str) -> bool {
101 std::fs::create_dir_all(dir_path).unwrap();
102 true
103}
104
105
106
107#[allow(dead_code)]
108pub fn create_file_path_sync(file_path: &str) -> bool {
109
110 let dir_path = get_file_path_dir(file_path);
111 if dir_path.is_none() {
112 return false;
113 }
114 let dir_path = dir_path.unwrap();
115
116 if Path::new(&dir_path).exists() {
117 return true;
118 }
119 return create_dir_sync(&dir_path);
120}
121
122#[allow(dead_code)]
123pub async fn write_content_to_file(file_path: &str, content: &str) -> std::io::Result<()> {
124 fs::write(file_path, content).await
125}
126
127#[allow(dead_code)]
128pub async fn read_file_as_string(file_path: &str) -> std::io::Result<String> {
129 fs::read_to_string(file_path).await
130}
131
132#[allow(dead_code)]
133pub async fn get_file_list(dir_path: &str) -> std::io::Result<LinkedList<String>> {
134 let mut file_list = LinkedList::new();
135 let mut entries = fs::read_dir(dir_path).await?;
136 while let Some(entry) = entries.next_entry().await? {
137 let file_name = entry.file_name();
138 let file_name = file_name.to_string_lossy().to_string();
139 file_list.push_back(file_name);
140 }
141 Ok(file_list)
142}
143
144#[allow(dead_code)]
145pub async fn get_file_list_recursively(
146 dir_path: &str,
147 is_add_path: bool,
148) -> std::io::Result<LinkedList<String>> {
149 let mut dirs_to_explore = VecDeque::new();
150 let mut file_list = LinkedList::new();
151 let base_path = PathBuf::from(dir_path);
152 dirs_to_explore.push_back(base_path.clone());
153 while let Some(current_dir) = dirs_to_explore.pop_front() {
154 let mut dir_entries = fs::read_dir(current_dir).await?;
155 while let Some(entry) = dir_entries.next_entry().await? {
156 let path = entry.path();
157 if path.is_dir() {
158 dirs_to_explore.push_back(path);
159 } else {
160 if is_add_path {
161 if let Ok(stripped_path) = path.strip_prefix(&base_path) {
162 file_list.push_back(stripped_path.display().to_string());
163 }
164 } else {
165 let file_name = entry.file_name();
166 let file_name = file_name.to_string_lossy().to_string();
167 file_list.push_back(file_name);
168 }
169 }
170 }
171 }
172 Ok(file_list)
173}
174
175#[allow(dead_code)]
176pub async fn copy_file(source_path: &str, destination_path: &str) -> std::io::Result<()> {
177 let mut source_file = File::open(source_path).await?;
179 if !create_file(destination_path).await {
180 return Err(io::Error::new(ErrorKind::Other, "创建目标文件失败!"));
182 }
183 let mut destination_file = File::create(destination_path).await?;
184 let mut buffer = vec![0; 4096];
186 loop {
187 let bytes_read = source_file.read(&mut buffer).await?;
188 if bytes_read == 0 {
189 break;
191 }
192 destination_file.write_all(&buffer[..bytes_read]).await?;
193 }
194 Ok(())
195}
196
197#[allow(dead_code)]
198pub fn get_file_name_from_path(file_path: &str) -> Option<String> {
199 let path = Path::new(file_path);
200 if let Some(file_name) = path.file_name() {
202 if let Some(file_name_str) = file_name.to_str() {
203 return Some(String::from(file_name_str));
204 }
205 }
206 None
207}
208
209#[allow(dead_code)]
210pub async fn remove_all_dir(dir_path: &str) -> std::io::Result<()> {
211 if !is_dir_exist(dir_path).await {
212 return Ok(());
213 }
214 fs::remove_dir_all(dir_path).await?;
215 Ok(())
216}
217
218#[allow(dead_code)]
219pub fn get_md5(file_path: &str) -> std::io::Result<String> {
220 let file = std::fs::File::open(file_path)?;
221 let mut reader = std::io::BufReader::new(file);
222 let mut context = md5::Context::new();
223 let mut buffer = vec![0u8; 4 * 1024 * 1024];
224 loop {
225 let bytes_read = reader.read(&mut buffer)?;
226 if bytes_read == 0 {
227 break;
228 }
229 context.consume(&buffer[..bytes_read]);
230 }
231
232 let digest = context.compute();
233 Ok(format!("{:x}", digest))
234}