习惯上从Rust中的给定路径提取文件扩展名 [英] Extracting a file extension from a given path in Rust idiomatically

查看:149
本文介绍了习惯上从Rust中的给定路径提取文件扩展名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从给定的String路径中提取文件的扩展名.

I am trying to extract the extension of a file from a given String path.

下面的代码可以工作,但是我想知道是否有更干净,更惯用的Rust方法来实现:

The following piece of code works, but I was wondering if there is a cleaner and more idiomatic Rust way to achieve this:

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 .这样可以减少过多的复制和堆分配.

In idiomatic Rust the return type of a function that can fail should be an Option or a Result. In general, functions should also accept slices instead of Strings and only create a new String where necessary. This reduces excessive copying and heap allocations.

您可以使用提供的 extension()方法,然后将生成的 OsStr 转换为& str :

You can use the provided extension() method and then convert the resulting OsStr to a &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()而不是 OsStr :: to_str -哪个更惯用可能是偏好或意见问题.

Using and_then is convenient here because it means you don't have to unwrap the Option<&OsStr> returned by extension() and deal with the possibility of it being None before calling to_str. I also could have used a lambda |s| s.to_str() instead of OsStr::to_str - it might be a matter of preference or opinion as to which is more idiomatic.

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

Notice that both the argument &str and the return value are references to the original string slice created for the assertion. The returned slice cannot outlive the original slice that it is referencing, so you may need to create an owned String from this result if you need it to last longer.

这篇关于习惯上从Rust中的给定路径提取文件扩展名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