Подтвердить что ты не робот

Временный путь к файлу с использованием быстрого

Как получить уникальный временный путь к файлу с помощью Swift/Cocoa в OS X? Cocoa, как представляется, не обеспечивает функцию для этого, только NSTemporaryDirectory(), которая возвращает путь к временному каталогу. Для использования функции BSD mktemp требуется переменная C-строка в качестве аргумента.

4b9b3361

Ответ 1

Вот возможный способ использовать mkstemp() из Swift 3 и более поздних mkstemp(). Методы URL используются для преобразования между экземплярами URL и строками C, представляющими путь файловой системы:

// The template string:
let template = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("file.XXXXXX") as NSURL

// Fill buffer with a C string representing the local file system path. 
var buffer = [Int8](repeating: 0, count: Int(PATH_MAX))
template.getFileSystemRepresentation(&buffer, maxLength: buffer.count)

// Create unique file name (and open file):
let fd = mkstemp(&buffer)
if fd != -1 {

    // Create URL from file system string:
    let url = URL(fileURLWithFileSystemRepresentation: buffer, isDirectory: false, relativeTo: nil)
    print(url.path)

} else {
    print("Error: " + String(cString: strerror(errno)))
}

Старый код для Swift 2:

// The template string:
let template = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("file.XXXXXX")

// Fill buffer with a C string representing the local file system path. 
var buffer = [Int8](count: Int(PATH_MAX), repeatedValue: 0)
template.getFileSystemRepresentation(&buffer, maxLength: buffer.count)

// Create unique file name (and open file):
let fd = mkstemp(&buffer)
if fd != -1 {

    // Create URL from file system string:
    let url = NSURL(fileURLWithFileSystemRepresentation: buffer, isDirectory: false, relativeToURL: nil)
    print(url.path!)

} else {
    print("Error: " + String(strerror(errno)))
}

Ответ 2

Apple пытается отойти от пути к строке и в NSURL. Здесь один из способов:

Swift 3:

let directory = NSTemporaryDirectory()
let fileName = NSUUID().uuidString

// This returns a URL? even though it is an NSURL class method
let fullURL = NSURL.fileURL(withPathComponents: [directory, fileName])

Swift 2:

let directory = NSTemporaryDirectory()
let fileName = NSUUID().UUIDString

let fullURL = NSURL.fileURLWithPathComponents([directory, fileName])

Ответ 3

A Swift 3 с одним слоем, основанный на ответе Swift 2 на основе UUID:

let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)

Ответ 4

Используйте GUID (глобально уникальный идентификатор):

let directory :NSString = "directory"
let randomName = NSProcessInfo().globallyUniqueString
let path = directory.stringByAppendingPathComponent(randomName)

Каталог/3B635E49-813A-4324-B4B8-56279B42BEAB-36687-0002D962615DAE5F

Ответ 5

Мне нравится идея этой статьи: NSTeorary Directory - NSHipster

При этом для создания уникальной строки используется NSTemporaryDirectory() для временной папки и ProcessInfo.processInfo.globallyUniqueString.

Свифт 4:

func uniqueTempFolderURL() -> URL
{
    let folderName = ProcessInfo.processInfo.globallyUniqueString
    return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(folderName)
}

Ответ 6

Swift3

Я пришел сюда, чтобы найти что-то вроде boost:: filesystem:: unique_path()

Итак, я сделал это расширение для класса URL.

extension URL {
    func appendingUniquePathComponent(pathExtension: String? = nil) -> URL {
        var pathComponent = UUID().uuidString
        if let pathExtension = pathExtension {
            pathComponent += ".\(pathExtension)"
        }
        return appendingPathComponent(pathComponent)
    }
}

Использование:

let url0 = URL(fileURLWithPath: "/tmp/some/dir")
let url1 = url0.appendingUniquePathComponent(pathExtension: "jpg")
print("url1: \(url1)")
// url1: file:///tmp/some/dir/936324FF-EEDB-410E-AD09-E24D5EB4A24F.jpg

