NSFileManager唯一文件名

45
我需要一种快速且简便的方法在iOS上存储文件,并使用唯一的文件名。我需要在文件名前面加上一个字符串,然后在末尾附加生成的唯一标识符。我希望NSFileManager有一些方便的方法来实现这一点,但我似乎找不到。我正在查看createFileAtPath:contents:attributes:,但我不确定属性是否会给我唯一的文件名。

1
这个SO可能是你需要的。 - user523234
9个回答

79

创建自己的文件名:

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

在评论中,@darrinm提出了一个更简单的替代方法:

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

13
获取GUID字符串的简单快捷方式是:NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString]。 - darrinm
2
很好,但是碰撞的概率是多少? - Arsynth
从文档中可以看出,UUID是通过将在生成它的计算机上唯一的值与表示100纳秒间隔数量的值相结合来保证其在空间和时间上的唯一性。有一个原因,它们被称为“唯一”。 - zaph
如果UUID将在循环中生成,使用函数srand()来生成UUID会有助于解决问题吗? - Arsynth
2
唯一可能的问题是,如果您生成UUID的速度快于每100纳秒一次,这在今天的处理器上可能不可能。此外,srand()及其相关函数并不擅长生成随机数,arc4random()是生成随机数的正确方式。 - zaph

10

超级简单的 Swift 4 一行代码:

fileName = "MyFileName_" + UUID().uuidString
或者
fileName = "MyFileName_" + ProcessInfo().globallyUniqueString

9
我使用当前日期来生成带有指定扩展名的随机文件名。这是我在NSFileManager类别中的一个方法:
+ (NSString*)generateFileNameWithExtension:(NSString *)extensionString { // 扩展名字符串格式为@".png"
NSDate *time = [NSDate date]; NSDateFormatter* df = [NSDateFormatter new]; [df setDateFormat:@"dd-MM-yyyy-hh-mm-ss"]; NSString *timeString = [df stringFromDate:time]; NSString *fileName = [NSString stringWithFormat:@"File-%@%@", timeString, extensionString];
return fileName; }

3
警告:使用日期可能会在夏令时-1期间发生冲突(即当同一小时重复时,通常出现在秋季)。 - bob
1
为了防止在夏令时变化时发生冲突,我们可以在日期格式字符串后附加“Z”说明符(它表示当前时区偏移量)。也许这会帮助到某些人。 - Stan Mots
除非您希望日期成为文件名的一部分,否则应避免这样做,因为Bob提到初始化“Date”对象是昂贵的,并且苹果已经提供了创建唯一标识符的替代方法。 - mfaani

7
您可以使用古老的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()来创建文件并返回文件描述符。

2
你实际上可以有一个扩展名为 path = @".../XXXXXX.pdf" 的文件,然后执行 mkstemps(path, suffixLength)。在这种情况下,suffixLength 为4。 - Marc

5

这是我在Swift 3.0中最终使用的代码:

public func generateUniqueFilename (myFileName: String) -> String {

    let guid = ProcessInfo.processInfo.globallyUniqueString
    let uniqueFileName = ("\(myFileName)_\(guid)")

    print("uniqueFileName: \(uniqueFileName)")

    return uniqueFileName
}

1
对于Swift 3:let guid = ProcessInfo.processInfo.globallyUniqueString - user3717478
谢谢!我更新了我的回答。 - Dave Levy

5
在iOS 6中,最简单的方法是使用以下代码:
NSString *uuidString = [[NSUUID UUID] UUIDString];

3

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

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)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接