Étant donné le nom d'un fichier dans le paquet, je veux charger le fichier dans mon application Swift. J'ai donc besoin d'utiliser cette méthode:
let soundURL = NSBundle.mainBundle().URLForResource(fname, withExtension: ext)
Pour une raison quelconque, la méthode nécessite le nom de fichier séparé de l'extension de fichier. Bien, il est assez facile de séparer les deux dans la plupart des langues. Mais jusqu'à présent, je ne le trouve pas à Swift.
Alors voici ce que j'ai:
var rt: String.Index = fileName.rangeOfString(".", options:NSStringCompareOptions.BackwardsSearch)
var fname: String = fileName .substringToIndex(rt)
var ext = fileName.substringFromIndex(rt)
Si je n'inclue pas la saisie sur la première ligne, des erreurs apparaissent sur les deux lignes suivantes. Avec cela, je reçois une erreur sur la première ligne:
Cannot convert the expression's type '(UnicodeScalarLiteralConvertible, options: NSStringCompareOptions)' to type 'UnicodeScalarLiteralConvertible'
Comment puis-je séparer le nom du fichier de l'extension? Y a-t-il une manière élégante de faire ceci?
Swift me passionnait à tous les égards car il semblait être un langage beaucoup plus élégant que l’objectif C. Mais à présent, je constate qu’il a sa propre lourdeur.
Deuxième tentative: j'ai décidé de créer ma propre méthode de recherche de chaînes:
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
}
Mais maintenant, je reçois une erreur sur la ligne var rt: String.Index = rfind(fileName, needle: ".")
:
'Int' is not convertible to 'String.Index'
Sans le casting, j'obtiens une erreur sur les deux lignes suivantes.
Quelqu'un peut-il m'aider à scinder ce nom de fichier et cette extension?
C’est avec Swift 2, Xcode 7: Si vous avez déjà le nom de fichier avec l’extension, vous pouvez alors passer le nom de fichier complet en tant que premier paramètre et une chaîne vide en tant que second paramètre:
let soundURL = NSBundle.mainBundle()
.URLForResource("soundfile.ext", withExtension: "")
Sinon, nil en tant que paramètre d'extension fonctionne également.
Si vous avez une URL et que vous souhaitez obtenir le nom du fichier lui-même pour une raison quelconque, procédez comme suit:
soundURL.URLByDeletingPathExtension?.lastPathComponent
Swift 4
let soundURL = NSBundle.mainBundle().URLForResource("soundfile.ext", withExtension: "")
soundURL.deletingPathExtension().lastPathComponent
Comme indiqué dans le commentaire, vous pouvez l'utiliser.
let filename: NSString = "bottom_bar.png"
let pathExtention = filename.pathExtension
let pathPrefix = filename.stringByDeletingPathExtension
Fonctionne avec Swift 3/Swift 4. Ajout de ces comportements à la classe String
:
extension String {
func fileName() -> String {
return NSURL(fileURLWithPath: self).deletingPathExtension?.lastPathComponent ?? ""
}
func fileExtension() -> String {
return NSURL(fileURLWithPath: self).pathExtension ?? ""
}
}
Exemple:
let file = "image.png"
let fileNameWithoutExtension = file.fileName()
let fileExtension = file.fileExtension()
Dans Swift 2.1, String.pathExtension n'est plus disponible. Au lieu de cela, vous devez le déterminer par la conversion NSURL:
NSURL(fileURLWithPath: filePath).pathExtension
Cette solution fonctionnera pour toutes les instances et ne dépend pas de l'analyse manuelle de la chaîne.
let path = "/Some/Random/Path/To/This.Strange.File.txt"
let fileName = URL(fileURLWithPath: path).deletingPathExtension().lastPathComponent
Swift.print(fileName)
La sortie résultante sera
This.Strange.File
Dans Swift, vous pouvez passer à NSString
pour obtenir une extension plus rapidement:
extension String {
func getPathExtension() -> String {
return (self as NSString).pathExtension
}
}
Dans Swift 2.1, il semble que la manière actuelle de faire cela est:
let filename = fileURL.URLByDeletingPathExtension?.lastPathComponent
let extension = fileURL.pathExtension
Solution native la plus courte 3.x de Swift
let fileName:NSString = "the_file_name.mp3"
let onlyName = fileName.deletingPathExtension
let onlyExt = fileName.pathExtension
Aucune extension ni aucun élément supplémentaire (J'ai testé. Basé sur la solution @gabbler pour Swift 2)
Les cordes dans Swift peuvent certainement être délicates. Si vous voulez une méthode Swift pure, voici comment je le ferais:
find
pour trouver la dernière occurrence d'un "."
dans le reverse
de la chaîneadvance
pour obtenir le bon index du "."
dans la chaîne d'origineString
de subscript
qui prend une IntervalType
pour obtenir les chaînesQuelque chose comme ça:
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
}
Ce qui serait utilisé comme:
let str = "/Users/me/Documents/Something.something/text.txt"
if let split = splitFilename(str) {
println(split.name)
println(split.ext)
}
Quelles sorties:
/Users/me/Documents/Something.something/text
txt
Ou bien, utilisez simplement les méthodes déjà disponibles NSString
like pathExtension
et stringByDeletingPathExtension
.
Essayez ceci pour une solution simple 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"
La dernière version de Swift 4.2 fonctionne comme ceci:
extension String {
func fileName() -> String {
return URL(fileURLWithPath: self).deletingPathExtension().lastPathComponent
}
func fileExtension() -> String {
return URL(fileURLWithPath: self).pathExtension
}
}
Swift 3.x extended solution:
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)
la constante de nom de fichier contient maintenant "filename_v123.456"
Swift 5
URL(string: filePath)?.pathExtension
Swift 3.0
let sourcePath = NSURL(string: fnName)?.pathExtension
let pathPrefix = fnName.replacingOccurrences(of: "." + sourcePath!, with: "")
Une réponse nettoyée pour Swift 4 avec une extension de 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
}
}
Comme indiqué dans XCode, le nom de fichier d'origine est le nom de l'actif au moment de sa création ou de son importation.
Crée une URL de formulaire "nom de fichier" unique comprenant deux dossiers précédents
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
}
Un meilleur moyen (ou au moins une alternative dans Swift 2.0) consiste à utiliser la propriété String pathComponents. Cela divise le chemin en un tableau de chaînes. par exemple
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!
Peut-être que je commence trop tard pour cela, mais une solution qui fonctionne pour moi et que je considère assez simple consiste à utiliser la directive de compilation #file
. Voici un exemple où j'ai une classe FixtureManager
, définie dans FixtureManager.Swift
à l'intérieur du/Tests/MyProjectTests/Fixturesdirectory. This works both in Xcode and with
Swift test`
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)
}
}
Ils se sont débarrassés de pathExtension pour une raison quelconque.
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]