用于从Rust中的给定路径中提取文件扩展名

ans*_*vas 7 filenames file-extension path rust

我试图从给定的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");

}
Run Code Online (Sandbox Code Playgroud)

Pet*_*all 13

在惯用的Rust中,可能失败的函数的返回类型应该是a Option或a Result.通常,函数也应该接受切片而不是Strings,并且只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"));
Run Code Online (Sandbox Code Playgroud)

使用and_then在这里很方便,因为这意味着您不必解包Option<&OsStr>返回的extension()None在调用之前处理它的可能性to_str.我也可以使用lambda |s| s.to_str()而不是OsStr::to_str- 它可能是一个偏好或意见的问题,哪个更惯用.

请注意,参数&str和返回值都是对为断言创建的原始字符串切片的引用.返回的切片不能超过它引用的原始切片,String因此如果需要更长的时间,可能需要从此结果创建一个拥有的切片.


Ale*_*ica 7

有什么比使用 Rust 的内置方法更惯用的了?

Path::new(&filename).extension()
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的快速回复,但我认为这个示例会失败: `assert_eq!(get_extension_from_filename("abc.tar.gz".to_string()) ,"tar.gz" );` (2认同)