- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试创建一个具有唯一名称的文件并在后台向其写入数据。
mktemp
说 只要有可能,就应该使用 mkstemp(),因为它没有竞争条件。
使用 mkstemp
会产生一个打开的文件描述符,因此 dispatch_write
似乎很明显。
现在 NSData
必须使用 dispatch_data_create
包装在 dispatch_data_t
中。必须注意释放需要释放的内存,保留必须保留的内存。在 ARC 下,这不太明显。
+ (void) createUnique:(NSData*)content name:(NSString*)name
extension:(NSString*)extension
completion:(void (^)(NSURL* url, NSError* error))completion {
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_data_t data = dispatch_data_create(content.bytes, content.length,
queue, ^{});
// dispatch_data_create() copies the buffer if DISPATCH_DATA_DESTRUCTOR_DEFAULT
// (= NULL) is specified, and attempts to free the buffer if
// DISPATCH_DATA_DESTRUCTOR_FREE is specified, so an empty destructor is
// specified.
dispatch_fd_t descriptor;
// Ignore details of creating the template C string
strcpy(nameCString, templateCString);
descriptor = mkstemps(nameCString, extensionLength);
free(nameCString);
if (descriptor != -1) {
dispatch_write(descriptor, data, queue,
^(dispatch_data_t data, int error) {
NSData* strongContent = content;
// Will this keep the NSData reference until the
// write is finished?
if (error) {
completion(nil, [NSError
errorWithDomain:NSURLErrorDomain
code:error userInfo:nil]);
} else {
// Ignore details of getting path from nameCString.
completion([NSURL URLWithString:path], nil);
}
// How does the file get closed?
});
} else {
completion(nil, [NSError errorWithDomain:NSURLErrorDomain code:errno
userInfo:nil]);
}
}
所以问题是:
mktemp
是否应该与 NSData
的 writeToFile:options:error:
一起使用而不用担心安全/竞争条件?dispatch_data_create
是否可以避免不必要的复制(保留指向 NSData
缓冲区的指针)?mkstemps
打开的描述符可以和dispatch_write
一起使用吗?NSData
的引用是否会使 dispatch_data_t
有效?这是必要的吗? ARC 在这里做什么?dispatch_io_close
?最佳答案
这并不是 dispatch_write
(和一般的 dispatch_data
)的真正用途。正如您所发现的,dispatch_data
关注的是功能和性能,而不是易用性。而你有一个如此简单的问题。
另请注意,您正在讨论的竞争条件与正在您的临时目录中快速创建文件的活跃攻击者有关。攻击是这样的:
/tmp
中创建一个你和 Eve 都可以读写的临时文件。/tmp
并发现某些文件名不存在这是对 Unix 系统的真正攻击。很明显,这不是对 iOS 系统的真正攻击。这并不意味着您不应该使用 mkstemp
。你应该。但重要的是要了解您要防范的是什么。这不是“哎呀;我撞到自己了”竞争条件,除非您每秒制作数百个文件(不要那样做)。
好的,那你是怎么做到的呢? Matt Gallagher 在 Cocoa with Love: Temporary files and folders in Cocoa 中有一个很好的例子.复制到这里以供将来的搜索者使用,但我强烈推荐这篇文章:
NSString *tempFileTemplate =
[NSTemporaryDirectory() stringByAppendingPathComponent:@"myapptempfile.XXXXXX"];
const char *tempFileTemplateCString =
[tempFileTemplate fileSystemRepresentation];
char *tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1);
strcpy(tempFileNameCString, tempFileTemplateCString);
int fileDescriptor = mkstemp(tempFileNameCString);
if (fileDescriptor == -1)
{
// handle file creation failure
}
// This is the file name if you need to access the file by name, otherwise you can remove
// this line.
tempFileName =
[[NSFileManager defaultManager]
stringWithFileSystemRepresentation:tempFileNameCString
length:strlen(tempFileNameCString)];
free(tempFileNameCString);
tempFileHandle =
[[NSFileHandle alloc]
initWithFileDescriptor:fileDescriptor
closeOnDealloc:NO];
现在,在最后,您会看到 Matt 创建了一个文件名和一个 NSFileHandle
。两者都可以使用。您可以使用 NSData
方法写入文件名,也可以使用 NSFileHandle
写入方法。此时不存在使用文件名的竞争条件,因为该文件已经存在并且归您所有。
要在后台编写它,只需将它放在 dispatch_async
block 中即可。
关于ios - 在 ARC 下使用 dispatch_write 将 NSData 写入后台唯一文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30447381/
我只是在玩一些 GCD 函数来向文件写入和读取数据。其中两个函数是 dispatch_write()和 dispatch_read() ,它允许人们在文件描述符中写入和读取数据而无需设置新的 disp
我正在尝试创建一个具有唯一名称的文件并在后台向其写入数据。 mktemp 说 只要有可能,就应该使用 mkstemp(),因为它没有竞争条件。 使用 mkstemp 会产生一个打开的文件描述符,因此
我是一名优秀的程序员,十分优秀!