2011-03-21 77 views
3

我将一个C++ lib移植到iOS,并遇到代码调用tmpnam的问题。该函数返回“var/tmp/tmp.0.0xGlzv”,我认为它在允许我的应用程序播放的“沙箱”之外。后续fopen返回“操作不允许”。有没有可行的替代品?我可以使用tempnam和IOS吗?

回答

3

什么

[NSTemporaryDirectory() stringByAppendingPathComponent:@"myTempFile1.tmp"]; 

名唯一,尝试这样的事情:

NSString *uniqueTempFile() 
{ 
    int i = 1; 
    while (YES) 
    { 
     NSString *currentPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%i.tmp", i]]; 
     if (![[NSFileManager defaultManager] fileExistsAtPath:currentPath]) 
      return currentPath; 
     else 
     { 
      i++; 
     } 
    } 
} 

这很简单,但可能不是最内存efficent答案。

+0

这让我进入了沙箱的可接受区域。现在生成一个唯一的文件名。 – tillerstarr 2011-03-21 16:17:15

+0

@tillerstarr检查我的更新 – 2011-03-21 16:23:15

1

我不知道任何可以用于iostreams的替换,但回想一下,使用函数返回一个后来打开的名称会使您遇到竞争状况,在这种情况下,另一个进程将同时打开文件并确定它不存在。

更安全的是使用类似tmpfile(man tmpfile)的东西,不幸的是它返回的是C风格FILE*,而不是允许您使用iostream。然而,编写一个使用stringstream进行封装的类,然后将该文件的内容作为文本写入FILE*将是微不足道的。

1

我相信这是你真正想要的东西(文件没有扩展使追加一个,如果你想):

char *td = strdup([[NSTemporaryDirectory() stringByAppendingPathComponent:@"XXXXXX"] fileSystemRepresentation]); 
int fd = mkstemp(td); 
if(fd == -1) { 
    NSLog(@"OPEN failed file %s %s", td, strerror(errno)); 
} 
free(td); 
+1

这里有一个提示 - 千万不要在C'template中命名变量。它会导致太多的错误,如果您需要在后续的C++中进行交互操作。 – 2013-02-14 18:02:47

+0

@ RichardJ.RossIII啊,我明白你的意思了 - 对不起 - 这只是示例代码。我会解决它。 – 2013-02-14 23:38:35

1

下面是我使用的是什么。而且,这样设置,您可以在不使用函数调用的情况下复制/粘贴内联。

- (NSString *)tempFilePath 
{ 
    NSString *tempFilePath; 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    for (;;) { 
     NSString *baseName = [NSString stringWithFormat:@"tmp-%x.caf", arc4random()]; 
     tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:baseName]; 
     if (![fileManager fileExistsAtPath:tempFilePath]) 
      break; 
    } 
    return tempFilePath; 
} 
+1

你的函数应该'return tempFilePath;':) – 2013-11-21 17:46:33