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

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

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

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

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

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

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

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

 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. } 

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

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

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

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

Пример кода в 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 } } } 

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

 NSData *imgDta = UIImageJPEGRepresentation(tImg, 1.0); [imgDta writeToFile:targetPath options:NSDataWritingFileProtectionNone error:&err]; 

Удаление и копирование файлов в цикле иногда не работает должным образом

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

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

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

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

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

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

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

  • Сохранение файла CSV с помощью CHCSVWriter
  • NSBundleResourceRequest bundlePath
  • iOS - весь каталог документов Flag, не поддерживающий резервное копирование
  • -writeToURL не перезаписывает предыдущую запись
  • Лучшее место для сохранения изображения, загруженного из Интернета на устройствах iOS?
  • Почему NSMutableDictionary не хочет записывать в файл?
  • Не удалось создать файлы в каталоге кешей
  • Основные данные против NSFileManager
  • Получить список файлов на пути swift
  • NSFileManager создает ошибку каталога 518 NSFileWriteUnsupportedSchemeError
  • Совместное использование базы данных между несколькими приложениями быстрого доступа
  • Interesting Posts

    Почему EAAccessoryDidConnectNotification происходит дважды?

    Размер ячейки UICollectionView в AutoLayout

    Какие расширения GLSL ES доступны на разных устройствах iOS?

    com.datastax.driver.core.exceptions.NoHostAvailableException

    Добавить значок Airplay в AVPlayer

    Изменить внешний вид UIStepper

    Назначение 'id <UINavigationControllerDelegate, UIImagePickerControllerDelegate>' из несовместимого типа 'ViewController * const__strong'

    Получите пользовательский UITableViewCell, который содержит нажатие UIButton

    Найти условие соответствия первого элемента в массиве Swift (например, EKSource)

    Swift 3 – Дождаться результата сервера

    «Установка приложения Apple Watch никогда не завершалась» Ошибка при развертывании приложения для набора часов на устройство

    Открывать UIDocument синхронно

    Быстрое рисование полупрозрачных линий, как сделать перекрывающиеся части не темными?

    Как автоматически выполнять модульные тесты для каждого действия «строить и запускать» в XCode 5?

    Есть ли способ сделать цвет фона градиента в построителе интерфейса?

    Давайте будем гением компьютера.