注:借鉴于:http://blog.csdn.net/jianjianyuer/article/details/8556024

在IOS开发过程中,不管是做什么应用,都会碰到数据保存问题。将数据保存到本地,能够让程序更加流畅,不会出现让人厌恶的菊花状,使得用户的体验更好。下面是介绍数据保存的方式

第一、NSKeyedArchiver:采用归档的形式来保存数据。(归档——解档)———大量数据和频繁读写不合适使用

1、归档器的作用是将任意的对象集合转换为字节流。这听起来像是NSPropertyListSerialization类采用的过程,但是它们之间有一个重要的区别。属性列表序列化只能转换一个有限集合的数据类型(大多是数量类型),而归档可以转换任意的OC对象、数据类型、数组、结构、字符串以及更多其他类型。

2、Foundatio框架支持两种归档器。顺序归档和基于键的归档。基于键的归档器更加灵活,是应用程序开发中推荐使用的归档器 。

3、一个面向对象程序在运行的时候,一般都创建了一个复杂的对象关系图,经常需要把这样一个复杂的对象关系图表示成字节流,这样的过程叫做          Archiving.

4、而当从字节流中重新恢复对象关系图的过程叫做unarchive。

5、NSCoder是archivie字节流的抽象类。

6、对一个对象归档需要满足的条件是:该对象的类必须实现NSCoding协议

归档、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
-(int)create:(Note *)model
 
{
 
    NSString *homeDictionary = NSHomeDirectory();
 
    NSString *path = [homeDictionary stringByAppendingPathComponent:FILE_NAME];
 
    NSFileManager *fileManager = [NSFileManager defaultManager];
 
     
 
    BOOL isexists = [fileManager fileExistsAtPath:path];
 
    NSMutableArray *array = [[NSMutableArray alloc] init];
 
    [array addObject:model];
 
    
 
    //archive归档
 
    NSMutableData *theData = [NSMutableData data];
 
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
 
    [archiver encodeObject:array forKey:ARCHIVE_KEY];
 
    [archiver finishEncoding];
 
     
 
    [theData writeToFile:path atomically:YES];
 
//    [array writeToFile:path atomically:YES];
 
     
 
    return 0;
 
  
 
}

解档、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-(NSMutableArray *)findAll
 
{
 
    NSString *homeDictionary = NSHomeDirectory();
 
    NSString *path = [homeDictionary stringByAppendingPathComponent:FILE_NAME];
 
    NSMutableArray *listData = [[NSMutableArray alloc] init];
 
    NSData *theData = [NSData dataWithContentsOfFile:path];
 
     
 
    if([theData length]>0)
 
    {
 
        NSKeyedUnarchiver *archiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
 
        listData = [archiver decodeObjectForKey:ARCHIVE_KEY];
 
        [archiver finishDecoding];
 
    }
 
    return listData;
 
}

第二、NSUserDefaults

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//自动登陆用到的
 
  
 
+(id)configForKey:(NSString *)key
 
{
 
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
 
    return [defaults objectForKey:key];
 
}
 
//写入内容
 
+(void)setLoginConfig:(id)value forKey:(NSString *)key
 
{
 
    NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
 
    [user setObject:value forKey:key];
 
    [user synchronize];   //及时强制写入
 
}
 
  
 
//读出内容
 
+(NSString *)getLoginConfig:(NSString *)key
 
{
 
    NSString *s = [Globle  configForKey:key];
 
    if(s==nil)
 
    {
 
        return @"";
 
    }
 
    return s;
 
  
 
}

第三、write写入磁盘

第一步:获得文件即将保存的路径:

NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,  NSUserDomainMask,YES);//使用C函数NSSearchPathForDirectoriesInDomains来获得沙盒中目录的全路径。该函数有三个参数,目录类型、he domain mask、布尔值。其中布尔值表示是否需要通过~扩展路径。而且第一个参数是不变的,即为NSSearchPathDirectory 。在IOS中后两个参数也是不变的,即为:NSUserDomainMask 和 YES。
NSString *ourDocumentPath =[documentPaths objectAtIndex:0];

还有一种方法是使用NSHomeDirectory函数获得sandbox的路径。具体的用法为:

NSString *sandboxPath = NSHomeDirectory();
// Once you have the full sandbox path, you can create a path from it,但是不能在sandbox的本文件层上写文件也不能创建目录,而应该是此基础上创建一个新的可写的目录,例如Documents,Library或者temp。
NSString *documentPath = [sandboxPath
            stringByAppendingPathComponent:@"Documents"];//将Documents添加到sandbox路径上,具体原因前面分析了!

这两者的区别就是:使用NSSearchPathForDirectoriesInDomains比在NSHomeDirectory后面添加Document更加安全。因为该文件目录可能在未来发送的系统上发生改变。

第二步:生成在该路径下的文件:

NSString *FileName=[documentDirectory stringByAppendingPathComponent:fileName];//fileName就是保存文件的文件名

第三步:往文件中写入数据:

[data writeToFile:FileName atomically:YES];//将NSData类型对象data写入文件,文件名为FileName

最后:从文件中读出数据:

