iOS文件路径上的/ private前缀表示什么?

时间:2013-02-21 00:57:52

标签: iphone ios filepath

当我的应用程序在iPhone上运行时,我有一个错误,但是当它在模拟器上运行时却没有。我使用主目录路径的长度来提取/ Documents中文件的相对路径。不幸的是,这并不总能在iPhone上正常工作,因为前缀“/ private”正被添加到主路径中。但是,无论有没有前缀,都可以引用相同的文件。以下代码演示了这种不一致性。 “/ private”的目的是什么?iOS何时提供?

- (IBAction)testHomepath:(id)sender {
    NSFileManager *fmgr = [NSFileManager defaultManager];
    NSString  *homePath = [NSString stringWithFormat:@"%@/Documents",NSHomeDirectory()];
    NSString  *dirPath  = [homePath stringByAppendingPathComponent:@"TempDir"];
    NSURL     *dirURL   = [NSURL fileURLWithPath:dirPath];
    NSString  *filePath = [dirPath  stringByAppendingPathComponent:@"test.jpg"];
    [fmgr createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:nil error:nil];
    [fmgr createFileAtPath:filePath contents:nil attributes:nil];
    NSArray *keys  = [[NSArray alloc] initWithObjects:NSURLNameKey,nil];
    NSArray *files = [fmgr contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:keys options:0 error:nil];
    NSURL *f1 = (files.count>0)? [files objectAtIndex:0] : 0;
    NSURL *f2 = (files.count>1)? [files objectAtIndex:1] : 0;
    bool   b0 = [fmgr fileExistsAtPath:filePath];
    bool   b1 = [fmgr fileExistsAtPath:f1.path];
    bool   b2 = [fmgr fileExistsAtPath:f2.path];

    NSLog(@"File exists=%d at path:%@",b0,filePath);
    NSLog(@"File exists=%d at path:%@",b1,f1.path);
    NSLog(@"File exists=%d at path:%@",b2,f2.path);
}

在iPhone上运行时,以下内容写入日志。我手动间隔输出以显示第1行和第2行之间的差异。

2013-02-20 16:31:26.615 Test1[4059:907] File exists=1 at path:        /var/mobile/Applications/558B5D82-ACEB-457D-8A70-E6E00DB3A484/Documents/TempDir/test.jpg
2013-02-20 16:31:26.622 Test1[4059:907] File exists=1 at path:/private/var/mobile/Applications/558B5D82-ACEB-457D-8A70-E6E00DB3A484/Documents/TempDir/test.jpg
2013-02-20 16:31:26.628 Test1[4059:907] File exists=0 at path:(null)

在模拟器上运行时,以下内容写入日志(无“/ private”):

2013-02-20 16:50:38.730 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/test.jpg
2013-02-20 16:50:38.732 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/.DS_Store
2013-02-20 16:50:38.733 Test1[7224:c07] File exists=1 at path:/Users/kenm/Library/Application Support/iPhone Simulator/6.1/Applications/C6FDE177-958C-4BF5-8770-A4D3FBD281F1/Documents/TempDir/test.jpg

6 个答案:

答案 0 :(得分:29)

我在调试器中尝试了这一点,发现URLByResolvingSymlinksInPath“修复了/private/添加内容。

(lldb) p (NSURL *)[NSURL fileURLWithPath:@"/private/var" isDirectory:YES]
(NSURL *) $1 = 0x1fd9fc20 @"file://localhost/private/var/"
(lldb) po [$1 URLByResolvingSymlinksInPath]
$2 = 0x1fda0190 file://localhost/var/

(lldb) p (NSURL *)[NSURL fileURLWithPath:@"/var" isDirectory:YES]
(NSURL *) $7 = 0x1fd9fee0 @"file://localhost/var/"
(lldb) po [$7 URLByResolvingSymlinksInPath]
$8 = 0x1fda2f50 file://localhost/var/

如您所见,file://localhost/var是我们真正想要的。

