如何在Swift中分离文件名和文件扩展名?

101

给定捆绑包中文件的名称,我想将该文件加载到我的Swift应用程序中。因此,我需要使用此方法:

let soundURL = NSBundle.mainBundle().URLForResource(fname, withExtension: ext)

出于某种原因,这种方法需要将文件名与文件扩展名分开。好的,在大多数语言中很容易把它们分开。但到目前为止,我在Swift中并没有发现如此简单。

所以这就是我拥有的:

var rt: String.Index = fileName.rangeOfString(".", options:NSStringCompareOptions.BackwardsSearch)
var fname: String = fileName .substringToIndex(rt)
var ext = fileName.substringFromIndex(rt)
如果我不在第一行包含打字,则会在后面两行出现错误。但是加上后,第一行会出现错误。
Cannot convert the expression's type '(UnicodeScalarLiteralConvertible, options: NSStringCompareOptions)' to type 'UnicodeScalarLiteralConvertible'

如何将文件名与扩展名分开?有没有一种优雅的方法可以做到这一点?

我对Swift感到非常兴奋,因为它似乎比Objective C更优雅。但现在我发现它也有自己的笨拙之处。


第二次尝试:我决定制作自己的字符串搜索方法:

func rfind(haystack: String, needle: Character) -> Int {
    var a = Array(haystack)

    for var i = a.count - 1; i >= 0; i-- {
        println(a[i])
        if a[i] == needle {
            println(i)
            return i;
        }
    }
    return -1
}

但是现在我在这一行代码var rt: String.Index = rfind(fileName, needle: ".")上遇到了一个错误:

'Int' is not convertible to 'String.Index'
没有这个 cast,接下来的两行代码会报错。 有人能帮我分离文件名和文件扩展名吗?

你有没有看过NSString中专门用于处理路径的方法(例如lastPathComponent和stringByDeletingPathExtension)? - rdelmar
7
你知道的,如果我们Objective-C用户必须忍受文档因为加入Swift而遭到破坏的话,那么如果你们Swift爱好者能够看一下它就太好了。 - Hot Licks
21个回答

141

Swift 5.0 更新:

如评论中所指出,您可以使用此方法。

let filename: NSString = "bottom_bar.png"
let pathExtention = filename.pathExtension
let pathPrefix = filename.deletingPathExtension

1
由于Swift的String类型与Foundation的NSString类无缝桥接,因此无需创建新的NSString。只需使用let pathExtension = filename.pathExtensionlet pathPrefix = filename.stringByDeletingPathExtension即可。 - James Huddleston
8
为了使用stringByDeletingPathExtension方法,你需要将filename强制转换为NSString类型 - 让pathPrefix = (filename as NSString).stringByDeletingPathExtension。 pathExtension也一样。 - user1021430
1
更新名称更改:stringByDeletingPathExtension 现在删除路径扩展名。 - Cameron Lowell Palmer
现在看起来你必须这样写:let filename: NSString = "bottom_bar.png" as NSString - Victor Engel
1
应该是 let pathPrefix = filename.deletingPathExtension - Adam
对于那些刚开始使用字符串的人,你可以将其转换为NSString,如下所示:let myStr =“bottom_bar.png”;let filename = myStr as NSString... 代码的其余部分 - Lance Samaria

92

使用 Swift 2 和 Xcode 7:如果你的文件名已经带有扩展名,那么可以将完整的文件名作为第一个参数并将空字符串作为第二个参数传递:

let soundURL = NSBundle.mainBundle()
    .URLForResource("soundfile.ext", withExtension: "")

作为替代,将扩展参数设置为nil也可以起作用。

如果您有一个URL并且出于某种原因想要获取文件本身的名称,则可以执行以下操作:

soundURL.URLByDeletingPathExtension?.lastPathComponent

Swift 4

let soundURL = NSBundle.mainBundle().URLForResource("soundfile.ext", withExtension: "")
soundURL.deletingPathExtension().lastPathComponent

这应该是推荐的答案!完美运作。 - Ipad
确实,文档中记录了可以传递完整的文件名并将扩展名设置为nil或为空:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/#//apple_ref/occ/instm/NSBundle/URLForResource:withExtension:subdirectory: - TruMan1

72

在Swift 5中工作。将这些行为添加到String类中:

extension String {

    func fileName() -> String {
        return URL(fileURLWithPath: self).deletingPathExtension().lastPathComponent 
    }

    func fileExtension() -> String {
        return URL(fileURLWithPath: self).pathExtension
    }
}

例子:

let file = "image.png"
let fileNameWithoutExtension = file.fileName()
let fileExtension = file.fileExtension()

5
仅仅是样式而已,但我更喜欢这种变化:public var fileExtension: String { return NSURL(fileURLWithPath: self).pathExtension.lowercaseString ?? "" } // 假设我们希望对于 .JPG 不区分大小写 Yahoos - BaseZen
2
在Swift 3中,您应该使用URL而不是NSURL - Sulthan

33

解决方案 Swift 4

此解决方案适用于所有实例,并且不依赖于手动解析字符串。

let path = "/Some/Random/Path/To/This.Strange.File.txt"

let fileName = URL(fileURLWithPath: path).deletingPathExtension().lastPathComponent

Swift.print(fileName)

生成的输出将会是:

This.Strange.File

这节省了我很多自定义格式化的时间,谢谢! - Menno

27

在 Swift 2.1 中,String.pathExtension 不再可用。相反,您需要通过 NSURL 转换来确定它:

NSURL(fileURLWithPath: filePath).pathExtension

然而,NSString.pathExtension仍然可用,因此您可以将其简单地转换为NSString:(pathString as NSString).pathExtension - Jamie Birch
这可以正常工作,但最好使用 URL 类来代替 NSURL - Vahid Amiri

14
在 Swift 中,您可以将 NSString 转换为以获得更快的扩展性:
extension String {
    func getPathExtension() -> String {
        return (self as NSString).pathExtension
    }
}

8

最新的Swift 4.2是这样工作的:

extension String {
    func fileName() -> String {
        return URL(fileURLWithPath: self).deletingPathExtension().lastPathComponent
    }

    func fileExtension() -> String {
        return URL(fileURLWithPath: self).pathExtension
    }
}

5
在Swift 2.1中,看起来目前实现此操作的方式是:
let filename = fileURL.URLByDeletingPathExtension?.lastPathComponent
let extension = fileURL.pathExtension

5

使用代码语法糖的 Swift 5

extension String {
    var fileName: String {
       URL(fileURLWithPath: self).deletingPathExtension().lastPathComponent
    }

    var fileExtension: String{
       URL(fileURLWithPath: self).pathExtension
    }
}

5

Swift 5

URL.deletingPathExtension().lastPathComponent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接