引言:本篇博文主要介绍iOS文件处理,包括NSData,沙盒,常用文件路径,NSBundle的介绍。
1. iOS的沙盒机制
1.1 沙盒
苹果公司为了限制对应用程序中系统资源和用户数据的访问,以在应用程序受到损害时控制损害,推出了沙盒机制。
应用程序沙盒通过限制应用程序对通过授权请求的资源的访问,为系统资源和用户数据提供保护。
再把App SandBox放大:
在app被安装后,iOS会为应用创建三个容器,如分别为Bundle Container和Data Container和iCloud Container(接入iCloud,这里不做介绍)。
1.2 Bundle Container
1.2.1 Bundle
bundle路径就是通常所说的应用程序在手机里面的安装路径,其就是一个目录,这个目录就是main bundle。这个目录里面通常包含图像、媒体资源、编译好的代码、nib、文件等可执行文件和所有资源文件,这个目录是只读的,但是在编程时试试,其实也是可以写入的。
1)怎么打开Bundle目录?
在Xcode中,找到poducts,其中有一个xxx.app,然后 show in finder。此时有一个xxx.app,然后显示包内容。
下面是我其中一个demo,有我自己添加的一些资源,具体可以打开自己的某个工程看看。
2)怎么添加资源文件到Bundle
一种方法是打开上面的目录,把资源文件放进去,添加目录或者直接放资源都是可以的,
另外一种方法是,在工程中创建Bundle文件,然后添加资源文件到Bundle。然后获取到天剑的Bundle,然后使用资源文件,
在代码中我们需要使用NSBundle来读取资源,下面来具体看看代码的使用
1.2.2 使用NSBundle
用具体代码来使用一下mainBundle。
// 获得主 Bundle 信息
// 就是 .app 目录路径
NSBundle *mainBundle = [NSBundle mainBundle];
// 获取主Bundle 文件路径
NSString *bundlePath = [NSBundle mainBundle].bundlePath;
NSString *resourcePath = [NSBundle mainBundle].resourcePath;
// 获取 Bundle URL 路径
NSURL *bundleUrl = [NSBundle mainBundle].bundleURL;
NSURL *resourceURL = [NSBundle mainBundle].resourceURL;
// 获得 Bundle 目录下的文件路径
NSString *filePath1 = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"json"];
// 获得 bundle 下子目录 subdirectory 下的文件路径
NSString *filePath2 = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"json" inDirectory:@"configFolder"];
// 获得 Bundle 目录下的 URL 路径
NSURL *fileUrl1 = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"txt"];
// 获得 bundle 下子目录 subdirectory 下的 URL 路径
NSURL *fileUrl2 = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"txt" subdirectory:@"testFolder"];
除了使用资源,我们还可以来使用查询和使用APP的一些信息,这些信息保存在info.plist中。
// 获取应用程序唯一标识包名
NSString *indentifier = [NSBundle mainBundle].bundleIdentifier;
// 获取应用程序 Info.plist 配置项词典对象实例
NSDictionary *info = [NSBundle mainBundle].infoDictionary;
// 获取某一特定字段的内容
NSString *bundleID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
/*
其他具体关于info.plist可以在网上在具体了解
*/
下面来看看怎么创建一个自定义的子Bundle,选择New—>File—>Setting Bundle。最后设置名称,引进资源。
用代码来使用我们子Bundle。
// 获取某bundle下的某个文件
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"bundle"]];
// 其余和mainBundle的使用方式是一样的
NSString *path = [bundle pathForResource:@"xxx" ofType:@"plist"];
1.3 Data Container
1.3.1 目录结构
目录中包含:Documents、Library、tmp
Document : 存储用户数据,需要备份的信息
Library/Caches : 存储缓存文件,程序专用的支持文件
Library/Preferences : 存储应用程序的偏好设置⽂件
tmp : 存储临时文件,比如:下载的zip包,解压后的再删除
注:
iTunes在与iPhone同步时,会备份Documents
和Preferences
目录下的⽂件 。
- Documents:用于存放程序中的文件数据,应用程序在运行时生成的一些需要长久保存的数据(比如:游戏进度存档、应用程序个人设置,下载的资源等等),通过 iTunes、iCloud 备份时, 会备份这个目录下的数据,此目录下保存相对重要的数据。
- Library 包含Caches和Preferences⼦目录
1)Caches:存放缓存文件,从网络上下载的文件或者数据(如:音乐缓存、图片缓存等),此目录下的文件不会在应用退出时自动删除 ,需要程序员手动清除改目录下的数据。iTunes、iCloud 备份时不会备份此目录下的数据。主要用于保存应用在运行时生成的需要长期使用的数据,一般用于存储体积较大,不需要备份的非重要数据。
2)Preferences存放的是基于NSUserDefaults的设置数据,文件格式为 “plist”。设置应用的一些功能会在该目录中查找相应设置的信息,iTunes、iCloud备份时会备份此目录下的数据。该目录由系统自动管理,通常用来储存一些基本的应用配置信息。比如账号密码、自动登录等。 - tmp:存放应用运行时产生的一些临时数据和文件,当应用程序退出、系统磁盘空间不足、手机重启时,都会自动清除该目录的数据。无需程序员手动清除该目录中的数据,iTunes、iCloud备份时不会备份此目录。
1.3.2 使用代码获取目录
NSArray*NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
用于查找目录,返回指定范围内的指定名称的目录的路径集合。param:directory 指定收索路径名称,博文后面附上完整的枚举
常用:NSDocumentDirectory、NSLibraryDirectory、NSCachesDirectory
param:domainMask 限定文件检索范围
常用:
NSUserDomainMask = 1, // 用户主目录
NSLocalDomainMask = 2, // 当前机器
NSNetworkDomainMask = 4, // 网络中可见的主机
NSSystemDomainMask = 8, // 系统目录,不可修改
NSAllDomainsMask = 0x0ffff // 所有
param:expandTilde 是否显示完整路径,还是使用~相对路径
// 获取程序的根目录
NSString *homeDirectory = NSHomeDirectory();
// 获取document目录
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 获取Caches目录
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 获取Library目录
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
// 获取Tmp目录
NSString *tmpDirectory = NSTemporaryDirectory();
通常我们都是使用NSFileManager来实现文件IO。这个类后面在数据处理时在详细介绍。
2. 数据的转换与处理
2.1 数据来源
在数据来源主要是本地文件与网络传输,数据的转换与处理也就是本地文件的数据与网络数据的IO操作,这其中设计数据的转换,由于文件格式,传输便捷等等各种原因,需要对IO数据进行转换与处理,下面就是常见的使用方法。
IO:数据的输入与输出
2.2 NSData
A static byte buffer in memory.
apple官网上的一句话,就是内存中静态字节缓冲区,在官网中还说明object-oriented wrappers for byte buffers.
即就是包装对象。
NSData屏蔽了数据之间的差异,对象,文本、音频、图像等数据都可用NSData来存储,也常用来数据持久化,网络数据传输等等。神通广大,下面我们来具体使用一下。
//对象方法创建
NSData *data1 = [[NSData alloc] init];
NSData *data2 = [[NSData alloc] initWithData:data1];
//类方法创建
NSData *data3 = [NSData data];
NSData *data4 = [NSData dataWithData:data3];
//由文件创建
NSString *filePath = @"xxx/xxx/xxx.xxx";
NSData *data5 = [[NSData alloc] initWithContentsOfFile:filePath];
NSData *data6 = [NSData dataWithContentsOfFile:filePath];
// 由 URL 创建
NSURL *urlPath = [NSURL URLWithString:@"xxx/xxx"];
NSData *data7 = [[NSData alloc] initWithContentsOfURL:urlPath];
NSData *data8 = [NSData dataWithContentsOfURL:urlPath];
// 由 字符串 创建
NSString *string = @"hello world!";
NSData *data9 = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *data10 = [string dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
// 可变 NSData 的创建
// 初始化时指定对象拥有的字节空间大小,在需要时会增加内存空间,在初始化时并没有分配内存空间
NSMutableData *data11 = [[NSMutableData alloc] initWithCapacity:5];
NSMutableData *data12 = [NSMutableData dataWithCapacity:5];
// 初始化时为对象分配指定长度的归零字节
NSMutableData *data13 = [[NSMutableData alloc] initWithLength:10];
NSMutableData *data14 = [NSMutableData dataWithLength:10];
上面是NSData对象的创建,除了NSData对象的转换,还有NSData对象转换成别的对象,因为NSData屏蔽了数据之间的差异,因此常常用来作为两个不同数据的中间对象。
2.3 NSStringPathExtensions
这是NSString的一个分类,主要是关于文件路径相关的。需要先了解一下。
// 首先我们先假设一个路径。
NSString *filePath = @"/Users/Name/Desktop/file.json";
// 获得组成此路径的各个组成部分,结果:("/","Users","Name","testfile.txt")
(NSArray *)pathComponents;
// 提取路径的最后一个组成部分,结果:file.json
(NSString *)lastPathComponent;
// 删除路径的最后一个组成部分,结果:/Users/Name/Desktop
(NSString *)stringByDeletingLastPathComponent;
// 将path添加到路径的末尾,结果:/Users/Name/Desktop/file.json/Desktop/file.json
// str = @"Desktop/file.json"
(NSString *)stringByAppendingPathConmponent:(NSString *)str;
// 去路径最后部分的扩展名,结果:json
(NSString *)pathExtension;
// 删除路径最后部分的扩展名,结果:/Users/Name/Desktop/file
(NSString *)stringByDeletingPathExtension;
// 路径最后部分追加扩展名,不要带. 如.zip .png 不用带前面的点, 直接zip png
(NSString *)stringByAppendingPathExtension:(NSString *)str;
2.4 NSFileManager
NSFileManager是一个单例的文件管理类。通过用defaultManager获取对象;
/* Returns the default singleton instance.
*/
@property (class, readonly, strong) NSFileManager *defaultManager;
下面介绍几个常用的方法。
// 创建一个文件并写入数据
- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
// 从一个文件中读取数据
- (NSData *)contentsAtPath:(NSString *)path;
// scrPath路径上的文件移动到dstPath路径上,注意这里的路径是文件路径而不是目录
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **) error;
// scrPath路径上的文件复制到dstPath路径上
- (BOOL)copyItemAtPath:(NSString *)scrPath toPath:(NSString *)dstPath error:(NSError **) error;
// 比较两个文件的内容是否一样
- (BOOL)contentsEqualAtPath:(NSString *)path1 andPath:(NSString *)path2;
// 文件是否存在
- (BOOL)fileExistsAtPath:(NSString *)path;
// 移除文件
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **) error;
// 将NSData对象写入文件
// 从这儿就可以看到,将任何对象转换成NSData对象后,写入文件,都可以实现本地文件持久化
BOOL success = [fileManager createFileAtPath:path contents: NSDataObj attributes:nil];
// NSFileManager-读取内容
NSData *fileData = [fileManager contentsAtPath:filePath]; NSString *content = [[NSString alloc] initWithData:fileData dataUsingEncoding: NSUTF8StringEncoding];
// NSData-读取内容
NSString *filePath = [path stringByAppendingPathComponent:@"xxx.txt"];
NSData *data = [NSData dataWithContentOfFile:filePath];
// NSString-读取内容
NSString *filePath = [path stringByAppendingPathComponent:@"xxx.txt"]; NSString *content = [[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
// 移动、复制、删除文件
// 移动文件(重命名)
BOOL Success = [fileManager moveItemAtPath:filePath toPath:toPath error:nil];
BOOL success = [fileManager copyItemAtPath:filePath toPath:toPath error:nil];
BOOL success = [fileManager removeItemAtPath:filePath error:nil];
// 获得文件的属性字典
NSDictionary *attrDic = [fileManager attributesOfItemAtpath:sourcePath error:nil]; NSNumber *fileSize = [attrDic objectForKey:NSFileSize];
// 字典的具体属性见 附
上面这个字典属性,如果没有对Linux文件系统有过了解的话,需要去了解一下,否则不是太容易理解:
【Linux文件与权限】这篇博文简单的理解了Linux下的文件与权限,可以参考一下。
2.5 JSON
本小姐是关于JSON格式的数据。包括网络传输的数据,本地JSON化的序列数据等,都可以用到。
我们用到的类是 NSJSONSerialization
我们能利用NSJSONSerialization将JSON转换成Foundation对象,也能将Foundation对象转换成JSON,转换成JSON的对象必须具有如下属性:
1)顶层对象必须是NSArray或者NSDictionary
2)所有的对象必须是NSString、NSNumber、NSArray、NSDictionary、NSNull的实例
3)所有NSDictionary的key必须是NSString类型
4)数字对象不能是非数值或无穷
在我们拿到与JSON格式相关的数据时,可以使用它。通常是网络数据中,response的data数据我们需要对齐进行转换成我们想要的NSDictionary
// 反序列化:根据NSData对象返回一个Foundation对象
+ (id)JSONObjectWithData:(NSData *)data
options:(NSJSONReadingOptions)opt
error:(NSError **)error
enum {
// 返回可变容器,NSMutableDictionary或NSMutableArray。
NSJSONReadingMutableContainers = (1UL << 0),
// 返回的JSON对象中字符串的值为NSMutableString,
NSJSONReadingMutableLeaves = (1UL << 1),
// 返回的既不是字典也不是数组,则必须使用该枚举值
NSJSONReadingAllowFragments = (1UL << 2)
};
typedef NSUInteger NSJSONReadingOptions;
// 序列化:将foundation对象转换成JSON对象
+ (NSData *)dataWithJSONObject:(id)obj
options:(NSJSONWritingOptions)opt
error:(NSError **)error
附:
NSSearchPathDirectory
typedef NS_ENUM(NSUInteger, NSSearchPathDirectory) {
NSApplicationDirectory = 1, // supported applications (Applications) 应用程序
NSDemoApplicationDirectory, // unsupported applications, demonstration versions (Demos)
NSDeveloperApplicationDirectory, // developer applications (Developer/Applications). DEPRECATED - there is no one single Developer directory. 已弃用
NSAdminApplicationDirectory, // system and network administration applications (Administration)
###Library###
NSLibraryDirectory, // various documentation, support, and configuration files, resources (Library)
NSDeveloperDirectory, // developer resources (Developer) DEPRECATED - there is no one single Developer directory. 已弃用
NSUserDirectory, // user home directories (Users)
NSDocumentationDirectory, // documentation (Documentation)
###Document###
NSDocumentDirectory, // documents (Documents)
NSCoreServiceDirectory, // location of CoreServices directory (System/Library/CoreServices)
NSAutosavedInformationDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 11, // location of autosaved documents (Documents/Autosaved)
NSDesktopDirectory = 12, // location of user's desktop
###Caches###
NSCachesDirectory = 13, // location of discardable cache files (Library/Caches)
NSApplicationSupportDirectory = 14, // location of application support files (plug-ins, etc) (Library/Application Support)
NSDownloadsDirectory API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 15, // location of the user's "Downloads" directory
NSInputMethodsDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 16, // input methods (Library/Input Methods)
NSMoviesDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 17, // location of user's Movies directory (~/Movies)
NSMusicDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 18, // location of user's Music directory (~/Music)
NSPicturesDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 19, // location of user's Pictures directory (~/Pictures)
NSPrinterDescriptionDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 20, // location of system's PPDs directory (Library/Printers/PPDs)
NSSharedPublicDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 21, // location of user's Public sharing directory (~/Public)
NSPreferencePanesDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 22, // location of the PreferencePanes directory for use with System Preferences (Library/PreferencePanes)
NSApplicationScriptsDirectory NS_ENUM_AVAILABLE(10_8, NA) = 23, // location of the user scripts folder for the calling application (~/Library/Application Scripts/code-signing-id)
NSItemReplacementDirectory API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = 99, // For use with NSFileManager's URLForDirectory:inDomain:appropriateForURL:create:error:
NSAllApplicationsDirectory = 100, // all directories where applications can occur
NSAllLibrariesDirectory = 101, // all directories where resources can occur
NSTrashDirectory API_AVAILABLE(macos(10.8), ios(11.0)) API_UNAVAILABLE(watchos, tvos) = 102 // location of Trash directory
};
文件属性(attributes)
// 文件或者文件夹的大小,注意单位是byte
NSFileSize(不可更改)
// 设置一个表示布尔值的NSNumber对象,表示创建的目录是否是只读的。
NSFileAppendOnly
// 设置一个NSDate对象,表示目录的创建时间。
NSFileCreationDate(可更改时间)
// 设置一个NSString对象,表示这个目录的所有者的名字。
NSFileOwnerAccountName
//设置一个NSString对象,表示这个目录的用户组的名字。
NSFileGroupOwnerAccountName
// 设置一个unsigned int的NSNumber对象,表示目录的组ID。
NSFileGroupOwnerAccountID
// 设置一个NSDate对象,表示目录的修改时间。
NSFileModificationDate(可更改时间)
// 设置一个unsigned int的NSNumber对象,表示目录的所有者ID。
NSFileOwnerAccountID
// 设置一个short int的NSNumber对象,表示目录的访问权限。
NSFilePosixPermissions
// 设置一个unsigned long的NSNumber对象,表示目录的引用计数,即这个目录的硬链接数。
NSFileReferenceCount