Programing

Swift에서 파일 확장자에서 파일 이름을 분할하는 방법은 무엇입니까?

lottogame 2020. 12. 6. 20:50
반응형

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보다 훨씬 더 우아한 언어처럼 보였기 때문에 흥분했습니다.하지만 이제는 그 자체가 번거 롭다는 것을 알게되었습니다.


두 번째 시도 : 나만의 문자열 검색 방법을 만들기로 결정했습니다.

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

주석에서 지적했듯이 이것을 사용할 수 있습니다.

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

솔루션 스위프트 4

이 솔루션은 모든 인스턴스에서 작동하며 문자열을 수동으로 구문 분석하는 데 의존하지 않습니다.

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 4.2는 다음과 같이 작동합니다.

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

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

SWIFT 3.x 최단 네이티브 솔루션

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

확장 또는 추가 항목 없음 (Swift 2의 @gabbler 솔루션을 기반으로 테스트했습니다)


Swift의 문자열은 확실히 까다로울 수 있습니다. 순수한 Swift 메서드를 원한다면 다음과 같이 할 수 있습니다.

  1. 문자열 find"."에서 마지막 항목을 찾는 데 사용 reverse합니다.
  2. 원래 문자열에서의 advance올바른 색인을 가져 오는 데 사용 "."합니다.
  3. 문자열을 가져 오는 데 걸리는 Stringsubscript함수를 사용하십시오.IntervalType
  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방법 등을 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"

스위프트 5

 URL(string: filePath)?.pathExtension

스위프트 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 "을 포함합니다.


더 나은 방법 (또는 적어도 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]

확장명이 PHAsset다음 과 같은 Swift 4에 대한 정리 된 답변 :

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은 자산을 만들거나 가져올 당시의 자산 이름입니다.


Maybe I'm getting too late for this but a solution that worked for me and consider quite simple is using the #file compiler directive. Here is an example where I have a class FixtureManager, defined in FixtureManager.swift inside the /Tests/MyProjectTests/Fixturesdirectory. This works both in Xcode and withswift 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)
    }

}

Creates unique "file name" form url including two previous folders

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
}

참고URL : https://stackoverflow.com/questions/26707352/how-to-split-filename-from-file-extension-in-swift

반응형