1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! # 文件工具模块
//! 提供文件操作相关的实用工具函数
//!
//! 该模块包含以下主要功能:
//! - 获取文件扩展名
//! - 计算文件的 SHA256 哈希值
//! - 检测跨设备操作错误
//!
//! ## 示例
//!
//! ```
//! use std::path::Path;
//! use your_crate::utils::file_utils::{get_file_ext, calc_hash};
//!
//! // 获取文件扩展名
//! let ext = get_file_ext("example.TXT");
//! assert_eq!(ext, "txt");
//!
//! // 计算文件哈希值
//! // let hash = calc_hash(Path::new("test.txt"));
//! // println!("文件哈希值: {}", hash);
//! ```
use Digest;
use File;
use io;
use Read;
use Path;
/// # 获取文件名的扩展名
///
/// 该函数从给定的文件名中提取扩展名部分。扩展名被定义为文件名中最后一个点(`.`)之后的部分,
/// 并且会被转换为小写形式。
///
/// ## 参数
///
/// * `file_name` - 包含文件名的字符串切片引用
///
/// ## 返回值
///
/// 返回文件的扩展名(不包括点号),如果文件名中没有点号则返回空字符串。
/// 扩展名会被自动转换为小写形式。
///
/// ## 示例
///
/// ```
/// use your_crate::utils::file_utils::get_file_ext;
///
/// assert_eq!(get_file_ext("example.TXT"), "txt");
/// assert_eq!(get_file_ext("document.pdf"), "pdf");
/// assert_eq!(get_file_ext("file_without_extension"), "");
/// ```
/// # 计算指定文件的 SHA256 哈希值
///
/// 该函数会打开指定路径的文件,并计算其完整的 SHA256 哈希值。
/// 使用 8192 字节的缓冲区以高效地处理大文件。
///
/// ## 参数
///
/// * `path` - 指向要计算哈希值的文件路径
///
/// ## 返回值
///
/// 返回表示文件 SHA256 哈希值的小写十六进制字符串。
///
/// ## Panics
///
/// 当无法打开文件或读取过程中发生错误时,函数会 panic。
/// 在生产环境中应适当处理这些错误情况。
///
/// ## 示例
///
/// ```
/// use std::path::Path;
/// use your_crate::utils::file_utils::calc_hash;
///
/// // 假设存在一个名为 "test.txt" 的文件
/// let hash = calc_hash(Path::new("test.txt"));
/// println!("文件哈希值: {}", hash);
/// ```
/// # 检查 IO 错误是否为跨设备错误
///
/// 跨设备错误通常发生在尝试移动或重命名文件时,源文件和目标路径位于不同的文件系统或设备上。
/// 此函数检测不同操作系统上的跨设备错误:
/// - 在 Unix 系统上检查 EXDEV 错误 (错误码 18)
/// - 在 Windows 系统上检查 ERROR_NOT_SAME_DEVICE 错误 (错误码 17)
///
/// ## 参数
///
/// * `err` - 要检查的 IO 错误引用
///
/// ## 返回值
///
/// 如果错误是跨设备错误则返回 `true`,否则返回 `false`。
///
/// ## 示例
///
/// ```
/// use std::io;
/// use your_crate::utils::file_utils::is_cross_device_error;
///
/// let error = io::Error::new(io::ErrorKind::InvalidInput, "cross-device link");
/// if is_cross_device_error(&error) {
/// println!("检测到跨设备错误");
/// }
/// ```