因此,/private/var似乎是/var的符号链接。 然而,@ Kevin-Ballard指出这不是真的。我确认他是正确的,/var/private/var(叹气)的符号链接

(lldb) p (NSDictionary *)[[NSFileManager defaultManager] attributesOfItemAtPath:@"/var" error:nil]
(NSDictionary *) $3 = 0x1fda11b0 13 key/value pairs
(lldb) po $3
$3 = 0x1fda11b0 {
    ...
    NSFileType = NSFileTypeSymbolicLink;
}

(lldb) p (NSDictionary *)[[NSFileManager defaultManager]   attributesOfItemAtPath:@"/private/var" error:nil]
(NSDictionary *) $5 = 0x1fda4820 14 key/value pairs
(lldb) po $5
$5 = 0x1fda4820 {
    ...
    NSFileType = NSFileTypeDirectory;
}

所以URLByResolvingSymlinksInPath在这里做了一些有趣的事情,但现在我们知道了。对于这个特殊问题,URLByResolvingSymlinksInPath仍然听起来像是一个适用于模拟器和设备的好解决方案,并且如果发生变化,将来还能继续工作。

答案 1 :(得分:5)

Swift 3中,URL具有standardizedFileUrl属性,该属性将移除所有符号链接并解析路径中的相对部分,如./

截至撰写时documentation非常无用,但看起来它与NSURL's standardized属性相当。

答案 2 :(得分:4)

要真正回答你的问题:

我相信/private是在发布OS X时添加的前缀(我不认为它在NeXTStep中存在,但它已经几十年)。似乎存在容纳etcvartmp(奇怪的是,tftpboot;我不知道我的PBG4可以做到这一点),也许是这样的用户不要奇怪这个名为etc的愚蠢文件夹是什么,并尝试删除它。

在设备上,Apple决定将用户数据存储在/private/var/mobile(用户名为“mobile”)。我不确定他们为什么不选择/Users/mobile或仅/mobile,但它在“正常”的Unix上没有比/var/mobile更重要的意义。

在模拟器上,您的用户帐户无法写入/var(有充分理由)。用户数据存储在~/Library/Application Support/iPhone Simulator的某个位置。有一次,他们开始为不同的模拟器版本使用不同的目录。

答案 3 :(得分:3)

/var只是/private/var的符号链接。因此,第一个路径是您尝试访问的逻辑路径。第二个是扩展符号链接的相同路径。

答案 4 :(得分:0)

  1. 在我的情况下,使用FileManager.default.fileExists来检查文件是否已经存在,但是我正在使用.absoluteString / “()” 。代替.path以将URL作为字符串传递。
  2. 当我使用
  3. 在Documents Directory中打印文件的路径时
  

让fileURLs =试试fileManager.contentsOfDirectory(at:

它打印为/private/var

  

让DocumentDirURL =尝试! FileManager.default.url(用于:.documentDirectory,位于:.userDomainMask,适当于:无,创建:true)

它打印为/var

  1. 路途上的差异让我感到困惑。
  2. 如上文所述,其符号链接。即两条路径都相同。

:)

答案 5 :(得分:0)

一项功能(快速5),用于从缓存中删除文件。我遇到了很多问题,使用URL解决了/ private问题。

class func removeFileFromCache( filePattern: String ) -> Bool {
    // find filename with pattern
     
    do {
        let cachePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
        let filePathUrl = URL( fileURLWithPath: filePattern )
        let originalFilename = filePathUrl.lastPathComponent
        let newFilePath = cachePath.appendingPathComponent( originalFilename ).path
       
        try FileManager.default.removeItem(atPath: newFilePath )
        print("file \( filePattern ) succesfull removed.",classname:URL(fileURLWithPath: #file).lastPathComponent )
        
    } catch let error as NSError {
        print("Error \(error)",classname:URL(fileURLWithPath: #file).lastPathComponent )
        return false // all is not well
    }
    
    return true
}