我將一個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