【iOS】线程安全的文件读写
前段时间看了一遍GCD(Grand Central Dispatch)多线程,GCD是苹果为多核开发提供的解决方案
多线程最常见的问题就是读写,比如数据库读写,文件读写,读取是共享的,写是互斥,允许多个线程进行读操作,当写文件时,阻止队列中所有其他的线程进入,直到文件写完成
本文利用GCD提供的相关API封装(主要有dispatch_barrier_async,dispatch_async,dispatch_queue_create)一个线程安全的文件读写类FileManager
注:这里使用的文件读写使用NSFileManager类,在测试过程发现多个线程同时写文件的时候并没有发现异常和报错,经过一番查阅发现,原来NSFileManager本身就是线程安全的,多个线程对文件进行写操作,并不会报异常
下面代码只作为加深GCD的学习,实际开发如果使用NSFileManager并不需要考虑线程安全问题(使用NSFileManager的delegate的时候需要注意,需要自己定义一个实例维护状态,避免与共享实例冲突)
SGFileManager.h
@interface SGFileManager : NSObject + (instancetype)shareInstance; - (NSData *)readFile:(NSString *)path;
- (void)readFileAsync:(NSString *)path complete:(void (^)(NSData *data))complete; - (BOOL)writeFile:(NSString *)path data:(NSData *)data;
- (void)writeFileAsync:(NSString *)path data:(NSData *)data complete:(void (^)(BOOL result))complete; @end
SGFileManager.m
#import "SGFileManager.h" //线程队列名称
static char *queueName = "fileManagerQueue"; @interface SGFileManager ()
{
//读写队列
dispatch_queue_t _queue;
} @end @implementation SGFileManager + (instancetype)shareInstance
{
static id instance = nil; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
}); return instance;
} - (instancetype)init
{
if(self = [super init]) {
_queue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT);
}
return self;
} - (NSData *)readFile:(NSString *)path
{
__block NSData *data;
dispatch_sync(_queue, ^{
if([[NSFileManager defaultManager] fileExistsAtPath:path]){
data = [[NSFileManager defaultManager] contentsAtPath:path];
}
});
return data;
} - (void)readFileAsync:(NSString *)path complete:(void (^)(NSData *data))complete
{
dispatch_async(_queue, ^{
NSData *data = nil; if([[NSFileManager defaultManager] fileExistsAtPath:path]){
data = [[NSFileManager defaultManager] contentsAtPath:path];
} if (complete) {
complete(data);
}
});
} - (BOOL)writeFile:(NSString *)path data:(NSData *)data
{
__block BOOL result = NO;
dispatch_barrier_sync(_queue, ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:path]){
[fileManager removeItemAtPath:path error:nil];
} result = [[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil]; NSLog(@"写文件:");
});
return result;
} - (void)writeFileAsync:(NSString *)path data:(NSData *)data complete:(void (^)(BOOL result))complete
{
__block BOOL result = NO;
dispatch_barrier_async(_queue, ^{
NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:path]){
[fileManager removeItemAtPath:path error:nil];
} result = [[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil]; if (complete) {
complete(result);
}
}); } @end
使用:
NSString *documentRoot = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentRoot stringByAppendingPathComponent:@"test.txt"]; [[SGFileManager shareInstance] writeFileAsync:filePath data:data complete:^(BOOL result) {
if (result) {
NSLog(@"异步写入文件成功");
}
}]; [[SGFileManager shareInstance] readFileAsync:filePath complete:^(NSData *data) {
if (data) {
NSLog(@"异步读取文件成功");
}
}];
使用GCD进行多线程开发还是挺方便的,不需要考虑锁的问题,并且性能也比较高,在开发中可以尽量使用GCD进行多线程的开发,并且GCD对从后台到UI的调用也非常方便
【iOS】线程安全的文件读写的更多相关文章
- ios 简单的plist文件读写操作(Document和NSUserDefaults)
最近遇到ios上文件读写操作的有关知识,记录下来,以便以后查阅,同时分享与大家. 一,简单介绍一下常用的plist文件. 全名是:Property List,属性列表文件,它是一种用来存储串行化后的对 ...
- iOS数据持久化文件读写之偏好设置
很多iOS应用都支持偏好设置,比如保存用户名.密码.字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能.每个应用都有个NSUserDefaults实例,通过它来存取偏好设置.比如, ...
- Cocos2d-x在win32,android和IOS下的文件读写问题
最近在学习和使用Cocos2d-x框架,虽然说的是跨平台,但是在用VS进行开发,然后移植到android或IOS下,也可能会出现各种问题,需要做细微的调整. 例如我在做文件读写操作的时候,很可能在wi ...
- ios本地文件内容读取,.json .plist 文件读写
ios本地文件内容读取,.json .plist 文件读写 本地文件.json .plist文件是较为常用的存储本地数据的文件,对这些文件的操作也是一种常用的基础. 本文同时提供初始化变量的比较标准的 ...
- iOS面向编码|iOSVideoToolbox:读写解码回调函数CVImageBufferRef的YUV图像
iOS面向编码|iOSVideoToolbox:读写解码回调函数CVImageBufferRef的YUV图像 本文档基于H.264的解码,介绍读写Video Toolbox解码回调函数参数CVImag ...
- iOS 线程安全
线程安全: 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题.就好比几个人在同一时修改同一个表格,造成数据的错乱. 解决多线程安全问题的方法 方法一:互斥锁(同步锁) @synchroni ...
- 实现iOS图片等资源文件的热更新化(三):动态的资源文件夹
简介 此文,将尝试动态从某个不确定的文件夹中加载资源文件.文章,会继续完善自定义的 imageNamed 函数,并为下一篇文章铺垫. 这么做的意义 正如我们经常所说的那样,大多数情景知道做事的意义往往 ...
- (转)linux文件读写的流程
转自http://hi.baidu.com/_kouu/item/4e9db87580328244ef1e53d0 在<linux内核虚拟文件系统浅析>这篇文章中,我们看到文件是如何被打开 ...
- C++文件读写详解(ofstream,ifstream,fstream)
C++文件读写详解(ofstream,ifstream,fstream) 这里主要是讨论fstream的内容: #include <fstream> ofstream //文件写操作 内存 ...
随机推荐
- iOS中的webView加载HTML
在日常开发中,我们为了效率会用到很多很多的WebView,比如在做某个明细页面的时候我们返回给你的可能是一个html字符串,我们就需要将当前字符串展示到webView上面,所以我们对HTML标签需要有 ...
- android 透明度颜色值
100% — FF99% — FC98% — FA97% — F796% — F595% — F294% — F093% — ED92% — EB91% — E890% — E689% — E388% ...
- Activity intent经常使用的 FLAG
Intent.FLAG_ACTIVITY_NEW_TASK 默认的跳转类型,会重新创建一个新的Activity,不过与这种情况,比方说Task1中有A,B,C三个Activity,此时在C中启动D的话 ...
- ubuntu 下安装 lxml 失败
/tmp/pip-build-7HN4t8/lxml/src/lxml/includes/etree_defs.h:14:31: fatal error: libxml/xmlversion.h: N ...
- EntityFramework Code First 添加唯一键
在EntityFramework 6.1后可以直接使用 [Index("TitleIndex", IsUnique = true)] public string Title { g ...
- SQL SERVER 服务启动后停止,某些服务由其它服务或程序使用时将自动停止
发生症状: 先是服务器挂掉,之后服务器可以登陆,但是实例却不能登陆进去(部分).出现的错误日志如下: :: R2 (SP2) - 10.50.4000.0 (X64) Jun :: Copyright ...
- 使用proxool 连接池:No suitable driver found for proxool
使用proxool连接池时:报错误No suitable driver found for proxool.shide的原因: ①.WEB-INF目录下的lib中没有proxool连接池jar驱动包. ...
- Xcode 6 UITextField 键盘不弹出
iOS Simulator -> Hardware -> Keyboard Uncheck "Connect Hardware Keyboard"
- 循环a数组(值代表b的下标)删除b数组中存在的记录,从后往前删
for (var j = adelete.Count-1; j >= 0; --j) { aAttachm ...
- android_audio
参考 source.android.com/devices/audio.html