Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/111.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将文件夹与NSFileManager合并,仅覆盖现有文件_Ios_Macos_Cocoa_Nsfilemanager - Fatal编程技术网

Ios 将文件夹与NSFileManager合并,仅覆盖现有文件

Ios 将文件夹与NSFileManager合并,仅覆盖现有文件,ios,macos,cocoa,nsfilemanager,Ios,Macos,Cocoa,Nsfilemanager,基本上,我正在寻找一种方法,用cocoa API合并文件系统中的两个文件夹: 我有一个包含文件和子文件夹的文件夹,我想将其复制到文件系统中的其他位置。 在我的目标路径中,已存在同名文件夹,其中可能还包含文件和文件夹 现在,如果目标文件夹(或其子文件夹)中的现有文件同名,我想用源文件夹的新内容覆盖它们。 我想保留的所有其他文件都不动 sourcefolder | - file1 - subfolder - file2 destinationfolder |

基本上,我正在寻找一种方法,用cocoa API合并文件系统中的两个文件夹:

我有一个包含文件和子文件夹的文件夹,我想将其复制到文件系统中的其他位置。
在我的目标路径中,已存在同名文件夹,其中可能还包含文件和文件夹

现在,如果目标文件夹(或其子文件夹)中的现有文件同名,我想用源文件夹的新内容覆盖它们。
我想保留的所有其他文件都不动

sourcefolder
   |
   - file1
   - subfolder
       - file2


destinationfolder
   |
   - file3
   - subfolder
       - file2
       - file4


resultingfolder
   |
   - file1
   - file3
   - subfolder
       - file2      <-- version from source folder
       - file4
sourcefolder
|
-文件1
-子文件夹
-文件2
目的文件夹
|
-文件3
-子文件夹
-文件2
-文件4
结果文件夹
|
-文件1
-文件3
-子文件夹

-我到处找,但什么也没找到。因此,我提出了自己的解决方案,利用
NSDirectoryEnumerator
。这应该适用于关系图(覆盖旧文件)。希望能有帮助

- (void)mergeContentsOfPath:(NSString *)srcDir intoPath:(NSString *)dstDir error:(NSError**)err {

    NSLog(@"- mergeContentsOfPath: %@\n intoPath: %@", srcDir, dstDir);

    NSFileManager *fm = [NSFileManager defaultManager];
    NSDirectoryEnumerator *srcDirEnum = [fm enumeratorAtPath:srcDir];
    NSString *subPath;
    while ((subPath = [srcDirEnum nextObject])) {

        NSLog(@" subPath: %@", subPath);
        NSString *srcFullPath =  [srcDir stringByAppendingPathComponent:subPath];
        NSString *potentialDstPath = [dstDir stringByAppendingPathComponent:subPath];

        // Need to also check if file exists because if it doesn't, value of `isDirectory` is undefined.
        BOOL isDirectory = ([[NSFileManager defaultManager] fileExistsAtPath:srcFullPath isDirectory:&isDirectory] && isDirectory);

        // Create directory, or delete existing file and move file to destination
        if (isDirectory) {
            NSLog(@"   create directory");
            [fm createDirectoryAtPath:potentialDstPath withIntermediateDirectories:YES attributes:nil error:err];
            if (err && *err) {
                NSLog(@"ERROR: %@", *err);
                return;
            }
        }
        else {
            if ([fm fileExistsAtPath:potentialDstPath]) {
                NSLog(@"   removeItemAtPath");
                [fm removeItemAtPath:potentialDstPath error:err];
                if (err && *err) {
                    NSLog(@"ERROR: %@", *err);
                    return;
                }
            }

            NSLog(@"   moveItemAtPath");
            [fm moveItemAtPath:srcFullPath toPath:potentialDstPath error:err];
            if (err && *err) {
                NSLog(@"ERROR: %@", *err);
                return;
            }
        }
    }
}

查看文件管理器方法,不要使用默认的文件管理器,而是使用alloc/init创建自己的文件管理器,设置一个委托,然后使用委托方法

Swift 3中的解决方案

let merger = FoldersMerger(actionType: .copy, conflictResolution: .keepSource)
merger.merge(atPath: sourceFolder, toPath: destinationFolder)


class FoldersMerger {

    enum ActionType { case move, copy }
    enum ConflictResolution { case keepSource, keepDestination }

    private let fileManager = FileManager()
    private var actionType: ActionType!
    private var conflictResolution: ConflictResolution!
    private var deleteEmptyFolders: Bool!

    init(actionType: ActionType = .move, conflictResolution: ConflictResolution = .keepDestination, deleteEmptyFolders: Bool = false) {
        self.actionType = actionType
        self.conflictResolution = conflictResolution
        self.deleteEmptyFolders = deleteEmptyFolders
    }

