2.plist属性列表 (适合简单数据类型,比如说一些配置信息之类的)
这种可以使用NSArrary, NSDictionary等这些工具类直接写入文件
使用 arrayWithContentsOfFile:(NSString *)aPath 来从文件获取数据
使用 writeToFile:atomically: 来把数据写入文件
3.归档 (经过加密的保存数据方式,也是以键值对形式保存读取的.)
例: 所有归档对象必须支持NSCoding协议 和 NSCopying(支持对象复制)
//写入归档文件
NSArray *list = @[[NSArray allc] initWithObjects:@"one", @"two", nil];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:list forKey:@"keyValue"];
[archiver finishEncoding];
BOOL success = [data writeToFile:@"/path/to/archive" atomically:YES];
//成功返回YES
//读取归档文件
NSArray *list = nil;
NSData *data = [[NSData alloc] initWithContentsOfFile:@"/path/to/archive"];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
list = [unarchiver decodeObjectForKey:@"keyValue"];
[unarchiver finishDecoding];
//至此已经完成
4.SQLite3 这是一个小型的数据库 (支持复杂的数据查询和存储)
使用前得引入动态库 libsqlite3.dylib, 使用过程中的字符串类型必须是标准C字符串.
sqlite3_open() //用来打开数据库
sqlite3_prepare_v2() //操作数据库前的准备
sqlite3_step() //分步查询或者执行
sqlite3_column() //查询过后获取列值
sqlite3_bind_*() //当你想要插入或者更新数据时来绑定的内容
sqlite3——reset() //重置这个语句,回到重新绑定的状态
sqlite3_finalize() //销毁这个对象
sqlite3_close() //关闭数据库
sqlite3_exec是sqlite3_prepare_v2,sqlite3_step()和sqlite3_finalize()的封装,能让程序多次执行sql语句而不要写许多重复的代码。
Sqlite3_exec接口执行0或多个UTF-8编码的,分号分割的sql语句,传到第二个参数中。如果sqlite3_exec的第三个参数回调函数指针不为空,那么它会为每个来自执行的SQL语句的结果行调用(也就是说回调函数会调用多次,上面例子中会返回2个结果行,因而会被执行2次),第4个参数是传给回调函数的第一个参数,如果回调函数指针为空,那么回调不会发生同时结果行被忽略。
如果在执行sql语句中有错误发生,那么当前的语句的执行被停止,后续的语句也被跳过。第五个参数不为空的时候,它被分配内存并写入了错误信息,所以在sqlite3_exec后面需要调用sqlite3_free去释放这个对象以防止内存泄露
回调函数:
int (*callback)(void*,int,char**,char**), /* Callback function */
第一个参数通过sqlite3_exec的第第四个参数传入的
第二个参数是结果行的列数
第三个参数是行中列数据的指针
第四个参数是行中列名称的指针
查询数据
int sqlite3_get_table(sqlite3*, const char *sql, char ***resultp, int *nrow, int *ncolumn, char **errmsg );
第1个参数是前面open函数得到的指针。
第2个参数const char *sql是一条 sql语句,以结尾。
第3个参数是查询结果,它是一维数组,它内存布局是:第一行是字段名称,后面是紧接着是每个字段的值。
第4个参数是查询出多少条记录(即查出多少行)。
第5个参数是多少个字段(多少列)。
第6个参数是错误信息。
操作二进制
sqlite3_stmt * 所表示的内容看成是 sql语句,但是实际上它不是我们所熟知的sql语句。它是一个已经把sql语句解析了的、用sqlite自己标记记录的内部数据结构。要插入二进制,前提是这个表的字段的类型是 blob 类型。
假设有一张表:
create table Tbl_2( ID integer, file_content blob )
首先声明
sqlite3_stmt * stat;
然后,把一个 sql 语句解析到 stat结构里去:
// sqlite3_prepare 接口把一条SQL语句编译成字节码留给后面的执行函数.使用该接口访问数据库是当前比较好的的一种方法.
sqlite3_prepare( db, “insert into Tbl_2( ID, file_content) values( 10, ? )”, -1, &stat, 0 );
上面的函数完成 sql 语句的解析
第一个参数跟前面一样,是个 sqlite3 * 类型变量,
第二个参数是一个 sql 语句。这个 sql语句特别之处在于 values里面有个 ?号。在sqlite3_prepare函数里,?号表示一个未定的值,它的值等下才插入。
第三个参数我写的是-1,这个参数含义是前面 sql语句的长度。如果小于0,sqlite会自动计算它的长度(把sql语句当成以结尾的字符串)。
第四个参数是 sqlite3_stmt 的指针的指针。解析以后的sql语句就放在这个结构里。
第五个参数为0就可以了。
如果这个函数执行成功(返回值是 SQLITE_OK 且 stat不为NULL),那么下面就可以开始插入二进制数据。
sqlite3_bind_blob( stat, 1, pdata, (int)(length_of_data_in_bytes), NULL );
// pdata为数据缓冲区,length_of_data_in_bytes为数据大小,以字节为单位
这个函数一共有5个参数。
第1个参数:是前面prepare得到的 sqlite3_stmt *类型变量。
第 2个参数:?号的索引。前面prepare的sql语句里有一个?号,假如有多个?号怎么插入?方法就是改变 bind_blob 函数第2个参数。参数为1,表示这里插入的值要替换 stat的第一个?号(这里的索引从1开始计数,而非从0开始)。如果你有多个?号,就写多个 bind_blob语句,并改变它们的第2个参数就替换到不同的?号。如果有?号没有替换,sqlite为它取值null。
第3个参数:二进制数据起始指针。
第4个参数:二进制数据的长度,以字节为单位。
第5个参数:是个析构回调函数,告诉sqlite当把数据处理完后调用此函数来析够你的数据。但是一般都填NULL,需要释放的内存自己用代码来释放。
bind完了之后,二进制数据就进入了你的“sql语句”里了。你现在可以把它保存到数据库里:
虚 拟机执行字节码,执行过程是一个步进(stepwise)的过程,每一步(step)由sqlite3_step()启动,并由VDBE(sqlite虚拟机)执行一段字节码。由sqlite3_prepare编译字节代码,并由sqlite3_step()启动虚拟机执行。在遍历结果集的过程中,它返回 SQLITE_ROW,当到达结果末尾时,返回SQLITE_DONE
int result = sqlite3_step( stat );
通过这个语句,stat 表示的sql语句就被写到了数据库里。
最后,要把 sqlite3_stmt 结构给释放:sqlite3_finalize( stat ); //把刚才分配的内容析构掉
读出二进制
先声明 sqlite3_stmt * 类型变量:
sqlite3_stmt * stat;
然后,把一个 sql 语句解析到 stat结构里去:
sqlite3_prepare( db, “select * from Tbl_2”, -1, &stat, 0 );
当 prepare 成功之后(返回值是 SQLITE_OK ),开始查询数据。
int result = sqlite3_step( stat );
这一句的返回值是 SQLITE_ROW 时表示成功(不是 SQLITE_OK )。
你可以循环执行 sqlite3_step 函数,一次 step查询出一条记录。直到返回值不为 SQLITE_ROW时表示查询结束。
然后开始获取第一个字段:ID 的值。ID是个整数,用下面这个语句获取它的值:
int id = sqlite3_column_int( stat, 0 ); //第2个参数表示获取第几个字段内容,从0开始计算。
下面开始获取 file_content 的值,因为 file_content是二进制,因此我需要得到它的指针,还有它的长度:
const void * pFileContent = sqlite3_column_blob( stat, 1 );
int len = sqlite3_column_bytes( stat, 1 );
这样就得到了二进制的值。
把 pFileContent 的内容保存出来之后,
不要忘了释放 sqlite3_stmt 结构:
sqlite3_finalize( stat ); //把刚才分配的内容析构掉
重复使用 sqlite3_stmt 结构
如果你需要重复使用 sqlite3_prepare 解析好的 sqlite3_stmt 结构,需要用函数: sqlite3_reset。
result = sqlite3_reset(stat);
这样, stat 结构又成为 sqlite3_prepare 完成时的状态,你可以重新为它 bind内容。
事务处理
sqlite 是支持事务处理的。如果你知道你要同步删除很多数据,不仿把它们做成一个统一的事务。通常一次 sqlite3_exec就是一次事务,如果你要删除1万条数据,sqlite就做了1万次:开始新事务->删除一条数据->提交事务->开始新事务 ->… 的过程。这个操作是很慢的。因为时间都花在了开始事务、提交事务上。你可以把这些同类操作做成一个事务,这样如果操作错误,还能够回滚事务。
事务的操作没有特别的接口函数,它就是一个普通的 sql 语句而已:
分别如下:
int result;
result = sqlite3_exec( db, "begin transaction", 0, 0, &zErrorMsg ); //开始一个事务
result = sqlite3_exec( db, "commit transaction", 0, 0, &zErrorMsg ); //提交事务
result = sqlite3_exec( db, "rollback transaction", 0, 0, &zErrorMsg ); //回滚事务
5. Core Data苹果自带的数据管理工具 (底层是SQLite3)
数据持久化存储
数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型
名词解释
(1)NSManagedObjectContext(被管理的数据上下文)
操作实际内容(操作持久层)
作用:插入数据,查询数据,删除数据
(2)NSManagedObjectModel(被管理的数据模型)
数据库所有表格或数据结构,包含各实体的定义信息
作用:添加实体的属性,建立属性之间的关系
操作方法:视图编辑器,或代码
(3)NSPersistentStoreCoordinator(持久化存储助理)
相当于数据库的连接器
作用:设置数据存储的名字,位置,存储方式,和存储时机
(4)NSManagedObject(被管理的数据记录)
相当于数据库中的表格记录
(5)NSFetchRequest(获取数据的请求)
相当于查询语句
(6)NSEntityDescription(实体结构)
相当于表格结构
(7)后缀为.xcdatamodeld的包
里面是.xcdatamodel文件,用数据模型编辑器编辑
编译后为.momd或.mom文件
(8)NSAttributeDescription
实体的attribut
(9)NSRelationshipDescription
指代实体间的relationship
(10)NSFetchedPropertyDescription
fetched属性
(11)NSSortDescriptor (排序)
NSSortDescriptor *sortDescriptor = [[NSSortDescriptoralloc]initWithKey:@"字段名"ascending:NO];
依赖关系
主要由以下几个类组合使用
//获取管理对象 后缀名为xcdatamodeld的Core Data文件做以下调用
NSURL *modelURL = [[NSBundlemainBundle] URLForResource:@"Core_Data_Peristence"withExtension:@"momd"];
NSManageObjectModel *model = [[NSManageObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManageObjectModel:];
//设置数据底层的存储类型和文件名
NSURL *url= [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] LastObject]];
NSURL *mUrl = [url URLByAppendingPathComponent:@"core_data_persitence.sqlite"];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:mUrl options:nil error:nil];
//创建对象管理上下文并关联数据
NSManagedObjectContext *context = [[NSManageObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];
NSError *error;
//创建一个抓取数据的对象管理
NSFetchRequest *request = [[NSFetchRequest alloc] init];
//创建一个实体对象描述 ,相当于选择一个数据库里的表Line
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:@"Line"
inManagedObjectContext:context];
//设置抓取数据的条件筛选
NSPredicate *pred = [NSPredicate predicateWithFormat:@"name = %s", @"xukai"];
//结合表和条件准备开始抓取
[request setEntity:entityDescription];
[request setPredicate:pred];
//用来保存抓取出来的结果
NSmanagedObject* object = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
if( [objects count] > 0 )
object = [objects objectAtIndex:0];
else
object = [NSEntityDescription
insertNewObjectForEntityForName:@"Line"
inManagedObjectContext:context];
[object setValue:29 forKey:@"age"];
[object setValue:1 forKey:@"sex"];
[context save:&error];
1
2
3
4
5
6
7
8
9
10
11
12
13NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"People" inManagedObjectContext:managedObjectContext]; request.entity = entity; request.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:@"age"]]; request.returnsDistinctResults = YES; request.resultType = NSDictionaryResultType; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES]; [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptors]]; [sortDescriptor release]; NSError *error = nil; NSArray *distincResults = [managedObjectContext executeFetchRequest:request error:&error]; // Use the results [request release];
CoreData数据库升级方法
1
2
3
4
5
6
7
8
9
10
11
12NSPersistentStoreCoordinator 初始化方案: 你以前的代码可能是这样: if (![persist addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrloptions:nil error:&err]) { NSAssert(0, @"persist init failed!"); } 修改成: NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; if (![persist addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrloptions:options error:&err]) { NSAssert(0, @"persist init failed!"); }
最后
以上就是高挑鸵鸟最近收集整理的关于IOS之持久化数据的常用5种方法的全部内容,更多相关IOS之持久化数据内容请搜索靠谱客的其他文章。
发表评论 取消回复