JSON解析以及对大文件下载的探讨

json解析简单介绍
1.是一种轻量级数据格式,用于数据交互;服务器返回客户端的数据,一般都是JSON格式或者XML格式;
注意:JSON格式的Key必须使用双引号;

2.解析:将JSON解析为OC数据类型;
JSON解析方案:
(1)第三方框架:JSONKit、SBJson、TouchJSON
(2)苹果原生:NSJSONSerialization(性能最好)
[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]
[NSJSONSerialization dataWithJSONObject:dictM options:NSJSONWritingPrettyPrinted error:nil]
注意:JSON解析又称为序列化;NSJSONSerialization称为序列化工具;可以在JSON和OC对象之间互相转换;
3.解析过程:
服务器端—>NSData/JSON—>OC对象(字典,数组)—>模型—>客户端
4.JSON数据和OC数据的对应关系:
JOSN OC
{} @{}
[] @[]
"" @""
false NSNumber 0
true NSNumber 1
null NSNull为空
[NSNull null]是一个单例;

5.将plist文件转换为JSON文件
(1)拿到plist文件的数组;
(2)进行序列化操作;
(3)生成JSON文件;
NSArray *array=[NSArray arrayWithContentsOfFile:@".plist"];
NSData *data = [NSJSONSerialization dataWithJSONObject:array options:1 error:nil];
[data writeToFile:@".json" atomically:YES];

大文件下载
1.内存飙升的原因是下载了大的文件,包括代理方法也需要拼接出一个大的文件;所以想办法直接将文件直接写入到沙盒里面(不在外部拼接);
2.定义全局属性沙盒路径,在didReceiveResponse方法中拿到沙盒路径;
3.不能使用拼接data,就删除mutableData属性,删除懒加载;这样无法实现计算下载进度;
所以需要定义全局属性,记录当前data的长度,在didReceiveData方法中累加data的长度;
4.写数据过程:
拿到文件的总大小;
拿到全路径;
使用文件管理者单例,创建一个空的文件夹creatFileAtPath;
创建一个文件句柄(NSFileHandle);定义全局属性,拿到文件句柄;
//创建一个空的文件夹
[[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
// 创建文件句柄
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
5.在didReceiveData方法中:
移动文件句柄到数据的末尾;
写数据;
获得进度;
// 将文件句柄移动到data的最末位置
[self.handle seekToEndOfFile];
// 进行写数据操作
[self.handle writeData:data];
6.注意:如果创建了一个文件句柄,需要在使用完之后关闭文件句柄(在didFinishLoading方法中);
// 关闭文件句柄
[self.handle closeFile];
self.handle=nil;
7.添加进度条,来吧进度信息显示到进度条控件上面;
//设置进度条
self.downloadProgress.progress=1.0 * self.currentLength /self.dataLength;


实现大文件断点下载
1.增加开始下载和取消下载操作;
将发送请求操作添加到开始下载按钮中;;
拿到Connection对象,在取消下载按钮中取消下载;
[self.connection cancel];
2.要记录下载断点,需要修改请求头信息,所以把请求对象设置成为可变的请求对象,来修改它的请求头;
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:url];
NSString *range=[NSString stringWithFormat:@"bytes=%zd-",self.currentLength];
表示从当前长度开始下载剩下的全部数据;
[request setValue:range forHTTPHeaderField:@"Range"];
3.但是这样做,当点击取消下载时候,会暂停下载;再次点击开始下载时候会再次创建一个新的请求对象,再次调用代理方法-didReceiveResponse:,创建一个新的文件夹,去接收数据,会覆盖原来的下载的文件;所以需要在这个方法中判断 属性当前文件的大小,如果大于0就return,不再创建新的文件夹;此时会接着上一次的下载的文件继续下载;
4.注意:本次请求的文件的总大小并不是文件的实际总大小,而是本次请求下载的大小;
//拿到本次请求文件的总大小
self.dataLength=response.expectedContentLength;
如果将这个操作挪到第3步的判断之前,那么总大小应该再加上当前获得的总大小self.currentLength;

输出流实现大文件断点下载
1.在didReceiveResponse方法中 :
创建输出流,传入要写的文件路径;
打开输出流;
定义一个全局属性输出流;
// 创建输出流
NSOutputStream *stream=[[NSOutputStream alloc]initToFileAtPath:self.fullPath append:YES];
// 打开输出流
[stream open];
self.stream=stream;
2.在didReceiveData方法中:
使用输出流写数据,传入data.bytes和data.length;
[self.stream write:data.bytes maxLength:data.length];
3.在完成方法中关闭输出流;
[self.stream close]; self.stream=nil;
注意:如果该输出流指向的地址没有文件,那么会自动创建一个空的文件;

posted @ 2016-09-14 09:55  陈宇杰  阅读(1276)  评论(0编辑  收藏  举报