从临时目录移走时无法重命名文件 [英] Unable to rename the file while moving from temporary directorary

查看:229
本文介绍了从临时目录移走时无法重命名文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  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];

                }

            }];


        }

任何建议.. 在此先感谢!

解决方案

让我们回顾一下您的代码以希望对您有所帮助.

它似乎很小,但是要选择好的变量名:

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提供的例程抽象了路径分隔符的详细信息以及如何找到最后一个路径组件的扩展名(在重命名以避免冲突时可能会发现这很有用)./p>

回到:

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

I am developing a zip extractor app i followed the algorithm that CRD explained @Here but i stuck at third step i am unable to rename the unzipped file which is at temporary directorary. here is my code

  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];

                }

            }];


        }

Any Suggestions.. Thanks in Advance !

解决方案

Let's just review your code to hopefully help you on your way.

It may seem minor, but pick good variable names:

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

Two names which are semantically similar for different things, that is just confusing. How about, say, destinationURL instead of tempDir?

Next, when constructing/pulling apart/etc. pathnames or URLs you will be better off being consistent. Both NSURL and NSString provide similar methods for these operations, in one place you use them:

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

but then restort to direct string manipulation using a path separator which may, or may not, be correct:

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

The routines provided by NSURL and NSString abstract away from the details of path separators and how to, say, find the extension on the last path component (which you might find useful when renaming to avoid clashes).

Going back to:

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

There is no reason for you to do this. The temporary directory is created for you and you should delete it after using it. So there is no need to create a subdirectory extracts within it, and by reassigning to the same variable you've lost the URL you need to delete the temporary directory.

Now something less obvious, in my comment above I wrote:

To move each item you must handle name clashes, to do this try the move and if you get an error indicating a name clash modify the destination name however you like and re-try the move, repeating until you succeed or you until reach some limit of tries (determined by you).

I didn't explain why you should do it this way and you have tackled the problem a different way: for each item you are going to move you check for names clashes before attempting the move by iterating over the names in the destination directory.

If you read Apple's documentation on the file system you will find they often recommend you try an operation and then examine any error returned instead of trying to predict whether an error will occur and avoid it. The reason for this is the file system is dynamic, other processes can be modifying it, so if you try to avoid an error you may still get one. In pseudocode you are better of doing something like:

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

Following this outline and using a simple count and the NSString/NSURL path routines will produce you a much simpler and more reliable solution than the one you have now posted as an answer.

HTH

这篇关于从临时目录移走时无法重命名文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