如何从文件扩展名中拆分文件名在Swift中?

鉴于包中文件的名称,我想加载到我的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更优雅的语言。但现在我发现它有自己的麻烦。


第二次尝试:我决定做我自己的stringsearch方法:

 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' 

如果没有演员,我会在后面两行中看到一个错误。

任何人都可以帮助我分裂这个文件名和扩展名?

这是与Swift 2,Xcode 7:如果你有扩展名已经在它的文件名,那么你可以传递完整的文件名作为第一个参数和空白string作为第二个参数:

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

或者,也可以使用扩展参数。

如果你有一个URL,并且你想得到文件名称,那么你可以这样做:

 soundURL.URLByDeletingPathExtension?.lastPathComponent 

正如在评论中指出的,你可以使用这个。

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

适用于Swift 3Swift 4 。 将此function添加到String类:

 extension String { func fileName() -> String { if let fileNameWithoutExtension = NSURL(fileURLWithPath: self).deletingPathExtension?.lastPathComponent { return fileNameWithoutExtension } else { return "" } } func fileExtension() -> String { if let fileExtension = NSURL(fileURLWithPath: self).pathExtension { return fileExtension } else { return "" } } } 

例:

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

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

 NSURL(fileURLWithPath: filePath).pathExtension 

解决schemeSwift 3

此解决scheme将适用于所有实例,不依赖于手动parsingstring。

 let path = "/Some/Random/Path/To/This.Strange.File.txt" let fileName = URL(fileURLWithPath: path).deletingPathExtension().lastPathComponent Swift.print(fileName) 

结果输出将是

 This.Strange.File 

在Swift中,您可以更改为NSString以更快地获得扩展名:

 extension String { func getPathExtension() -> String { return (self as NSString).pathExtension } } 

在Swift 2.1中,似乎目前的做法是:

 let filename = fileURL.URLByDeletingPathExtension?.lastPathComponent let extension = fileURL.pathExtension 

Swift中的string肯定可以通过棘手的。 如果你想要一个纯粹的Swift方法,下面是我将如何做到这一点:

  1. 使用find来查找"."的最后一个出现"." 在string的reverse
  2. 使用advance来获得"."的正确索引"." 在原来的string中
  3. 使用Stringsubscript函数,该函数使用IntervalType来获取string
  4. 把这个包装在一个函数中,返回一个可选的名字和扩展名的元组

像这样的东西:

 func splitFilename(str: String) -> (name: String, ext: String)? { if let rDotIdx = find(reverse(str), ".") { let dotIdx = advance(str.endIndex, -rDotIdx) let fname = str[str.startIndex..<advance(dotIdx, -1)] let ext = str[dotIdx..<str.endIndex] return (fname, ext) } return nil } 

这将用于:

 let str = "/Users/me/Documents/Something.something/text.txt" if let split = splitFilename(str) { println(split.name) println(split.ext) } 

哪些产出:

 /Users/me/Documents/Something.something/text txt 

或者,只需使用已有的NSString方法,如pathExtensionstringByDeletingPathExtension

Swift 3.0

  let sourcePath = NSURL(string: fnName)?.pathExtension let pathPrefix = fnName.replacingOccurrences(of: "." + sourcePath!, with: "") 

SWIFT 3.x最短原生解决scheme

 let fileName:NSString = "the_file_name.mp3" let onlyName = fileName.deletingPathExtension let onlyExt = fileName.pathExtension 

没有扩展或任何额外的东西(我已经testing。基于Swift 2的@ gabbler解决scheme)

Swift 3.x扩展解决scheme:

 extension String { func lastPathComponent(withExtension: Bool = true) -> String { let lpc = self.nsString.lastPathComponent return withExtension ? lpc : lpc.nsString.deletingPathExtension } var nsString: NSString { return NSString(string: self) } } let path = "/very/long/path/to/filename_v123.456.plist" let filename = path.lastPathComponent(withExtension: false) 

文件名常量现在包含“ filename_v123.456

试试这个简单的Swift 4解决scheme

 extension String { func stripExtension(_ extensionSeperator: Character = ".") -> String { let selfReversed = self.reversed() guard let extensionPosition = selfReversed.index(of: extensionSeperator) else { return self } return String(self[..<self.index(before: (extensionPosition.base.samePosition(in: self)!))]) } } print("hello.there.world".stripExtension()) // prints "hello.there" 

一个更好的方法(或至less在Swift 2.0中的替代方法)是使用String pathComponents属性。 这将path名分割成一个string数组。 例如

 if let pathComponents = filePath.pathComponents { if let last = pathComponents.last { print(" The last component is \(last)") // This would be the extension // Getting the last but one component is a bit harder // Note the edge case of a string with no delimiters! } } // Otherwise you're out of luck, this wasn't a path name! 

无论出于何种原因,他们都摆脱了path扩展。

 let str = "Hello/this/is/a/filepath/file.ext" let l = str.componentsSeparatedByString("/") let file = l.last?.componentsSeparatedByString(".")[0] let ext = l.last?.componentsSeparatedByString(".")[1]