Unable to rename the file while moving from temporary directorary

一个人想着一个人 提交于 2019-12-13 08:26:17

问题


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 !


回答1:


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




回答2:


Here is the code working for me.

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


            }


        }


来源:https://stackoverflow.com/questions/51614004/unable-to-rename-the-file-while-moving-from-temporary-directorary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!