[英]Extracting a file extension from a given path in Rust idiomatically
我试图从给定的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中,可能失败的函数的返回类型应该是Option
或Result
。 通常,函数也应该接受切片而不是String
并且只在必要时创建一个新的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>
并在调用to_str
之前处理它是None
的可能性。 我也可以使用lambda |s| s.to_str()
|s| s.to_str()
而不是OsStr::to_str
- 它可能是一个偏好或意见的问题,哪个更惯用。
请注意,参数&str
和返回值都是对为断言创建的原始字符串切片的引用。 返回的切片不能超过它引用的原始切片,因此如果需要更长的时间,可能需要从此结果创建一个拥有的String
。
什么比使用Rust的内置方法更惯用?
Path::new(&filename).extension()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.