ios - saber - programas para abrir archivos de todo tipo
¿Cómo dividir el nombre de archivo de la extensión de archivo en Swift? (19)
Solución Swift 4
Esta solución funcionará para todas las instancias y no depende del análisis manual de la cadena.
let path = "/Some/Random/Path/To/This.Strange.File.txt"
let fileName = URL(fileURLWithPath: path).deletingPathExtension().lastPathComponent
Swift.print(fileName)
La salida resultante será
This.Strange.File
Dado el nombre de un archivo en el paquete, quiero cargar el archivo en mi aplicación Swift. Entonces necesito usar este método:
let soundURL = NSBundle.mainBundle().URLForResource(fname, withExtension: ext)
Por alguna razón, el método necesita un nombre de archivo separado de la extensión del archivo. Bien, es bastante fácil separar los dos en la mayoría de los idiomas. Pero hasta ahora no creo que sea así en Swift.
Entonces, esto es lo que tengo:
var rt: String.Index = fileName.rangeOfString(".", options:NSStringCompareOptions.BackwardsSearch)
var fname: String = fileName .substringToIndex(rt)
var ext = fileName.substringFromIndex(rt)
Si no incluyo la escritura en la primera línea, obtengo errores en las dos líneas siguientes. Con él, obtengo un error en la primera línea:
Cannot convert the expression''s type ''(UnicodeScalarLiteralConvertible, options: NSStringCompareOptions)'' to type ''UnicodeScalarLiteralConvertible''
¿Cómo puedo dividir el nombre de archivo de la extensión? ¿Hay alguna forma elegante de hacer esto?
Estaba muy entusiasmado con Swift porque parecía un lenguaje mucho más elegante que el Objetivo C. Pero ahora descubro que tiene su propia complejidad.
Segundo intento: decidí hacer mi propio método de búsqueda de cadenas:
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
}
Pero ahora recibo un error en la línea
var rt: String.Index = rfind(fileName, needle: ".")
:
''Int'' is not convertible to ''String.Index''
Sin el elenco, obtengo un error en las dos líneas siguientes.
¿Alguien puede ayudarme a dividir este nombre de archivo y extensión?
Como se señaló en el comentario, puede usar esto.
let filename: NSString = "bottom_bar.png"
let pathExtention = filename.pathExtension
let pathPrefix = filename.stringByDeletingPathExtension
Crea una URL de formulario única de "nombre de archivo" que incluye dos carpetas anteriores
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
}
El último Swift 4.2 funciona así:
extension String {
func fileName() -> String {
return URL(fileURLWithPath: self).deletingPathExtension().lastPathComponent
}
func fileExtension() -> String {
return URL(fileURLWithPath: self).pathExtension
}
}
En Swift 2.1 String.pathExtension ya no está disponible. En su lugar, debe determinarlo a través de la conversión NSURL:
NSURL(fileURLWithPath: filePath).pathExtension
En Swift 2.1, parece que la forma actual de hacer esto es:
let filename = fileURL.URLByDeletingPathExtension?.lastPathComponent
let extension = fileURL.pathExtension
En Swift puede cambiar a
NSString
para obtener una extensión más rápida:
extension String {
func getPathExtension() -> String {
return (self as NSString).pathExtension
}
}
Esto es con Swift 2, Xcode 7: si ya tiene el nombre de archivo con la extensión, puede pasar el nombre de archivo completo como primer parámetro y una cadena en blanco como segundo parámetro:
let soundURL = NSBundle.mainBundle()
.URLForResource("soundfile.ext", withExtension: "")
Alternativamente nil como el parámetro de extensión también funciona.
Si tiene una URL y desea obtener el nombre del archivo en sí mismo por alguna razón, puede hacer esto:
soundURL.URLByDeletingPathExtension?.lastPathComponent
Swift 4
let soundURL = NSBundle.mainBundle().URLForResource("soundfile.ext", withExtension: "")
soundURL.deletingPathExtension().lastPathComponent
Funciona con Swift 3 / Swift 4. Agregar estos comportamientos a
String
clase
String
:
extension String {
func fileName() -> String {
return NSURL(fileURLWithPath: self).deletingPathExtension?.lastPathComponent ?? ""
}
func fileExtension() -> String {
return NSURL(fileURLWithPath: self).pathExtension ?? ""
}
}
Ejemplo:
let file = "image.png"
let fileNameWithoutExtension = file.fileName()
let fileExtension = file.fileExtension()
Las cadenas en Swift definitivamente pueden ser complicadas. Si quieres un método Swift puro, así es como lo haría:
-
Use
find
para encontrar la última aparición de un"."
en elreverse
de la cuerda -
Use el
advance
para obtener el índice correcto de"."
en la cadena original -
Use
String
función desubscript
String
que toma unIntervalType
para obtener las cadenas - Empaquete todo esto en una función que devuelva una tupla opcional del nombre y la extensión
Algo como esto:
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
}
Que se usaría como:
let str = "/Users/me/Documents/Something.something/text.txt"
if let split = splitFilename(str) {
println(split.name)
println(split.ext)
}
Qué salidas:
/Users/me/Documents/Something.something/text
txt
O simplemente use los
métodos
NSString
ya disponibles
como
pathExtension
y
stringByDeletingPathExtension
.
Pruebe esto para obtener una solución simple de 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"
Se libraron de pathExtension por cualquier razón.
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 3.0
let sourcePath = NSURL(string: fnName)?.pathExtension
let pathPrefix = fnName.replacingOccurrences(of: "." + sourcePath!, with: "")
Swift 5
URL(string: filePath)?.pathExtension
Tal vez estoy llegando demasiado tarde para esto, pero una solución que funcionó para mí y considero bastante simple es usar la directiva del compilador
#file
.
Aquí hay un ejemplo donde tengo una clase
FixtureManager
, definida en
FixtureManager.swift
dentro del
directory. This works both in Xcode and with
/ Tests / MyProjectTests / Fixtures
directory. This works both in Xcode and with
directory. This works both in Xcode and with
prueba rápida`
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)
}
}
Una mejor manera (o al menos una alternativa en Swift 2.0) es usar la propiedad String pathComponents. Esto divide el nombre de ruta en una matriz de cadenas. p.ej
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!
Una respuesta limpia para Swift 4 con una extensión fuera 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
}
}
Como se señaló en XCode, el nombre de archivo original es el nombre del activo en el momento en que se creó o importó.
La solución nativa más corta de SWIFT 3.x
let fileName:NSString = "the_file_name.mp3"
let onlyName = fileName.deletingPathExtension
let onlyExt = fileName.pathExtension
Sin extensión ni material adicional (lo he probado. Basado en la solución @gabbler para Swift 2)
Solución extendida 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)
nombre de archivo constante ahora contiene " filename_v123.456 "