【问题标题】:Unable to rename the file while moving from temporary directorary从临时目录移动时无法重命名文件
【发布时间】:2019-01-07 21:17:08
【问题描述】:

我正在开发一个 zip 提取器应用程序,我遵循 CRD 解释的算法@Here,但我停留在第三步,我无法重命名临时目录中的解压缩文件。 这是我的代码

  NSURL *tempDir = [NSURL fileURLWithPath:destinationPath];
        NSError *error;

        NSURL *tmpDirectory = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:tempDir create:YES error:&error];
        if (error) {
            return ;
        }
        tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];
        NSLog(@"temp dir %@",tmpDirectory);
        NSLog(@"temp path %@",tmpDirectory.path);


        [SSZipArchive unzipFileAtPath:zipFilePath toDestination:tmpDirectory.path];

        NSArray *dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpDirectory.path error:nil];
        NSLog(@"dir file %@",dirFiles);
        for (NSString *string in dirFiles) {

            NSArray *dirDestinationFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:destinationPath error:nil];
            NSLog(@"dir destination file %@",dirDestinationFiles);
            [dirDestinationFiles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSFileManager *fm = [NSFileManager defaultManager];
                NSError *error;


                if ([string isEqualToString:obj]) {


                    NSLog(@"Already present");

                    BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path  toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-1",string]] error:&error];

                    if (isMoved) {
                        NSLog(@"Moved");
                    }else{
                        NSLog(@"errorL %@", error);
                        NSLog(@"Not moved");
                    }

                    [fm removeItemAtPath:tmpDirectory.path error:&error];

                    [self moveFileToTrash:zipFilePath];
                    [self openExtractedFolderWithZipPath:zipFilePath toDestinationPath:destinationPath];

                }

            }];


        }

任何建议.. 提前致谢!

【问题讨论】:

  • 到底发生了什么? ` NSLog(@"errorL %@", error);` 是否输出了一些东西? tmpDirectory 有错误吗?
  • @Larme 没有错误输出变得像Cannot make directory /Users/Prem/Downloads: File exists
  • 解压缩文件可能已将一个或多个项目放入您的临时目录中,您需要将这些项目中的每一个移动到目录destinationPath 中。您的代码正在尝试复制临时目录本身,而不是其内容。要移动每个项目,您必须处理名称冲突,为此请尝试移动,如果您收到指示名称冲突的错误,请根据您的喜好修改目标名称并重试移动,重复直到成功或达到某个限制尝试次数(由您决定)。
  • @CRD 代码已编辑,如您所见,我可以再创建一个实例( BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-1 ",string]] error:&error]; ) 这个硬编码我如何动态地制作多个。

标签: objective-c macos cocoa unzip


【解决方案1】:

让我们检查一下您的代码,希望对您有所帮助。

这可能看起来很小,但请选择好的变量名:

NSURL *tempDir = [NSURL fileURLWithPath:destinationPath];
NSURL *tmpDirectory = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:tempDir create:YES error:&error];

对于不同的事物来说,两个在语义上相似的名字,这只是令人困惑。比如说destinationURL 而不是tempDir 怎么样?

接下来,在构建/拆开/等时。路径名或 URL 最好保持一致。 NSURLNSString 都为这些操作提供了类似的方法,您可以在一个地方使用它们:

tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];

然后使用路径分隔符恢复为直接字符串操作,这可能是正确的,也可能不是正确的:

[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-1",string]]

NSURLNSString 提供的例程从路径分隔符的细节以及如何找到最后一个路径组件上的扩展名(在重命名以避免冲突时可能会发现它很有用)的细节中抽象出来。

回到:

tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];

您没有理由这样做。临时目录是为您创建的,您应该在使用后将其删除。因此无需在其中创建子目录extracts,并且通过重新分配给同一个变量,您已经丢失了删除临时目录所需的 URL。

现在有些不太明显,在我上面的评论中我写道:

要移动每个项目,您必须处理名称冲突,为此请尝试移动,如果出现指示名称冲突的错误,请根据需要修改目标名称并重新尝试移动,重复直到成功或直到达到一定的尝试次数限制(由您决定)。

我没有解释为什么你应该这样做,你已经用不同的方式解决了这个问题:对于你要移动的每个项目,你检查名称冲突在尝试移动之前遍历目标目录中的名称。

如果您阅读 Apple 关于文件系统的文档,您会发现他们经常建议您尝试一个操作,然后检查返回的任何错误,而不是尝试预测是否会发生错误并避免它。这样做的原因是文件系统是动态的,其他进程可以修改它,所以如果你试图避免错误,你可能仍然会得到一个。在伪代码中,您最好执行以下操作:

moveDone = false
attemptCount = 0
while not moveDone and attemptCount < MAX_ATTEMPTS
   move object
   if object exists error
      modify destination URL
      increment attemptCount
   else
      moveDone = true
   end
end
if not moveDone then handle error

遵循此大纲并使用简单的计数和NSString/NSURL 路径例程将为您提供比您现在发布的答案更简单、更可靠的解决方案。

HTH

【讨论】:

  • 谢谢,你能帮我解决this的问题吗?
【解决方案2】:

这是为我工作的代码。

 NSURL *tempDir = [NSURL fileURLWithPath:destinationPath];
        NSError *error;

        NSURL *tmpDirectory = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:tempDir create:YES error:&error];
        if (error) {
            return ;
        }
        tmpDirectory = [tmpDirectory URLByAppendingPathComponent:@"extracts"];
        NSLog(@"temp dir %@",tmpDirectory);
        NSLog(@"temp path %@",tmpDirectory.path);


        [SSZipArchive unzipFileAtPath:zipFilePath toDestination:tmpDirectory.path];

        NSArray *dirFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpDirectory.path error:nil];
        NSLog(@"dir file %@",dirFiles);
        for (NSString *string in dirFiles) {

            NSArray *dirDestinationFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:destinationPath error:nil];
            NSLog(@"dir destination file %@",dirDestinationFiles);
            NSMutableArray *folderCount = [[NSMutableArray alloc] init];
            NSMutableArray *folderNumCount = [[NSMutableArray alloc] init];

            [dirDestinationFiles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

               if ([obj containsString:string]){
                    [folderNumCount   addObject:obj];
                }
                if ([string isEqualToString:obj]) {


                    [folderCount addObject:string];

                }

            }];


            NSFileManager *fm = [NSFileManager defaultManager];
            NSError *error;

            if (folderCount.count == 0) {
                NSLog(@"First time extract");


                BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path  toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@",string]] error:&error];

                if (isMoved) {
                    NSLog(@"Moved");
                }else{
                    NSLog(@"errorL %@", error);
                    NSLog(@"Not moved");
                }
                [fm removeItemAtPath:tmpDirectory.path error:&error];

                // [self moveFileToTrash:zipFilePath];
                // [self openExtractedFolderWithZipPath:zipFilePath toDestinationPath:destinationPath];

            }else if (folderCount.count > 0){
                NSLog(@"Already present");

                BOOL isMoved = [fm moveItemAtPath:tmpDirectory.path  toPath:[destinationPath stringByAppendingString:[NSString stringWithFormat:@"/%@-%lu",string,folderNumCount.count-1]] error:&error];

                if (isMoved) {
                    NSLog(@"Moved");
                }else{
                    NSLog(@"errorL %@", error);
                    NSLog(@"Not moved");
                }
                [fm removeItemAtPath:tmpDirectory.path error:&error];

                //  [self moveFileToTrash:zipFilePath];
                //  [self openExtractedFolderWithZipPath:zipFilePath toDestinationPath:destinationPath];


            }


        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-15
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多