文件存储

文件存储

文件存储基础

沙盒模型

手机中的沙盒:

  • 安全
  • 隐私
  • 整洁

磁盘空间比较小的时候,提供会对library内的部分文件进行清理。
Documents下的文件不会被清理。

Bundle Container

App内找文件->Bundle->文件名->对应文件

对应代码:
[[NSBundle mainBundle] pathForReasource:@"name" ofType:@"type"];

Data Container

//Home目录,即最外层目录
 NSHomeDirectory();

//Home目录,目录下子目录
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

//Temp目录
NSTemporaryDirectory();

资源管理器

  1. 发现资源(遍历目录)
  2. 修改资源 (创建/删除目录, 创建/删除文件, 修改目录, 读取文件)

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的特性

可读性
可维护性

将对象归档的方法

  1. 创建一个自定义的对象,需遵循NSCoding协议。需实现:
- encodeWithCoder:    //将对象转为特定的数据流
- initWithCoder:      //将文件转为特定的对象
  1. 使用以下方法对文件进行读写:
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 |
--------- | ------------- | ----- |---
查询速度 | 非常快 | 快(但需要精心设计) | 较快
读写速度 | 随着数据量增大读写速度变慢 | 快,稳定 | 快,稳定
内存占用 | 高 | 低 | 低
复杂度 | 低,使用简单 | 中,使用繁琐 | 高,使用简单
大数据量支持 | 不适宜 | 适宜 | 适宜
适应场景 | 少量数据存储 | 几乎适用所有的场景,对大数据查询有特别好的支持 | 几乎适用所有场景
兼容性 | 兼容性好 | 涉及到数据升级会比较麻烦 | 兼容性好

你可能感兴趣的:(文件存储)