【问题标题】:iOS - How to selectively delete files older than a month in Documents DirectoryiOS - 如何选择性地删除文档目录中超过一个月的文件
【发布时间】:2012-04-25 02:27:24
【问题描述】:

我正在将图像下载到我的应用程序中,几周后用户将不再关心这些图像。我将它们下载到应用程序中,因此不必每次启动都下载它们。问题是我不希望 Documents 文件夹随着时间的推移变得比它更大。所以我想我可以“清理”一个月以上的文件。

问题是,那里会有一些文件会超过一个月,但我不想删除。它们将是静态命名文件,因此它们很容易识别,并且只有 3 或 4 个。虽然我可能要删除几十个旧文件。举个例子:

picture.jpg           <--Older than a month DELETE
picture2.jpg          <--NOT older than a month Do Not Delete
picture3.jpg          <--Older than a month DELETE
picture4.jpg          <--Older than a month DELETE
keepAtAllTimes.jpg    <--Do not delete no matter how old
keepAtAllTimes2.jpg   <--Do not delete no matter how old
keepAtAllTimes3.jpg   <--Do not delete no matter how old

我怎样才能有选择地删除这些文件?

提前致谢!

【问题讨论】:

  • 扫描目录,提取文件日期,并删除超过一个月的日期。有一个文件列表,以便与您不想删除的文件进行比较。
  • 是的。三天前也有人问过同样的问题。

标签: iphone objective-c ios iphone-4


【解决方案1】:

我的两分钱值。更改符合要求以适应。

func cleanUp() {
    let maximumDays = 10.0
    let minimumDate = Date().addingTimeInterval(-maximumDays*24*60*60)
    func meetsRequirement(date: Date) -> Bool { return date < minimumDate }

    func meetsRequirement(name: String) -> Bool { return name.hasPrefix(applicationName) && name.hasSuffix("log") }

    do {
        let manager = FileManager.default
        let documentDirUrl = try manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        if manager.changeCurrentDirectoryPath(documentDirUrl.path) {
            for file in try manager.contentsOfDirectory(atPath: ".") {
                let creationDate = try manager.attributesOfItem(atPath: file)[FileAttributeKey.creationDate] as! Date
                if meetsRequirement(name: file) && meetsRequirement(date: creationDate) {
                    try manager.removeItem(atPath: file)
                }
            }
        }
    }
    catch {
        print("Cannot cleanup the old files: \(error)")
    }
}