    func merge(atPath: String, toPath: String) {
        let pathEnumerator = fileManager.enumerator(atPath: atPath)

        var folders: [String] = [atPath]

        while let relativePath = pathEnumerator?.nextObject() as? String {

            let subItemAtPath = URL(fileURLWithPath: atPath).appendingPathComponent(relativePath).path
            let subItemToPath = URL(fileURLWithPath: toPath).appendingPathComponent(relativePath).path

            if isDir(atPath: subItemAtPath) {

                if deleteEmptyFolders! {
                   folders.append(subItemAtPath)
                }

                if !isDir(atPath: subItemToPath) {
                    do {
                        try fileManager.createDirectory(atPath: subItemToPath, withIntermediateDirectories: true, attributes: nil)
                        NSLog("FoldersMerger: directory created: %@", subItemToPath)
                    }
                    catch let error {
                        NSLog("ERROR FoldersMerger: %@", error.localizedDescription)
                    }
                }
                else {
                    NSLog("FoldersMerger: directory %@ already exists", subItemToPath)
                }
            }
            else {

                if isFile(atPath:subItemToPath) && conflictResolution == .keepSource {
                    do {
                        try fileManager.removeItem(atPath: subItemToPath)
                        NSLog("FoldersMerger: file deleted: %@", subItemToPath)
                    }
                    catch let error {
                        NSLog("ERROR FoldersMerger: %@", error.localizedDescription)
                    }
                }

                do {
                    try fileManager.moveItem(atPath: subItemAtPath, toPath: subItemToPath)
                    NSLog("FoldersMerger: file moved from %@ to %@", subItemAtPath, subItemToPath)
                }
                catch let error {
                    NSLog("ERROR FoldersMerger: %@", error.localizedDescription)
                }
            }
        }

        if deleteEmptyFolders! {
            folders.sort(by: { (path1, path2) -> Bool in
                return path1.characters.split(separator: "/").count < path2.characters.split(separator: "/").count
            })
            while let folderPath = folders.popLast() {
                if isDirEmpty(atPath: folderPath) {
                    do {
                        try fileManager.removeItem(atPath: folderPath)
                        NSLog("FoldersMerger: empty dir deleted: %@", folderPath)
                    }
                    catch {
                        NSLog("ERROR FoldersMerger: %@", error.localizedDescription)
                    }
                }
            }
        }
    }

    private func isDir(atPath: String) -> Bool {
        var isDir: ObjCBool = false
        let exist = fileManager.fileExists(atPath: atPath, isDirectory: &isDir)
        return exist && isDir.boolValue
    }

    private func isFile(atPath: String) -> Bool {
        var isDir: ObjCBool = false
        let exist = fileManager.fileExists(atPath: atPath, isDirectory: &isDir)
        return exist && !isDir.boolValue
    }

    private func isDirEmpty(atPath: String) -> Bool {
        do {
            return try fileManager.contentsOfDirectory(atPath: atPath).count == 0
        }
        catch _ {
            return false
        }
    }
}
let merge=FoldersMerger(操作类型:。复制,冲突解决:。keepSource)
merge.merge(atPath:sourceFolder,toPath:destinationFolder)
类折叠器{
枚举操作类型{case move,copy}
枚举冲突解决{case keepSource,keepDestination}
private let fileManager=fileManager()
私有var actionType:actionType!
私有var冲突解决:冲突解决!
私人var deleteEmptyFolders:Bool!
init(actionType:actionType=.move,conflictResolution:conflictResolution=.keepDestination,deleteEmptyFolders:Bool=false){
self.actionType=actionType
self.conflictdolution=冲突解决
self.deleteEmptyFolders=deleteEmptyFolders
}
func合并(atPath:String,toPath:String){
让pathEnumerator=fileManager.enumerator(atPath:atPath)
变量文件夹:[String]=[atPath]
而让relativePath=pathEnumerator?.nextObject()作为?字符串{
让subItemAtPath=URL(fileURLWithPath:atPath).appendingPathComponent(relativePath).path
让subItemToPath=URL(fileURLWithPath:toPath).appendingPathComponent(relativePath).path
if isDir(atPath:子项atPath){
如果删除空文件夹{
文件夹。追加(子项路径)
}
if!isDir(atPath:subItemToPath){
做{
尝试fileManager.createDirectory(路径:subItemToPath,中间目录:true,属性:nil)
NSLog(“FoldersMerger:已创建目录:%@”,子项路径)
}
捕捉错误{
NSLog(“错误文件夹:%@”,错误。本地化描述)
}
}
否则{
NSLog(“FoldersMerger:目录%@已存在”,子项路径)
}
}
否则{
如果isFile(atPath:subItemToPath)&&conflictsolution==.keepSource{
做{
尝试fileManager.removeItem(路径:subItemToPath)
NSLog(“文件夹:文件已删除:%@”,子项路径)
}
捕捉错误{
NSLog(“错误文件夹:%@”,错误。本地化描述)
}
}
做{
尝试fileManager.moveItem(atPath:subItemAtPath,toPath:subItemToPath)
NSLog(“文件夹:文件从%@移动到%@”,子项路径,子项路径)
}
捕捉错误{
NSLog(“错误文件夹:%@”,错误。本地化描述)
}
}
}
如果删除空文件夹{
排序(按:{(路径1,路径2)->Bool-in
返回路径1.characters.split(分隔符:“/”).countBool{
var isDir:ObjCBool=false
let exist=fileManager.fileExists(atPath:atPath,isDirectory:&isDir)
返回exist&&isDir.boolValue
}
私有函数isFile(atPath:String)->Bool{
var isDir:ObjCBool=false
let exist=fileManager.fileExists(atPath:atPath,isDirectory:&isDir)
返回exist&!isDir.boolValue
}
private func isDirEmpty(atPath:String)->Bool{
做{
返回try fileManager.contentsOfDirectory(atPath:atPath).count==0
}
接住{
返回错误
}
}
}

谢谢您的建议!我还发现,还有其他方法可以更干净地做到这一点。我将编辑我的答案。