文件存储
文件存储基础
沙盒模型
手机中的沙盒:
- 安全
- 隐私
- 整洁
磁盘空间比较小的时候,提供会对library内的部分文件进行清理。
Documents下的文件不会被清理。
Bundle Container
App内找文件->Bundle->文件名->对应文件
对应代码:
[[NSBundle mainBundle] pathForReasource:@"name" ofType:@"type"];
Data Container
//Home目录,即最外层目录
NSHomeDirectory();
//Home目录,目录下子目录
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//Temp目录
NSTemporaryDirectory();
资源管理器
- 发现资源(遍历目录)
- 修改资源 (创建/删除目录, 创建/删除文件, 修改目录, 读取文件)
NSFileManager
用于文件读写,目录遍历,目录/文件创建,复制,移动,删除...
使用方法:
NSFileManager *manager = [[NSFileManager alloc] init];
NSFileManager *defaultManager = [NSFileManager defaultManager];//单例
内置存储
NSUserDefaults
NSUserDefaults可以存储:
NSString
NSData
NSDate
NSArray
NSDictionary
NSNumber
BOOL,Integer,Float,Double
总结
NSUserDefaults实际上就是个.plist文件
只适合存储一些小的数据。比如用户名,游戏的最高分等等
无加密,不能存储机密文件
一个App只有一个NSUserDefaults
propertyList
当有很多份数据,或不同种数据需要在不同的plist文件中时,就不能使用NSUserDefaults,因为它只有一个。
writeToFile:atomically:
NSArray---------------------------->file.plist
file.plist---------------------------->NSArray
arrayWithContentsOfFile:
writeToFile:atomically:
NSDictionary---------------------------->file.plist
file.plist---------------------------->NSDictionary
dictionaryWithContentsOfFile:
对象归档
NSDictionary is Not a Model
可读性差
model的特性
可读性
可维护性
将对象归档的方法
- 创建一个自定义的对象,需遵循NSCoding协议。需实现:
- encodeWithCoder: //将对象转为特定的数据流
- initWithCoder: //将文件转为特定的对象
- 使用以下方法对文件进行读写:
NSKeyedArchiver
NSKeyedUnarchiver
SQLite
之前文件存储的方法缺点:
无论多小的改动,都是将所有的数据写入文件
所有的数据都是一次性加载到内存
SQL(Structural Query Language)
- 建表
- 插入数据
- 查询数据
- 删除数据
- 更新数据
SQL-建表
建表 create table
表名 members
列名 id,name,gender,mobile
列类型 text,integer,blob
create table if not members (id integer primary key autoincrement, name text, gender integer, mobile text)
SQL-插入
更新 insert into
表名 members
列名 name,gender,mobile
列内容 '小明', '1', '133323'
insert into member (name, gender, mobile) values ('小明',‘1’,‘133323’)
SQL-读取
读取 select from
内容 */entity
表名 members
条件 where/order/group/limit/offset/having
SQL-删除
删除 delete from
表名 members
条件 where
在iOS工程中使用SQLite
在工程中引入SQLite库
import SQLite头文件 #import
调用SQLite API (C API)
SQLite API:
打开数据库
int sqlite3_open (
const char *filename,
sqlite3 **ppDb
);
关闭数据库
int sqlite3_close(sqlite3*);
执行SQL语句
int sqlite3)exec (
sqlite3*,
const char *sql,
int (*callback) (void*, int, char**, char**),
void *,
char **errmsg;
);
准备SQL语句
int sqlite3_prepare(
sqlite3 *db; // Database handle
const char *zSql; // SQL statement, UTF-8 encoded
int nByte, // Maximum length of zSql in bytes
sqlite3_stmt **ppStmt, // 将sql语句的字符串,转化为sql语句的结构体
const char **pzTail // 如何sql语句过长,而且没有准确描述sql语句的长度,则会将超出的字符串截取到该指针中
);
执行
int sqlite_step(sqlite3_stmt *);
清理
int sqlite3_finalize(sqlite3_stmt *pStmt);
Beyond the SQLite
SQLite的缺点
大量C <--> OC 转换
手动指定index
手动资源清理
手动绑定数据
使用OC做SQLite C API 的wrapper
@interface Database : NSObject
- (BOOL)open:(NSString *)filepath;
- (BOOL)close;
- (BOOL)exec:(NSString *)sql,...;
- (NSArray *)query:(NSString *)sql,...;
@end
@interface Database() {
sqlite3 *_db;
}
@end
@implementation Database
- (BOOL)open:(NSString *)filepath {
const char *filename = [filepath UTF8String];
return sqlite3_open(filename, &_db) == SQLITE_OK;
}
- (BOOL)close {
int err = 0;
if (_db) {
err = sqlite3_close(_db);
}
_db = NULL;
return err == SQLITE_OK;
}
- (BOOL)exec:(NSString *)sql,... {
//内部状态判断...
int err = 0;
sqlite3_stmt *stmt = NULL;
if ([sqlite3_prepare(_db, [sql UTF8String], -1, &stmt, NULL) == SQLITE_OK) {
//解析参数
va_list args;
va_start(args, sql);
NSArray *bindArgs = [self parseArguments:args];
va_end(args);
//绑定参数
for (NSInteger i = 0; i < [bindArgs count]; i++) {
[self bindObject:[bindArgs objectAtIndex:i]
index:i + 1
toStmt:stmt];
}
//执行
err = sqlite3_step(stmt);
//回收
sqlite3_finalize(stmt);
}
return err == SQLITE_DONE;
}
@end
FMDB
FMDB是成熟的SQLite Objective-C封装
github地址
CoreData
FMDB是很好用,但是写SQL很麻烦,很繁琐。
CoreData优点
没有sql语句
兼容性强
苹果主推
CoreData缺点
学习曲线陡峭
坑多
ORM(Object-Relational Mapping)
CoreData Stack
Objects <--> ORM <--> Database //ORM是对象和数据库之间的衔接。
做存储的第三方库
不会把所有内容存到内存中,有很好的性能
levelDB类似CoreData,但比CoreData简单。
Realm
对比
| plist/对象归档/文件读写 | SQLite | CoreData |
--------- | ------------- | ----- |---
查询速度 | 非常快 | 快(但需要精心设计) | 较快
读写速度 | 随着数据量增大读写速度变慢 | 快,稳定 | 快,稳定
内存占用 | 高 | 低 | 低
复杂度 | 低,使用简单 | 中,使用繁琐 | 高,使用简单
大数据量支持 | 不适宜 | 适宜 | 适宜
适应场景 | 少量数据存储 | 几乎适用所有的场景,对大数据查询有特别好的支持 | 几乎适用所有场景
兼容性 | 兼容性好 | 涉及到数据升级会比较麻烦 | 兼容性好