从 Rust 中的给定路径中惯用地提取文件扩展名
Extracting a file extension from a given path in Rust idiomatically
我正在尝试从给定的字符串路径中提取文件的扩展名。
以下代码有效,但我想知道是否有更简洁、更惯用的 Rust 方式 来实现此目的:
use std::path::Path;
fn main() {
fn get_extension_from_filename(filename: String) -> String {
//Change it to a canonical file path.
let path = Path::new(&filename).canonicalize().expect(
"Expecting an existing filename",
);
let filepath = path.to_str();
let name = filepath.unwrap().split('/');
let names: Vec<&str> = name.collect();
let extension = names.last().expect("File extension can not be read.");
let extens: Vec<&str> = extension.split(".").collect();
extens[1..(extens.len())].join(".").to_string()
}
assert_eq!(get_extension_from_filename("abc.tar.gz".to_string()) ,"tar.gz" );
assert_eq!(get_extension_from_filename("abc..gz".to_string()) ,".gz" );
assert_eq!(get_extension_from_filename("abc.gz".to_string()) , "gz");
}
有什么比使用 Rust 的 builtin method 更地道的呢?
Path::new(&filename).extension()
在惯用的 Rust 中,可以失败的函数的 return 类型应该是 Option
或 Result
。一般来说,函数也应该接受切片而不是 String
s,并且只在必要时创建一个新的 String
。这减少了过多的复制和堆分配。
您可以使用提供的 extension()
方法,然后将生成的 OsStr
转换为 &str
:
use std::path::Path;
use std::ffi::OsStr;
fn get_extension_from_filename(filename: &str) -> Option<&str> {
Path::new(filename)
.extension()
.and_then(OsStr::to_str)
}
assert_eq!(get_extension_from_filename("abc.gz"), Some("gz"));
在这里使用 and_then
很方便,因为这意味着您不必解包 extension()
编辑的 Option<&OsStr>
return 并处理它被替换的可能性None
在调用 to_str
之前。我也可以使用 lambda |s| s.to_str()
而不是 OsStr::to_str
- 这可能是关于哪个更惯用的偏好或意见的问题。
请注意,参数 &str
和值 return 都是对为断言创建的原始字符串切片的引用。 returned 切片不能比它引用的原始切片长寿,因此如果您需要它持续更长时间,您可能需要根据此结果创建一个拥有的 String
。
我正在尝试从给定的字符串路径中提取文件的扩展名。
以下代码有效,但我想知道是否有更简洁、更惯用的 Rust 方式 来实现此目的:
use std::path::Path;
fn main() {
fn get_extension_from_filename(filename: String) -> String {
//Change it to a canonical file path.
let path = Path::new(&filename).canonicalize().expect(
"Expecting an existing filename",
);
let filepath = path.to_str();
let name = filepath.unwrap().split('/');
let names: Vec<&str> = name.collect();
let extension = names.last().expect("File extension can not be read.");
let extens: Vec<&str> = extension.split(".").collect();
extens[1..(extens.len())].join(".").to_string()
}
assert_eq!(get_extension_from_filename("abc.tar.gz".to_string()) ,"tar.gz" );
assert_eq!(get_extension_from_filename("abc..gz".to_string()) ,".gz" );
assert_eq!(get_extension_from_filename("abc.gz".to_string()) , "gz");
}
有什么比使用 Rust 的 builtin method 更地道的呢?
Path::new(&filename).extension()
在惯用的 Rust 中,可以失败的函数的 return 类型应该是 Option
或 Result
。一般来说,函数也应该接受切片而不是 String
s,并且只在必要时创建一个新的 String
。这减少了过多的复制和堆分配。
您可以使用提供的 extension()
方法,然后将生成的 OsStr
转换为 &str
:
use std::path::Path;
use std::ffi::OsStr;
fn get_extension_from_filename(filename: &str) -> Option<&str> {
Path::new(filename)
.extension()
.and_then(OsStr::to_str)
}
assert_eq!(get_extension_from_filename("abc.gz"), Some("gz"));
在这里使用 and_then
很方便,因为这意味着您不必解包 extension()
编辑的 Option<&OsStr>
return 并处理它被替换的可能性None
在调用 to_str
之前。我也可以使用 lambda |s| s.to_str()
而不是 OsStr::to_str
- 这可能是关于哪个更惯用的偏好或意见的问题。
请注意,参数 &str
和值 return 都是对为断言创建的原始字符串切片的引用。 returned 切片不能比它引用的原始切片长寿,因此如果您需要它持续更长时间,您可能需要根据此结果创建一个拥有的 String
。