Ответ 7

Хотя NSTemporaryDirectory() действительно возвращает временный путь к каталогу для текущего пользователя, документация содержит следующее предупреждение:

См. url(for:in:appropriateFor:create:) метода FileManager url(for:in:appropriateFor:create:) FileManager url(for:in:appropriateFor:create:) чтобы узнать о предпочтительных способах поиска правильного временного каталога.

По этой ссылке мы представляем следующее:

Вы можете использовать этот метод для создания нового временного каталога. Для этого укажите FileManager.SearchPathDirectory.itemReplacementDirectory для параметра directory, userDomainMask для параметра domain и URL-адрес для параметра url который определяет объем возвращаемого URL-адреса.

Например, следующий код приводит к созданию нового временного каталога с путем в виде /private/var/folders/d0/h37cw8ns3h1bfr_2gnwq2yyc0000gn/T/TemporaryItems/Untitled/:

let desktop = URL(fileURLWithPath: "/Users/jappleseed/Desktop/")

do {
   let temporaryDirectory = try FileManager.default.url(
       for: .itemReplacementDirectory,
       in: .userDomainMask,
       appropriateFor: desktop,
       create: true
   )

   print(temporaryDirectory)
} catch {
   // Handle the error.
}

(Обратите внимание, что параметр create игнорируется при создании временного каталога.)

Так в чем же разница между этими двумя подходами? Хорошо, вот что я получаю, когда вызываю два разных метода из Swift REPL:

1> import Foundation

2> NSTemporaryDirectory() 
$R0: String = "/var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/"

3> let desktop = URL(fileURLWithPath: "/Users/chris/Desktop/") 
desktop: URL = "file:///Users/chris/Desktop/"

4> let temporaryDirectory = try FileManager.default.url( 
5.     for: .itemReplacementDirectory, 
6.     in: .userDomainMask, 
7.     appropriateFor: desktop, 
8.     create: true 
9. )
temporaryDirectory: URL = "file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20repl_swift)/"

Похоже, что NSTemporaryDirectory() всегда будет возвращать путь к временному каталогу для текущего пользователя, тогда как FileManager url(for:appropriateFor:create) FileManager url(for:appropriateFor:create) FileManager url(for:appropriateFor:create) будет возвращать новый временный подкаталог при каждом вызове. Например, вот каталоги, возвращаемые последовательными вызовами url(for:in:appropriateFor:create:) из Swift REPL:

  • file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20repl_swift)/
  • file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20repl_swift%202)/
  • file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20repl_swift%203)/

А вот каталоги, возвращаемые последовательными вызовами одного и того же метода из Swift Playground:

  • file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20Xcode)/
  • file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20Xcode%202)/
  • file:///var/folders/n_/0_9q7d2d1ls5v9kx599y_tj00000gn/T/TemporaryItems/(A%20Document%20Being%20Saved%20By%20Xcode%203)/

Статья NSHipster о временных файлах, по- видимому, предполагает, что url(for:in:appropriateFor:create:) метода FileManager url(for:in:appropriateFor:create:) FileManager url(for:in:appropriateFor:create:) предназначен для использования при подготовке файла для перемещения в более постоянное местоположение (например, рабочий стол пользователя в примере выше), но я не понимаю, почему он не может быть использован для простого получения уникального подкаталога, который будет автоматически удален, когда вы закончите с ним, и где вам не нужно беспокоиться о случайном попадании файлов другие процессы записывают в тот же временный каталог.

Ответ 8

Расширение FileManager в Swift для получения временного URL файла. Вы можете передать собственное имя файла и расширение, если это необходимо.

public extension FileManager {

    func temporaryFileURL(fileName: String = UUID().uuidString) -> URL? {
        return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(fileName)
    }
}

Использование:

let tempURL = FileManager.default.temporaryFileURL()
let tempJPG = FileManager.default.temporaryFileURL(fileName: "temp.jpg")