鉴于bundle中文件的名称,我想将文件加载到我的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'
如果没有强制转换,我会在后续的两行中出错。
任何人都可以帮我分割这个文件名和扩展名吗?
这是使用Swift 2,Xcode 7:如果您已经有扩展名的文件名,那么您可以将完整文件名作为第一个参数传递,将空字符串作为第二个参数传递:
let soundURL = NSBundle.mainBundle()
.URLForResource("soundfile.ext", withExtension: "")
或者nil作为扩展参数也可以。
如果您有一个URL,并且由于某种原因想要获取文件的名称,那么您可以这样做:
soundURL.URLByDeletingPathExtension?.lastPathComponent
斯威夫特4
let soundURL = NSBundle.mainBundle().URLForResource("soundfile.ext", withExtension: "")
soundURL.deletingPathExtension().lastPathComponent
Swift中的字符串肯定是棘手的。如果你想要一个纯粹的Swift方法,我会这样做:
find
查找字符串的"."
中reverse
的最后一次出现advance
获取原始字符串中"."
的正确索引String
的subscript
函数,它需要一个IntervalType
来获取字符串像这样的东西:
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
或者,只需使用像already available NSString
methods和pathExtension
这样的stringByDeletingPathExtension
。
试试这个简单的Swift 4解决方案吧
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"
Swift 3.0
let sourcePath = NSURL(string: fnName)?.pathExtension
let pathPrefix = fnName.replacingOccurrences(of: "." + sourcePath!, with: "")
Swift 3.x扩展解决方案:
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”
斯威夫特5
URL(string: filePath)?.pathExtension
更好的方法(或者至少是Swift 2.0中的替代方法)是使用String pathComponents属性。这会将路径名拆分为字符串数组。例如
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!
无论出于何种原因,他们都摆脱了pathExtension。
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]
Swift 4的清理答案,扩展名为PHAsset
:
import Photos
extension PHAsset {
var originalFilename: String? {
if #available(iOS 9.0, *),
let resource = PHAssetResource.assetResources(for: self).first {
return resource.originalFilename
}
return value(forKey: "filename") as? String
}
}
如XCode中所述,originalFilename是创建或导入资产时的名称。
也许我为此已经太迟了但是一个对我有用的解决方案并且考虑很简单就是使用#file
编译器指令。这是一个例子,我有一个类FixtureManager
,在/ Tests / MyProjectTests / FixturesFixtureManager.swift
swift测试中的directory. This works both in Xcode and with
中定义。
import Foundation
final class FixtureManager {
static let fixturesDirectory = URL(fileURLWithPath: #file).deletingLastPathComponent()
func loadFixture(in fixturePath: String) throws -> Data {
return try Data(contentsOf: fixtureUrl(for: fixturePath))
}
func fixtureUrl(for fixturePath: String) -> URL {
return FixtureManager.fixturesDirectory.appendingPathComponent(fixturePath)
}
func save<T: Encodable>(object: T, in fixturePath: String) throws {
let data = try JSONEncoder().encode(object)
try data.write(to: fixtureUrl(for: fixturePath))
}
func loadFixture<T: Decodable>(in fixturePath: String, as decodableType: T.Type) throws -> T {
let data = try loadFixture(in: fixturePath)
return try JSONDecoder().decode(decodableType, from: data)
}
}
创建唯一的“文件名”表单URL,包括两个以前的文件夹
func createFileNameFromURL (colorUrl: URL) -> String {
var arrayFolders = colorUrl.pathComponents
// -3 because last element from url is "file name" and 2 previous are folders on server
let indx = arrayFolders.count - 3
var fileName = ""
switch indx{
case 0...:
fileName = arrayFolders[indx] + arrayFolders[indx+1] + arrayFolders[indx+2]
case -1:
fileName = arrayFolders[indx+1] + arrayFolders[indx+2]
case -2:
fileName = arrayFolders[indx+2]
default:
break
}
return fileName
}
正如评论中指出的那样,你可以使用它。
let filename: NSString = "bottom_bar.png"
let pathExtention = filename.pathExtension
let pathPrefix = filename.stringByDeletingPathExtension
适用于Swift 3 / Swift 4.将这些行为添加到String
类:
extension String {
func fileName() -> String {
return NSURL(fileURLWithPath: self).deletingPathExtension?.lastPathComponent ?? ""
}
func fileExtension() -> String {
return NSURL(fileURLWithPath: self).pathExtension ?? ""
}
}
例:
let file = "image.png"
let fileNameWithoutExtension = file.fileName()
let fileExtension = file.fileExtension()
在Swift 2.1中,String.pathExtension不再可用。相反,您需要通过NSURL转换来确定它:
NSURL(fileURLWithPath: filePath).pathExtension
此解决方案适用于所有实例,不依赖于手动解析字符串。
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 3.x最短原生解决方案
let fileName:NSString = "the_file_name.mp3"
let onlyName = fileName.deletingPathExtension
let onlyExt = fileName.pathExtension
没有扩展或任何额外的东西(我已经测试过。基于@gabbler Swift 2的解决方案)
最新的Swift 4.2的工作原理如下:
extension String {
func fileName() -> String {
return URL(fileURLWithPath: self).deletingPathExtension().lastPathComponent
}
func fileExtension() -> String {
return URL(fileURLWithPath: self).pathExtension
}
}