【讨论】:

    【解决方案2】:

    在 Swift 3 和 4 中,删除 DocumentsDirectory 中的特定文件

    do{
        try FileManager.default.removeItem(atPath: theFile)
    } catch let theError as Error{
        print("file not found \(theError)")
    }
    

    【讨论】:

      【解决方案3】:

      这是一个不使用字符串比较日期并在枚举器中预取修改时间的函数:

      + (NSArray<NSURL *> *)deleteFilesOlderThan:(NSDate *)earliestDateAllowed
                                     inDirectory:(NSURL *)directory {
          NSFileManager *fileManager = [NSFileManager defaultManager];
          NSDirectoryEnumerator<NSURL *> *enumerator =
              [fileManager enumeratorAtURL:directory
                  includingPropertiesForKeys:@[ NSURLContentModificationDateKey ]
                                     options:0
                                errorHandler:^BOOL(NSURL *_Nonnull url, NSError *_Nonnull error) {
                                    NSLog(@"Failed while enumerating directory '%@' for files to "
                                               @"delete: %@ (failed on file '%@')",
                                               directory.path, error.localizedDescription, url.path);
                                    return YES;
                                }];
      
          NSURL *file;
          NSError *error;
          NSMutableArray<NSURL *> *filesDeleted = [NSMutableArray new];
          while (file = [enumerator nextObject]) {
              NSDate *mtime;
              if (![file getResourceValue:&mtime forKey:NSURLContentModificationDateKey error:&error]) {
                  NSLog(@"Couldn't fetch mtime for file '%@': %@", file.path, error);
                  continue;
              }
      
              if ([earliestDateAllowed earlierDate:mtime] == earliestDateAllowed) {
                  continue;
              }
      
              if (![fileManager removeItemAtURL:file error:&error]) {
                  NSLog(@"Couldn't delete file '%@': %@", file.path, error.localizedDescription);
                  continue;
              }
              [filesDeleted addObject:file];
          }
          return filesDeleted;
      }
      

      如果您不关心被删除的文件,您可以让它返回 BOOL 以指示是否有任何错误,或者如果您只想尽最大努力尝试,则只需返回 void

      要有选择地保留一些文件,可以向函数添加一个正则表达式参数以匹配要保留的文件,并在 while 循环中添加一个检查(似乎最适合您的用例),或者如果有具有不同模式的离散数量的文件,您可以接受 NSSet 以及要保留的文件名,并在继续删除之前检查是否包含在集合中。

      这里也只是提到这一点,因为它可能与某些人相关:iOS 和 OSX 上的文件系统不会以超过一秒的精度存储 mtime,因此如果您需要毫秒精度或类似精度,请注意这一点。

      如果需要,可以将相应的测试用例放入您的测试套件中:

      @interface MCLDirectoryUtilsTest : XCTestCase
      
      @property NSURL *directory;
      
      @end
      
      
      @implementation MCLDirectoryUtilsTest
      
      - (void)setUp {
          NSURL *tempdir = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
          self.directory = [tempdir URLByAppendingPathComponent:[NSUUID UUID].UUIDString isDirectory:YES];
          NSFileManager *fileManager = [NSFileManager defaultManager];
          [fileManager createDirectoryAtURL:self.directory
                withIntermediateDirectories:YES
                                 attributes:nil
                                      error:nil];
      }
      
      
      - (void)tearDown {
          NSFileManager *fileManager = [NSFileManager defaultManager];
          [fileManager removeItemAtURL:self.directory error:nil];
      }
      
      
      - (void)testDeleteFilesOlderThan {
          NSFileManager *fileManager = [NSFileManager defaultManager];
          // Create one old and one new file
          [fileManager createFileAtPath:[self.directory URLByAppendingPathComponent:@"oldfile"].path
                               contents:[NSData new]
                             attributes:@{
                                 NSFileModificationDate : [[NSDate new] dateByAddingTimeInterval:-120],
                             }];
          [fileManager createFileAtPath:[self.directory URLByAppendingPathComponent:@"newfile"].path
                               contents:[NSData new]
                             attributes:nil];
      
          NSArray<NSURL *> *filesDeleted =
              [MCLUtils deleteFilesOlderThan:[[NSDate new] dateByAddingTimeInterval:-60]
                                 inDirectory:self.directory];
          XCTAssertEqual(filesDeleted.count, 1);
          XCTAssertEqualObjects(filesDeleted[0].lastPathComponent, @"oldfile");
          NSArray<NSString *> *contentsInDirectory =
              [fileManager contentsOfDirectoryAtPath:self.directory.path error:nil];
          XCTAssertEqual(contentsInDirectory.count, 1);
          XCTAssertEqualObjects(contentsInDirectory[0], @"newfile");
      }
      

      【讨论】:

        【解决方案4】:

        删除超过两天的文件的代码。最初我回答了here。我测试了它,它在我的项目中工作。

        附注在删除 Document 目录中的所有文件之前要小心,因为这样做可能最终会丢失数据库文件(如果您正在使用..!!),这可能会给您的应用程序带来麻烦。这就是为什么我在那里保持条件。 :-))

        // Code to delete images older than two days.
           #define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
        
        NSFileManager* fileManager = [[[NSFileManager alloc] init] autorelease];
        NSDirectoryEnumerator* en = [fileManager enumeratorAtPath:kDOCSFOLDER];    
        
        NSString* file;
        while (file = [en nextObject])
        {
            NSLog(@"File To Delete : %@",file);
            NSError *error= nil;
        
            NSString *filepath=[NSString stringWithFormat:[kDOCSFOLDER stringByAppendingString:@"/%@"],file];
        
        
            NSDate   *creationDate =[[fileManager attributesOfItemAtPath:filepath error:nil] fileCreationDate];
            NSDate *d =[[NSDate date] dateByAddingTimeInterval:-1*24*60*60];
        
            NSDateFormatter *df=[[NSDateFormatter alloc]init];// = [NSDateFormatter initWithDateFormat:@"yyyy-MM-dd"];
            [df setDateFormat:@"EEEE d"]; 
        
            NSString *createdDate = [df stringFromDate:creationDate];
        
             NSString *twoDaysOld = [df stringFromDate:d];
        
            NSLog(@"create Date----->%@, two days before date ----> %@", createdDate, twoDaysOld);
        
            // if ([[dictAtt valueForKey:NSFileCreationDate] compare:d] == NSOrderedAscending)
            if ([creationDate compare:d] == NSOrderedAscending)
        
            {
                if([file isEqualToString:@"RDRProject.sqlite"])
                {
        
                    NSLog(@"Imp Do not delete");
                }
        
                else
                {
                     [[NSFileManager defaultManager] removeItemAtPath:[kDOCSFOLDER stringByAppendingPathComponent:file] error:&error];
                }
            }
        }
        

        【讨论】:

        • 我最初尝试过这个,但没有成功。我又试了一次,现在可以了。谢谢!
        • 啊哈..酷..实际上我为这个问题试了几分钟,并在我正在运行的应用程序中验证了它,然后我发布了代码。你会在我的代码中看到用于日期验证的额外代码。 . :-))
        • @ParthBhatt :但我本人在那里回答。我没有复制任何东西。
        • @ParthBhatt:如果他们伤害了你,我很抱歉。我会删除评论。
        • 谢谢。一点注意 NSString 有一个非常有用且安全的方法,名为 stringByAppendingPathComponent
        【解决方案5】:

        要查找文件的创建日期,您可以参考一篇非常有用的 StackOverflow 帖子:

        iOS: How do you find the creation date of a file?

        参考这篇文章,这可能有助于您删除它们。您可以大致了解从 Documents Directory 中删除这些数据需要做什么:

        How to delete files from iPhone's document directory which are older more than two days

        希望对你有所帮助。

        【讨论】:

          【解决方案6】:

          您可以获取文件创建日期,查看此SO Post,然后仅比较日期。并为需要删除的文件和不删除的文件创建两个不同的数组..

          【讨论】:

          • +1 表示正确答案。但是,我建议使用NSMetadataQuery,而不是使用链接问题中的解决方案,它会自动搜索早于某个日期的文件。
          猜你喜欢
          • 1970-01-01
          • 2011-01-14
          • 1970-01-01
          • 1970-01-01
          • 2015-05-21
          • 2018-01-31
          • 2016-04-29
          • 2020-01-29
          • 1970-01-01
          相关资源
          最近更新 更多