NSData data=[NSData dataWithContentsOfFile:FileName options:0 error:NULL];//从FileName中读取出数据

第四、SQLite数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@interface BaseViewController ()
 
{
 
    sqlite3 *sqlDataBase;
 
}
 
@end
 
  
 
@implementation BaseViewController
 
  
 
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
 
{
 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 
    if (self) {
 
        // Custom initialization
 
    }
 
    return self;
 
}
 
  
 
- (void)viewDidLoad
 
{
 
    [super viewDidLoad];
 
    if ([self createOrOpen:@"test.db"]) {
 
//        [self createUserTable:sqlDataBase];
 
//        [self insertMBkey:nil];
 
        NSMutableArray *s = [NSMutableArray new];
 
        [self GetList:s];
 
        NSLog(@"%@",s);
 
    }else
 
    {
 
        NSLog(@"FAIL");
 
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/**
 
 *该函数主要打开数据库myDataBase.sql,如果该数据库不存在,则进行创建
 
 *打开或者创建成功返回yes,否则返回false,参数dbName是数据库的名称
 
 **/
 
-(BOOL)createOrOpen:(NSString *)dbName
 
{
 
    //获取用户域覆径信息
 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectoryNSUserDomainMaskYES);
 
    NSString *documentsDirectory = [paths objectAtIndex:0];
 
    /**
 
     *Users/admin/Library/Application Support/iPhone Simulator/7.1/Applications/8E23557E-AAA6-471A-AAFE-E036BF1B7E4C/Library/Documentation
 
     *判断用户域是否有数据库dbNmae
 
     */
 
    NSString *path = [documentsDirectory stringByAppendingPathComponent:dbName];
 
    NSFileManager *fileManageer = [NSFileManager defaultManager];
 
    //如果用户域内有该数据库,则返回yes,否则返回NO
 
    BOOL find = [fileManageer fileExistsAtPath:path];
 
    if(find)   //对找到进行处理,如果找到了,并且打开了,则返回yes
 
    {
 
        //打开该数据库,如果打开失败,则返回NO,否则返回yes
 
        if(sqlite3_open([path UTF8String], &sqlDataBase)!= SQLITE_OK)
 
           {
 
               //关闭sqlDataBase,实际是释放了它
 
               sqlite3_close(sqlDataBase);
 
               return NO;
 
           }
 
           return YES;
 
    }
 
     
 
    NSLog(@"%d",sqlite3_open([path UTF8String], &sqlDataBase));
 
           //创建数据库,创建返回yes,并且打开数据库,否则返回NO
 
    if(sqlite3_open([path UTF8String], &sqlDataBase)==SQLITE_OK)
 
    {
 
        return YES;
 
    }else
 
    {
 
     //关闭sqlDataBase,实际是释放了它
 
        sqlite3_close(sqlDataBase);
 
        return NO;
 
    }
 
            
 
            
 
            
 
    return NO;
 
}
 
//在打开的数据库中创建表,其中sqldb为成功打开的数据库的sqlite3对象
 
-(BOOL)createUserTable:(sqlite3 *)sqlDataBas
 
{
 
    //设置sql语句
 
    char *sql = "create table user(id integer primary key, name text, address text, imageData BLOB, imageLen integer)";
 
    sqlite3_stmt *statement;  //这个相当于ODBC的Command对象,用于保存编译好的SQL语句
 
    //进行预处理,预处理失败返回NO
 
    if(sqlite3_prepare_v2(sqlDataBase, sql, -1, &statement, nil)!=SQLITE_OK)
 
    {
 
        return NO;
 
    }
 
    //预处理成功,进行执行创建操作
 
    int success = sqlite3_step(statement);
 
    sqlite3_finalize(statement);
 
    if(success !=SQLITE_DONE)
 
    {
 
        return NO;
 
    }
 
    return YES;
 
     
 
     
 
}
 
//向表中插入数据
 
-(void)insertMBkey:(NSString *)key
 
{
 
    BOOL isOK = NO;
 
    sqlite3_stmt *statement;
 
    static char *sql = "INSERT INTO user VALUES ('1', 'Bill', '河南', 'ssss','2')";
 
    int success = sqlite3_prepare_v2(sqlDataBase, sql, -1, &statement, NULL);
 
    if(success !=SQLITE_OK)
 
    {
 
        isOK = NO;
 
    }else
 
    {
 
        sqlite3_bind_text(statement, 1, [key UTF8String], -1, SQLITE_TRANSIENT);
 
        success = sqlite3_step(statement);
 
        sqlite3_finalize(statement);
 
    }
 
     
 
    if(success ==SQLITE_ERROR)
 
    {
 
        isOK = NO;
 
    }else
 
    {
 
        isOK=YES;
 
    }
 
     
 
    return;
 
}
 
//查询数据
 
-(void)GetList:(NSMutableArray *)KeysList
 
{
 
    BOOL  isOK = NO;
 
    sqlite3_stmt *statement;
 
    static char *sql = "select id,address from user";
 
    int success = sqlite3_prepare_v2(sqlDataBase, sql, -1, &statement, NULL);
 
    if(success !=SQLITE_OK)
 
    {
 
        isOK = NO;
 
    }else
 
    {
 
        //查询结果集中一条一条地遍历所有记录,这里的数字对应的时列值
 
        while (sqlite3_step(statement)==SQLITE_ROW) {
 
            int kid = sqlite3_column_int(statement, 0);
 
            char *key = (char  *)sqlite3_column_text(statement, 1);
 
            UserInfo *userModel = [[UserInfo alloc] init];
 
         
 
                userModel.userId =kid;
 
            if (key) {
 
              userModel.userAddress = [NSString stringWithUTF8String:key];
 
            }
 
                [KeysList addObject:userModel];
 
            sqlite3_finalize(statement);
 
        }
 
        NSLog(@"%@",KeysList);
 
        if(success==SQLITE_ERROR)
 
        {
 
            isOK = NO;
 
        }else
 
        {
 
            isOK = YES;
 
        }
 
        return;
 
    }
 
  
 
}

IOS数据本地存储的四种方式--的更多相关文章

  1. ios页面间传递参数四种方式

    ios页面间传递参数四种方式 1.使用SharedApplication,定义一个变量来传递. 2.使用文件,或者NSUserdefault来传递 3.通过一个单例的class来传递 4.通过Dele ...

  2. [转载]-win7启动本地MongoDB的四种方式

    2016年04月07日 09:52:34 cherry__cheng 阅读数:19451 标签: win7启动本地MongoDB的四种方式快速启动本地mongodb 更多 个人分类: mongodb& ...

  3. android 数据存储的四种方式.

    Android系统一共提供了四种数据存储方式.分别是:SharePreference.SQLite.Content Provider和File.由于Android系统中,数据基本都是私有的的,都是存放 ...

  4. IOS音频1:之采用四种方式播放音频文件(一)AudioToolbox AVFoundation OpenAL AUDIO QUEUE

    本文转载至 http://blog.csdn.net/u014011807/article/details/40187737 在本卷你可以学到什么? 采用四种方法设计应用于各种场合的音频播放器: 基于 ...

  5. ASP.NET MVC之控制器传递数据到视图的四种方式

    前奏 1. 在新建项目中的Models文件下,新建Products类: public class Products { public int Id { get; set; } public strin ...

  6. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  7. C#_批量插入数据到Sqlserver中的四种方式

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  8. C#批量插入数据到Sqlserver中的四种方式 - 转

    先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...

  9. 实现web数据同步的四种方式

    http://www.admin10000.com/document/6067.html 实现web数据同步的四种方式 1.nfs实现web数据共享 2.rsync +inotify实现web数据同步 ...

随机推荐

  1. 关于 rand() 函数返回值的值域的疑问

    <C语言参考手册>中关于 rand() 函数有如下描述. (1)rand() 函数的原型 int rand(void); (2)连续调用 rand 将返回 0 到 int 类型的最大可表示 ...

  2. oracle查询字符集语句

      (1)查看字符集(三条都是等价的) 复制代码 代码如下: select * from v$nls_parameters  where parameter='NLS_CHARACTERSET'sel ...

  3. ONFI闪存数据通道接口标准

    早期的闪存产品每个厂家的设计标准各有不同,会碰到各种各样的问题,特别是到了06年之后,闪存产业市场需求开始发力,造成了迫切需要一个统一的标准来改变这个问题. 2007年1月,以英特尔,镁光,海力士,意 ...

  4. QR Code簡介、介紹

    QR Code為目前最常被使用的一種二維條碼,1994年由日本Denso-Wav e公司發明,QR是英文Qu ickResponse的縮寫,即快速反應的意思,1999年時,公布了符合日本當地的標準-「 ...

  5. thrift之初体验

    hrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, ...

  6. 精通 VC++ 实效编程280例 - 01 窗口

    窗口是屏幕上的一个矩形区域.窗口分为3种:重叠窗口.弹出窗口和子窗口.每个窗口都有由系统绘制的“非客户区”和应用程序绘制的“客户区”.在 MFC 中,CWnd 类为各种窗口提供了基类. 1 通过 HW ...

  7. VS2010/MFC对话框:字体对话框

    字体对话框) 在上一节为大家讲解了文件对话框的使用,本节则主要介绍字体对话框如何应用. 字体对话框的作用是用来选择字体.我们也经常能够见到.MFC使用CFontDialog类封装了字体对话框的所有操作 ...

  8. 经常使用的时间同步server地址

    转载出处http://www.minunix.com/2013/03/ntpserver/ 感谢原作者,一切的权利都属于原作者,假设有所不适,我会马上删除 中国大概能用的NTP时间server地址 s ...

  9. Linux 进程通信之 ——信号和信号量总结

    如今最经常使用的进程间通信的方式有:信号,信号量,消息队列,共享内存.       所谓进程通信,就是不同进程之间进行一些"接触",这种接触有简单,也有复杂.机制不同,复杂度也不一 ...

  10. MOSS程序中如何发Mail?

    我们使用.NET类库中的API发Mail的时候,我们要配置他的SMTP Server等,但是在Sharepoint里,已经提供了相关的封装的方法: SPUtility.SendEmail(SPWeb, ...