【问题标题】:NSFileManager unique file namesNSFileManager 唯一的文件名
【发布时间】:2011-12-07 05:40:30
【问题描述】:

我需要一种快速简便的方法来在 iOS 上存储具有唯一文件名的文件。我需要在文件前面加上一个字符串,然后将生成的唯一标识符附加到末尾。我希望NSFileManager 有一些方便的方法来做到这一点,但我似乎找不到它。

我正在查看 createFileAtPath:contents:attributes:,但不确定属性是否会为我提供唯一的文件名。

【问题讨论】:

标签: objective-c ios cocoa-touch uniqueidentifier file-management


【解决方案1】:

Swift 4.15。只需将文件扩展名传递给您,函数将返回唯一的文件名。

func uniqueFileNameWithExtention(fileExtension: String) -> String {
        let uniqueString: String = ProcessInfo.processInfo.globallyUniqueString
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMddhhmmsss"
        let dateString: String = formatter.string(from: Date())
        let uniqueName: String = "\(uniqueString)_\(dateString)"
        if fileExtension.length > 0 {
            let fileName: String = "\(uniqueName).\(fileExtension)"
            return fileName
        }
        
        return uniqueName
    }

【讨论】:

    【解决方案2】:

    Swift 4.2,我使用了两个选项,一个是唯一但可读的,另一个是唯一的。

    // Create a unique filename, added to a starting string or not
    public func uniqueFilename(filename: String = "") -> String {
        let uniqueString = ProcessInfo.processInfo.globallyUniqueString
        return filename + "-" + uniqueString
    }
    
    // Mostly Unique but Readable ID based on date and time that is URL compatible ("unique" to nearest second)
    public func uniqueReadableID(name: String = "") -> String {
    
        let timenow = DateFormatter.localizedString(from: Date(), dateStyle: .medium, timeStyle: .medium)
        let firstName = name + "-" + timenow
        do {
            // Make ID compatible with URL usage
            let regex = try NSRegularExpression(pattern: "[^a-zA-Z0-9_]+", options: [])
            let newName = regex.stringByReplacingMatches(in: firstName, options: [], range: NSMakeRange(0, firstName.count), withTemplate: "-")
            return newName
        }
        catch {
            print("? Unique ID Error: \(error.localizedDescription)")
            return uniqueFilename(filename: name)
        }
    }
    

    【讨论】:

      【解决方案3】:

      超级简单的Swift 4 1-liner:

      fileName = "MyFileName_" + UUID().uuidString
      

      fileName = "MyFileName_" + ProcessInfo().globallyUniqueString
      

      【讨论】:

        【解决方案4】:

        这是我最终在 Swift 3.0 中使用的内容

        public func generateUniqueFilename (myFileName: String) -> String {
        
            let guid = ProcessInfo.processInfo.globallyUniqueString
            let uniqueFileName = ("\(myFileName)_\(guid)")
        
            print("uniqueFileName: \(uniqueFileName)")
        
            return uniqueFileName
        }
        

        【讨论】:

        • 对于 Swift 3:让 guid = ProcessInfo.processInfo.globallyUniqueString
        • 谢谢!更新了我的答案。
        【解决方案5】:

        在 iOS 6 中最简单的方法是使用:

        NSString *uuidString = [[NSUUID UUID] UUIDString];
        

        【讨论】:

          【解决方案6】:

          创建您自己的文件名:

          CFUUIDRef uuid = CFUUIDCreate(NULL);
          CFStringRef uuidString = CFUUIDCreateString(NULL, uuid);
          CFRelease(uuid);
          NSString *uniqueFileName = [NSString stringWithFormat:@"%@%@", prefixString, (NSString *)uuidString];
          CFRelease(uuidString);
          

          @darrinm 在 cmets 中提出的更简单的替代方案:

          NSString *prefixString = @"MyFilename";
          
          NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString] ;
          NSString *uniqueFileName = [NSString stringWithFormat:@"%@_%@", prefixString, guid];
          
          NSLog(@"uniqueFileName: '%@'", uniqueFileName);
          

          NSLog 输出:
          uniqueFileName: 'MyFilename_680E77F2-20B8-444E-875B-11453B06606E-688-00000145B460AF51'

          注意:iOS6 引入了 NSUUID 类,可以用来代替 CFUUID。

          NSString *guid = [[NSUUID new] UUIDString];
          

          【讨论】:

          • 获取 GUID 字符串的好方法是:NSString *guid = [[NSProcessInfo processInfo] globalUniqueString]
          • 很好,但是发生冲突的概率是多少?
          • @user578205 来自文档:UUID 在空间和时间上都是唯一的,方法是结合生成它的计算机的唯一值和表示 100 纳秒间隔数的值。它们被称为“独特”是有原因的。
          • 而如果在循环中会产生UUID,那么生成UUID的函数srand()会帮助解决问题吗?
          • 唯一的潜在问题是,如果您生成 UUID 的速度快于每 100 纳秒,这在当今的处理器上可能是不可能的。 srand() 及其家族也不太擅长随机数,arc4random() 是随机数的方法。
          【解决方案7】:

          我使用当前日期生成具有给定扩展名的随机文件名。这是我的 NSFileManager 类别中的方法之一:

          + (NSString*)generateFileNameWithExtension:(NSString *)extensionString { // 扩展字符串就像@".png" NSDate *time = [NSDate 日期]; NSDateFormatter* df = [NSDateFormatter 新]; [df setDateFormat:@"dd-MM-yyyy-hh-mm-ss"]; NSString *timeString = [df stringFromDate:time]; NSString *fileName = [NSString stringWithFormat:@"File-%@%@", timeString, extensionString]; 返回文件名; }

          【讨论】:

          • 警告:在夏令时 -1 期间使用日期可能会导致冲突。 (在秋季重复相同的时间。)
          • 为了防止夏令时更改时发生冲突,我们可以将“Z”说明符附加到日期格式字符串(它表示当前时区偏移量)。也许这会对某人有所帮助。
          • 除非您希望日期成为文件名的一部分,否则应该避免这种情况,因为 Bob 提到的冲突,初始化 Date 对象是昂贵的,Apple 已经提供了替代方法创建唯一标识符
          【解决方案8】:

          您也可以使用可敬的mktemp()(参见man 3 mktemp)。像这样:

          - (NSString*)createTempFileNameInDirectory:(NSString*)dir
          {
            NSString* templateStr = [NSString stringWithFormat:@"%@/filename-XXXXX", dir];
            char template[templateStr.length + 1];
            strcpy(template, [templateStr cStringUsingEncoding:NSASCIIStringEncoding]);
            char* filename = mktemp(template);
          
            if (filename == NULL) {
              NSLog(@"Could not create file in directory %@", dir);
              return nil;
            }
            return [NSString stringWithCString:filename encoding:NSASCIIStringEncoding];
          }
          

          XXXXX 将替换为唯一的字母/数字组合。它们只能出现在模板的末尾,因此您不能在模板中附加扩展名(尽管您可以在获得唯一文件名后附加它)。在模板中添加任意数量的X

          文件没有创建,需要自己创建。如果您有多个线程在同一目录中创建唯一文件,则可能会出现竞争条件。如果是这种情况,请使用 mkstemp() 创建文件并返回文件描述符。

          【讨论】:

          • 你实际上可以有一个扩展..path = @".../XXXXXX.pdf"然后做mkstemps(path, suffixLength)suffixLength = 4 在这种情况下。
          【解决方案9】:

          这应该对你有用:

          http://vgable.com/blog/2008/02/24/creating-a-uuid-guid-in-cocoa/

          帖子的作者建议将“stringWithUUID”方法实现为 NSString 的一个类别。只需将使用此方法生成的 GUID 附加到您正在创建的文件名的末尾即可。

          【讨论】:

            猜你喜欢
            • 2011-05-07
            • 1970-01-01
            • 1970-01-01
            • 2011-03-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-27
            • 2020-04-11
            相关资源
            最近更新 更多