我将一个C++ lib移植到iOS,并遇到代码调用tmpnam的问题。该函数返回“var/tmp/tmp.0.0xGlzv”,我认为它在允许我的应用程序播放的“沙箱”之外。后续fopen返回“操作不允许”。有没有可行的替代品?我可以使用tempnam和IOS吗?
回答
什么
[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答案。
我不知道任何可以用于iostreams的替换,但回想一下,使用函数返回一个后来打开的名称会使您遇到竞争状况,在这种情况下,另一个进程将同时打开文件并确定它不存在。
更安全的是使用类似tmpfile
(man tmpfile)的东西,不幸的是它返回的是C风格FILE*
,而不是允许您使用iostream。然而,编写一个使用stringstream进行封装的类,然后将该文件的内容作为文本写入FILE*
将是微不足道的。
我相信这是你真正想要的东西(文件没有扩展使追加一个,如果你想):
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);
这里有一个提示 - 千万不要在C'template中命名变量。它会导致太多的错误,如果您需要在后续的C++中进行交互操作。 – 2013-02-14 18:02:47
@ RichardJ.RossIII啊,我明白你的意思了 - 对不起 - 这只是示例代码。我会解决它。 – 2013-02-14 23:38:35
下面是我使用的是什么。而且,这样设置,您可以在不使用函数调用的情况下复制/粘贴内联。
- (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;
}
你的函数应该'return tempFilePath;':) – 2013-11-21 17:46:33
这让我进入了沙箱的可接受区域。现在生成一个唯一的文件名。 – tillerstarr 2011-03-21 16:17:15
@tillerstarr检查我的更新 – 2011-03-21 16:23:15