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

Как перезаписать файл с помощью NSFileManager при копировании?

Я использую этот метод для копирования файла:

[fileManager copyItemAtPath:sourcePath toPath:targetPath error:&error];

Я хочу перезаписать файл, когда он уже существует. Поведение этого метода по умолчанию заключается в том, чтобы выдать исключение/ошибку "Файл существует". когда файл существует. Нет возможности указать, что он должен быть перезаписан.

Итак, какой был бы самый безопасный способ сделать это?

Я должен сначала проверить, существует ли файл, а затем удалить его, а затем попытаться скопировать? Это может привести к тому, что приложение или устройство выключится прямо в наносекунду после удаления файла, но новый файл не был скопирован в это место. Тогда ничего.

Возможно, мне сначала нужно будет изменить имя нового файла, а затем удалить старый, а затем изменить имя нового? Та же проблема. Что делать, если в этот наносекунд приложение или устройство выключится, а переименование не произойдет?

4b9b3361

Ответ 1

В этом случае вы хотите сделать атомное сохранение, чего лучше всего использовать с помощью методов NSData или NSString writeToFile:atomically: (и их вариантов):

NSData *myData = ...; //fetched from somewhere
[myData writeToFile:targetPath atomically:YES];

Или для NSString:

NSString *myString = ...;
NSError *err = nil;
[myString writeToFile:targetPath atomically:YES encoding:NSUTF8StringEncoding error:&err];
if(err != nil) {
  //we have an error.
}

Ответ 2

Если вы не можете/не хотите хранить содержимое файла в памяти, но хотите, чтобы атомный переписывать, как указано в других предложениях, вы можете сначала скопировать исходный файл в каталог temp по уникальному пути (документация Apple предлагает использовать временный каталог), а затем использовать NSFileManager

-replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:

В соответствии с справочной документацией этот метод "заменяет содержимое элемента по указанному URL таким образом, который не обеспечивает потерю данных". (из справочной документации). Копирование оригинала во временный каталог необходимо, потому что этот метод перемещает исходный файл. Здесь справочная документация NSFileManager о -replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:

Ответ 3

Обнаружение файла существует ошибка, удалите файл назначения и снова скопируйте.

Пример кода в Swift 2.0:

class MainWindowController: NSFileManagerDelegate {

    let fileManager = NSFileManager()

    override func windowDidLoad() {
        super.windowDidLoad()
        fileManager.delegate = self
        do {
            try fileManager.copyItemAtPath(srcPath, toPath: dstPath)
        } catch {
            print("File already exists at \'\(srcPath)\':\n\((error as NSError).description)")
        }
    }

    func fileManager(fileManager: NSFileManager, shouldProceedAfterError error: NSError, copyingItemAtPath srcPath: String, toPath dstPath: String) -> Bool {
        if error.code == NSFileWriteFileExistsError {
            do {
                try fileManager.removeItemAtPath(dstPath)
                print("Existing file deleted.")
            } catch {
                print("Failed to delete existing file:\n\((error as NSError).description)")
            }
            do {
                try fileManager.copyItemAtPath(srcPath, toPath: dstPath)
                print("File saved.")
            } catch {
                print("File not saved:\n\((error as NSError).description)")
            }
            return true
        } else {
            return false
        }
    }
}

Ответ 4

Для перезаписи файлов я предпочитаю

NSData *imgDta = UIImageJPEGRepresentation(tImg, 1.0);

[imgDta writeToFile:targetPath options:NSDataWritingFileProtectionNone error:&err];

Удаление и копирование файлов в цикле иногда не работает по назначению

Ответ 5

Я думаю, что возможность наносекунды, которую вы наделали, слаба. поэтому придерживайтесь первого метода удаления существующего файла и копирования нового файла.

Ответ 6

Я думаю, что вы ищете метод протокола NSFileManagerDelegate:

- (BOOL)fileManager:(NSFileManager *)fileManager shouldProceedAfterError:(NSError *)error copyingItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath;

Из этого метода вы можете решить, что делать с существующим файлом (переименовать/удалить), а затем продолжить копирование.

Ответ 7

Swift4:

_ = try FileManager.default.replaceItemAt(previousItemUrl, withItemAt: currentItemUrl)

Ответ 8

Это для улучшения "Swift 3 и выше" вопроса "Переместить файл и переопределить [duplicate] ', который отмечен как дубликат этого вопроса.

Переместить файл из sourcepath (string) в DestinationPath (строка). Удалите существующий файл, если тот же файл имен уже существует в DestinationPath.

// Set the correct path in string in 'let' variables.
let destinationStringPath = ""
let sourceStringPath = ""

let fileManager:FileManager = FileManager.default
do
{
    try fileManager.removeItem(atPath: sourceStringPath)
}
catch
{
}

do
{
    try fileManager.moveItem(atPath: sourceStringPath, toPath: destinationStringPath)
}
catch
{
}

Ответ 9

Я знаю, что это маленький тяжеловес, но он работает для меня:

task = Process()
task.launchPath = "/bin/cp"
task.arguments = [srcPath, dstPath]
task.launch()
task.waitUntilExit()

Иногда производительность не является проблемой, и нам просто нужно что-то простое и просто работает.