本章主要介绍Objective-C输入/输出(简称I/O或O/I)的相关知识。
Objective-C提供了如下相关API:
本章包括:
NSFileManager进行管理文件和目录,包括创建、删除、移动、修改和复制文件。
NSFileHandle进行处理读取文件内容,
NSUrl进行读取网络资源;
NSBundle进行读取项目内部资源;
一、使用NSData与NDMutableData
Foundation提供了NSData和NSMutableData,他们代表Objective-C的数据缓冲区。NSData的作用有两个:
- ①、对数据读取NSData;
- ②、输出NSData的数据;
NSData的初始化方法:
- (1)、data创建一个不包含任何数据的、空的NSData对象;
- (2)、dataWithBytes:length:/initWithBytes:length:复制C数组所包含的数据来初始化NSData的数据;
- (3)、dataWithBytesNoCopy:length:/initWithBytesNoCopy:length:直接利用C数组所包含的数据来初始化NSData对象。当该对象被执行malloc方法释放自己时,程序会释放该C数组;
- (4)、dataWithBytesNoCopy:length:freeWhenDone:/initWithBytesNoCopy:length:freeWhenDone:直接利用C数组所包含的数据来初始化NSData对象,只有当最后一个参数为YES,且该对象执行malloc方法销毁自己时,程序才会是释放该C数组;
- (5)、dataWithContentsOfFile:/initWithContentsOfFile:直接读取文件内容,并利用文件内容来初始化NSData;
- (6)、dataWithContentsOfURL:/initWithContentsOfURL:直接读取URL关联的内容,并利用文件内容来初始化NSData;
- (7)、dataWithData:/initWithData:直接使用另一个NSData所包含的数据来初始化新创建的数据。
得到NSData对象之后,可以调用如下方法来访问数据:
- (1)、bytes返回该NSData所包含的数据;
- (2)、getBytes:length:获取NSData所包含的指定长度的数据;
- (3)、getBytes:range:获取NSData所包含的指定范围的数据;
- (4)、subdataWithRange:获取NSData所包含的指定范围的数据组- 成的NSData对象;
- (5)、writeToFile:atomically:将NSData的数据写入文件;
- (6)、writeToUrl:atomically:将NSData的数据写入指定URL的资源;
例如:
(1)、使用指定URL对应的数据初始化NSData
//使用NSData读取指定URL对应的数据
NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.crazyit.org/ethos.php"]];
(2)、求得NSData的长度
NSLog(@"%ld",[data length]);//
//定义一个长度为100的数组
char buffer[100];
(3)、将指定范围的数据写入数组
//将NSData指定范围的数据写入数组
[data getBytes:buffer range:NSMakeRange(103, 100)];
//输出数组的内容
NSLog(@"%s",buffer);
/*
输出:
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-T…
*/
(4)、将NSData转化成NSString
//直接将NSData的数据用UTF-8的格式转化成字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"网页内容为:%@",content);
二、使用NSFileManager管理文件和目录
NSFileManager代表文件管理器,通过NSFileManager的帮助,开发者可以完成许多通用的文件操作。当开发者使用NSFileManager执行移动、复制、链接、删除文件或目录时,程序可以为NSFileManager提供一个配套的事件委托(实现了NSFileManagerDelegate协议的对象)。
NSFileManager采用文件作为文件的唯一标识,每个文件都是一个普通的NSString对象,它即可使用相对路径,也可以是绝对路径。
- (1)、相对路径:不以斜线开头的路径都是相对路径。比如:abc.m、codes/Test.m。
- (2)、绝对路径:以斜线(代表根路径)开头的路径就是绝对路径。绝对路径是唯一的,他代表的文件或目录总是固定的,比如:/Users/abc。
除此之外,还有几个比较特殊的路径:
- (1)、~:代表当前用户的Home目录。比如当前用户为abc,那么“~”就代表/Users/abc;还可以写成~xyz,它代表xyz用户的Home目录,即/Users/xyz。
- (2)、.:代表当前路径。
- (3)、..:代表当前目录的上一级目录。
1、访问文件属性和内容
NSFileManager为访问文件属性和内容提供了如下方法:
- (1)、fileExistsAtPath::判断指定文件名对应的文件是否存在。
- (2)、fileExistsAtPath:isDirectory::判断该指定文件名对应的文件或目录是否存在,该方法的后一个参数可用于返回该文件名是否为目录。
- (3)、isReadableFileAtPath::判断指定目录下的文件是否可读。
- (4)、isWritableFileAtPath::判断指定目录下的文件是否可写。
- (5)、isExecutableFileAtPath::判断指定目录下的文件是否可执行。
- (6)、isDeletableFileAtPath::判断指定目录下的文件是否可删除。
- (7)、componentsToDisplayForPath::获取指定文件名对应文件的各个路径组件。
- (8)、displayNameAtPath::获取指定文件问对应文件的简单文件名。
- (9)、attributesOfItemAtPath:error::获取指定文件名对应文件的属性。
- (10)、attributesOfFileSystemForPath:error::获取指定文件名对应文件所在文件系统的属性
- (11)、setAttributes:ofItemAtPath::设置指定文件名对应文件的属性。
- (12)、contentsAtPath::获取指定文件名对应文件的内容。
- (13)、contentsEqualAtPath:andPath::判断两个文件名指定的文件内容是否相同。
例如:
(1)、获取单例
//单例
NSFileManager* fm = [NSFileManager defaultManager];
(2)、是否存在
//将输出代表真的1
NSLog(@"mydict.txt是否存在:%d",[fm fileExistsAtPath:@"mydict.txt"]);//mydict.txt是否存在:1
(3)、是否存在且是否为目录
BOOL isDir;
NSLog(@"mydict.txt是否存在:%d",[fm fileExistsAtPath:@"mydict.txt" isDirectory:&isDir]);
//将会输出代表假的0
NSLog(@"mydict.txt是否为目录:%d",isDir);//mydict.txt是否为目录:0
(4)、是否可读
//将会输出代表真的1
NSLog(@"mydict.txt是否为可读文件:%d",[fm isReadableFileAtPath:@"mydict.txt"]);
(5)、是否可写
//将会输出代表真的1
NSLog(@"mydict.txt是否为可写文件:%d",[fm isWritableFileAtPath:@"mydict.txt"]);
(6)、是否可执行
//将会输出代表假的0
NSLog(@"mydict.txt是否为可执行文件:%d",[fm isExecutableFileAtPath:@"mydict.txt"]);
(7)、是否可删除
//将会输出代表真的1
NSLog(@"mydict.txt是否为可删除文件:%d",[fm isDeletableFileAtPath:@"mydict.txt"]);
(8)、获取路径组件
//获取mydict.txt文件所在的路径组件
NSArray* arrat = [fm componentsToDisplayForPath:@"mydict.txt"];
NSLog(@"--mydict.txt所在路径的完整路径组件为--");
for (NSObject* ele in arrat) {
NSLog(@"%@",ele);
/*
输出:
Macintosh HD
用户
chenxiao
资源库
Developer
Xcode
DerivedData
重新学习-fvftebswkwfhovfdqhoyfjkqitbx
Build
Products
Debug
mydict.txt
*/
}
(9)、获取相关属性
//获取文件的相关属性
NSDictionary* attr = [fm attributesOfItemAtPath:@"mydict.txt" error:nil];
//获取文件属性的详情
NSLog(@"mydict.txt的创建时间为:%@",[attr fileCreationDate]);//mydict.txt的创建时间为:2014-12-08 07:37:03 +0000
NSLog(@"mydict.txt的属主账户为:%@",[attr fileOwnerAccountName]);//mydict.txt的属主账户为:chenxiao
NSLog(@"mydict.txt的文件大小为:%lld",[attr fileSize]);//mydict.txt的文件大小为:356
(10)、获取文件内容
//直接获取文件内容
NSData* data = [fm contentsAtPath:@"mydict.txt"];
//直接将NSData的数据用UTF-8的格式转换字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"------输出文件内容------");
NSLog(@"%@",content);
/*
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>four</key>
<string>Perl</string>
<key>one</key>
<string>Objective-C</string>
<key>three</key>
<string>Python</string>
<key>two</key>
<string>Ruby</string>
</dict>
</plist>
*/
2、创建、删除、移动、复制
NSFileManager为创建、删除、移动、复制文件或目录提供了如下方法:
- (1)、createDirectoryAtUrl:withIntermediateDirectories:attributes:error::根据指定的URL创建目录;
- (2)、createDirectoryAtPath:withIntermediateDirectories:attributes:error::根据指定的路径创建目录;
- (3)、createFileAtPath:contents:attributes::根据指定的文件路径、内容创建文件;
- (4)、removeItemAtUrl:error::删除指定URL对应的文件;
- (5)、removeItemAtPath:error::删除指定路径对应的文件;
- (6)、copyItemAtURL:toURL:error::根据指定的URL复制文件或目录;
- (7)、copyItemAtPath:toPath:error::根据指定路径复制文件或目录;
- (8)、moveItemAtURL:toURL:error::根据指定URL移动文件或目录;
- (9)、moveItemAtPath:toPath:error::根据指定路径移动文件或目录。
例如:注意路径全是绝对路径
(1)、单例
NSFileManager* fm = [NSFileManager defaultManager];
(2)、创建目录
//创建目录
//第一个参数:文件路径
//第二个参数:如果父目录不存在,则创建父目录
//第三个参数:文件属性
[fm createDirectoryAtPath:@"/Users/chenxiao/Desktop/xyz/abc" withIntermediateDirectories:YES attributes:nil error:nil];
NSString* content = @"《疯狂iOS讲义》是我正在学习的图书";
(3)、创建文件
//创建一个文件
[fm createFileAtPath:@"/Users/chenxiao/Desktop/xyz/abc/myInfo.txt" contents:[content dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
(4)、获取文件属性
//获取文件属性
NSLog(@"myInfo.txt:%@",[fm attributesOfItemAtPath:@"/Users/chenxiao/Desktop/xyz/abc/myInfo.txt" error:nil]);
/*
输出:
myInfo.txt:
{
NSFileCreationDate = "2014-12-09 09:51:54 +0000";
NSFileExtensionHidden = 0;
NSFileGroupOwnerAccountID = 20;
NSFileGroupOwnerAccountName = staff;
NSFileHFSCreatorCode = 0;
NSFileHFSTypeCode = 0;
NSFileModificationDate = "2014-12-09 09:51:54 +0000";
NSFileOwnerAccountID = 501;
NSFileOwnerAccountName = chenxiao;
NSFilePosixPermissions = 420;
NSFileReferenceCount = 1;
NSFileSize = 48;
NSFileSystemFileNumber = 6150933;
NSFileSystemNumber = 16777219;
NSFileType = NSFileTypeRegular;
}
*/
(5)、复制文件
//复制一份新文件
[fm copyItemAtPath:@"myInfo.txt" toPath:@"/Users/chenxiao/Desktop/xyz/abc/copyInfo.txt" error:nil];
(6)、删除文件
//删除文件
[fm removeItemAtPath:@"/Users/chenxiao/Desktop/xyz/abc/myInfo.txt" error:nil];
(7)、删除目录
//删除目录
[fm removeItemAtPath:@"/Users/chenxiao/Desktop/xyz" error:nil];
3、查看目录包含的内容
对于文件目录,NSFileManager提供了如下方法查看目录包含的内容
- (1)、contentsOfDirectoryAtPath:error::获取指定目录下的所有文件和子目录。对于指定目录下的子目录该方法不会进行递归枚举;
- (2)、enumeratorAtPath::获取指定目录下的所有文件和子目录对应的枚举器(NSDirectoryEnumerator对象)。如果指定目录下的文件是子目录,该方法默认会递归枚举子目录中所有的内容。当然,程序可调用NSDirectoryEnumerator方法的skipDescendants方法来组织递归枚举子目录。
- (3)、subpathsOfDirectoryAtPath:error::递归获取指定路径包含的所有目录及子目录;
- (4)、subpathsAtPath::与前一个方法的功能基本类似。
例如:
(1)、单例
NSFileManager* fm = [NSFileManager defaultManager];
(2)、获取指定目录下的文件夹 不递归子目录
//获取指定目录下的所有文件和文件夹
NSArray* array = [fm contentsOfDirectoryAtPath:@"/Users/chenxiao/Desktop/重新学习" error:nil];
for (NSString* item in array) {
NSLog(@"%@",item);
/*
.DS_Store
.git
FDPersonTest.h
FKPerson.h
FKPerson.m
FKPersonTest.m
重新学习
重新学习.xcodeproj
*/
}
(2)、获取指定目录下所有文件和文件夹的枚举器 递归子目录
//获取指定目录下所有文件和文件夹对应的枚举器
NSDirectoryEnumerator* dirEnum = [fm enumeratorAtPath:@"/Users/chenxiao/Desktop/重新学习"];
NSString* file;
while (file = [dirEnum nextObject]) {
//如果该文件名以.m结尾
if ([[file pathExtension] isEqualToString:@"m"]) {
//直接获取文件内容
NSData* data = [fm contentsAtPath:[NSString stringWithFormat:@"/Users/chenxiao/Desktop/重新学习/%@",file]];
//直接将NSData的数据用UTF-8的格式转换字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"content = %@",content);
}else{
NSLog(@"%@",file);
}
}
(3)、获取目录下的所有子目录,递归子目录
//获取当前目录下的所有子目录
NSArray* subArr = [fm subpathsOfDirectoryAtPath:@"/Users/chenxiao/Desktop/重新学习" error:nil];
NSArray* subarr = [fm subpathsAtPath:@"/Users/chenxiao/Desktop/重新学习"];
NSLog(@"%@==%@",subArr,subarr);
三、使用NSPathUtilities.h管理路径
NSPathUtilities.h包含了对NSString类的扩展,从而为NSString类新增了一些专门用于操作路径的方法:
- (1)、+ (NSString )pathWithComponents:(NSArray )components;根据components中的元素构造有效的路径;
- (2)、- (NSArray *)pathComponents;分拆路径,返回该路径中各部分所组成的数组;
- (3)、- (BOOL)isAbsolutePath;返回该路径是否为绝对路径;
- (4)、- (NSString *)lastPathComponent;提取该路径的最后一个组成部分;
- (5)、- (NSString *)pathExtension;从路径的最后一个组成部分提取扩展名;
- (6)、- (NSString *)stringByAbbreviatingWithTildeInPath;将路径中当前用户的home路径替换为~;将路径中指定当前用户的home路径替换为~user的形式;
- (7)、- (NSString )stringByAppendingPathComponent:(NSString )str;将str添加到现有路径的结尾处;
- (8)、- (NSString )stringByAppendingPathExtension:(NSString )str;将str扩展名添加到现有路径的结尾处;
- (9)、- (NSString *)stringByDeletingLastPathComponent;删除路径的最后一个组成部分;
- (10)、- (NSString *)stringByDeletingPathExtension;删除路径的最后一个组成部分的扩展名;
- (11)、- (NSString *)stringByExpandingTildeInPath;将路径中的代字符(~或user)解析成当前用户的home目录或指定用户的home目录;
- (12)、- (NSString *)stringByResolvingSymlinksInPath;解析路径中的符号链接,返回解析后的路径;
- (13)、- (NSString *)stringByStandardizingPath;解析路径中的~、..、.和符号链接,返回解析后生成的标准路径;
除此之外还有 - (14)、NSString *NSUserName(void);返回当前用户名;
- (15)、NSString *NSFullUserName(void);返回当前用户的完整用户名;
- (16)、NSString *NSHomeDirectory(void);返回当前用户的home目录;
- (17)、NSString *NSHomeDirectoryForUser(NSString *userName);返回指定用户的home目录;
- (18)、NSString *NSTemporaryDirectory(void);返回系统的临时文件;
- (19)、NSString *NSOpenStepRootDirectory(void);
例如:
(1)、获取当前用户
NSLog(@"当前用户名为:%@",NSUserName());//当前用户名为:chenxiao
(2)、获取当前用户完整用户名
NSLog(@"当前用户的完整用户名为:%@",NSFullUserName());//当前用户的完整用户名为:陈晓
(3)、获取当前用户的home目录
NSLog(@"当前用户的home目录为:%@",NSHomeDirectory());//当前用户的home目录为:/Users/chenxiao
(4)、获取root用户的home目录
NSLog(@"root用户的home目录为:%@",NSHomeDirectoryForUser(@"root"));//root用户的home目录为:/var/root
(5)、获取系统临时目录
NSLog(@"系统临时目录为:%@",NSTemporaryDirectory());//系统临时目录为:/var/folders/js/fsgm7wns4tq37pc2cfdqsp9w0000gn/T/
(6)、将~root解析成root用户的的home目录
NSString* path1 = @"~root";
//将~root解析成root用户的home目录
NSLog(@"解析~root的结果:%@",[path1 stringByExpandingTildeInPath]); //解析~root的结果:/var/root
(7)、替换成~的形式
NSString* path2 = @"/Users/chenxiao/publish";
//将会输出~/publish
NSLog(@"替换成~的形式:%@",[path2 stringByAbbreviatingWithTildeInPath]);//替换成~的形式:~/publish
(8)、遍历路径中包含的个路径组件
//遍历该路径中包含的各路径组件
NSArray* array = [path2 pathComponents];
for (NSString* item in array) {
NSLog(@"%@",item);
/*
输出:
/
Users
chenxiao
publish
*/
}
(9)、在路径后边追加一个路径
//在path2路径后追加一个路径
NSString* path3 = [path2 stringByAppendingPathComponent:@"abc.m"];
NSLog(@"path3为:%@",path3);//path3为:/Users/chenxiao/publish/abc.m
(10)、获取路径的最后部分
//获取路径的最后部分
NSString* last = [path3 lastPathComponent];
NSLog(@"path3的最后一个路径组件为:%@",last);//path3的最后一个路径组件为:abc.m
(11)、获取路径的最后部分的扩展名
//获取路径的最后部分的扩展名
NSLog(@"path3的最后一个路径的扩展名:%@",[path3 pathExtension]);//path3的最后一个路径的扩展名:m
四、使用ProcessInfo获取进度信息
当一个程序运行起来之后就变成了一个进程,NSProcessInfo对象则可用于获取该进程的相关信息,包括获取运行该程序的参数、进程标识符等。还可以获取该进程的主机名,操作系统名,操作系统版本等信息。
程序调用NSProcessInfo的processInfo类方法即可获取该进程对应的NSProcessInfo对象,接下来即可调用NSProcessInfo的如下方法来获取该进程,以及该进程所在系统的信息:
- (1)、argument:该方法返回该程序所传入的参数组成的NSArray对象;
- (2)、environment:该方法返回系统内所有环境变量名和值组成的NSDictionary对象;
- (3)、processIdentifier:该方法返回该进程的标识符;
- (4)、globallyUniqueString:该方法用于返回一个全局的、唯一的字符串;
- (5)、processName:该方法返回该进程的进程名;
- (6)、setProcessName:该方法用于设置进程的进程名;
- (7)、hostName:该方法返回该进程所在系统的主机名;
- (8)、operationSystem:该方法返回该进程所在系统的操作系统;
- (9)、operatingSystemName:该方法返回该进程所在系统的操作系统名;
- (10)、operationSystemVersionString:该方法返回该进程所在系统的操作系统版本号;
- (11)、physicalMemory:该方法返回系统的物理内存;
- (12)、activeProcessorCount:该方法返回系统中激活状态的处理器的数量;
- (13)、systemUptime:该方法返回系统已运行的时间。
例如:
(1)、获取当前进程的ProcessInfo对象
//获取当前进程对应的ProcessInfo对象
NSProcessInfo* proInfo = [NSProcessInfo processInfo];
(2)、获取运行该程序所指向的参数
//获取运行该程序所指向的参数
NSArray* arr = [proInfo arguments];
NSLog(@"运行程序的参数为:%@",arr);
(3)、获取进程标识符
NSLog(@"进程标识符为:%d",[proInfo processIdentifier]);//进程标识符为:1590
(4)、获取进程的进程名
NSLog(@"进程的进程名为:%@",[proInfo processName]);//进程的进程名为:重新学习
(5)、获取所在系统的主机名
NSLog(@"进程所在系统的主机名为:%@",[proInfo hostName]);//进程所在系统的主机名为:chenxiaodemacbook-pro.local
(6)、获取进程所在系统的操作系统
NSLog(@"进程所在系统的操作系统为:%ld",[proInfo operatingSystem]);//进程所在系统的操作系统为:5
(7)、获取进程所在系统的操作系统名
NSLog(@"进程所在系统的操作系统名为:%@",[proInfo operatingSystemName]);//进程所在系统的操作系统名为:NSMACHOperatingSystem
(8)、获取进程所在系统的操作系统版本字符串
NSLog(@"进程所在系统的操作系统版本字符串为:%@",[proInfo operatingSystemVersionString]);//进程所在系统的操作系统版本字符串为:Version 10.9.5 (Build 13F34)
(9)、获取进程所在系统的物理内存
NSLog(@"进程所在系统的物理内存为:%lld",[proInfo physicalMemory]);//进程所在系统的物理内存为:8589934592
(10)、获取进程所在系统的处理器数量
NSLog(@"进程所在系统的处理器数量为:%ld",[proInfo processorCount]);//进程所在系统的处理器数量为:4
(11)、获取进程所在系统的激活的处理器数量
NSLog(@"进程所在系统的激活的处理器数量为:%ld",[proInfo activeProcessorCount]);//进程所在系统的激活的处理器数量为:4
(12)、获取进程所在系统的运行时间为
NSLog(@"进程所在系统的运行时间为:%f",[proInfo systemUptime]);//进程所在系统的运行时间为:17633.546019
五、使用NSFileHandle处理文件IO
NSFileHandle提供了处理文件IO相关方法,步骤如下:
- 创建一个NSFileHandle,该NSFileHandle将会打开指定的文件;
- 对打开的文件执行IO操作;
- 关闭文件;
NSFileHandle提供的方法如下:
- (1)、+ (instancetype)fileHandleForReadingAtPath:(NSString *)path;根据指定路径打开一份准备读取文件内容的文件,并返回该文件对应的NSFileHandle;
- (2)、+ (instancetype)fileHandleForReadingFromURL:(NSURL )url error:(NSError *)error;根据指定URL打开一份准备读取文件内容的文件,并返回该文件对应的NSFileHandle;
- (3)、+ (instancetype)fileHandleForWritingAtPath:(NSString *)path;根据指定路径打开一份准备写入文件内容的文件,并返回该文件对应的NSFileHandle;
- (4)、+ (instancetype)fileHandleForWritingToURL:(NSURL )url error:(NSError *)error;根据指定URL打开一份准备写入文件内容的文件,并返回该文件对应的NSFileHandle;
- (5)、+ (instancetype)fileHandleForUpdatingAtPath:(NSString *)path;根据指定路径路径打开一份即可读取,又可写入文件内容的文件,并返回该文件对应的NSFileHandle;
- (6)、+ (instancetype)fileHandleForUpdatingURL:(NSURL )url error:(NSError *)error;根据指定URL打开一根即可读取,又可写入文件内容的文件,并返回该文件对应的NSFileHandle;
- (7)、+ (NSFileHandle *)fileHandleWithStandardError;打开标准错误输出设备对应的NSFileHandle;
- (8)、+ (NSFileHandle *)fileHandleWithStandardInput;打开标准输入设备(通常是键盘)对应的NSFileHandle;
- (9)、+ (NSFileHandle *)fileHandleWithStandardOutput;打开标准输出设备(通常是屏幕)对应的NSFileHandle;
- (10)、+ (NSFileHandle *)fileHandleWithNullDevice;打开空设备对应的NSFileHandle;
- (11)、- fileDescriptor:获取对应文件的描述器;
- (12)、- availableData:返回该文件所有可用的数据;
- (13)、- (NSData *)readDataToEndOfFile;读取该文件中包含的所有数据;
- (14)、- (NSData *)readDataOfLength:(NSUInteger)length;读取该文件中length字节的数据;
- (15)、- seekToEndOfFile:将该NSFileHandle中文件指针移动到文件的结尾处;
- (16)、- (void)seekToFileOffset:(unsigned long long)offset;将该NSFileHandle中文件指针移动到指定的位置;
- (17)、- (void)closeFile;关闭底层文件;
- (18)、- (void)truncateFileAtOffset:(unsigned long long)offset;将文件长度“截断”为offset字节。如果该offset参数小于文件本身的大小,多余的备份被截断;如果该offset参数大于文件本身的大小,文件末尾将会被填充空数据;
例如:
(1)、打开一份可读文件
//打开一份文件准备读取
NSFileHandle* fh = [NSFileHandle fileHandleForReadingAtPath:@"/Users/chenxiao/Desktop/重新学习的ios/重新学习的ios/NSFileHandleTest.m"];
NSData* data;
(2)、按指定的长度读取文件,文件指针会移动
//读取NSFileHandle中的128字节
while ([(data = [fh readDataOfLength:128]) length] > 0) {
NSLog(@"%ld",[data length]);
//直接将NSData的数据用UTF-8的格式转换字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",content);
}
(3)、关闭文件
[fh closeFile];
(4)、打开一份可写文件
//打开一份可以准备写入的文件
NSFileHandle* fh2 = [NSFileHandle fileHandleForWritingAtPath:@"/Users/chenxiao/Desktop/abc.txt”];
(5)、如果文件不存在,创建文件
if (!fh2) {
//创建一个NSFileManager对象
NSFileManager* fm = [NSFileManager defaultManager];
[fm createFileAtPath:@"/Users/chenxiao/Desktop/abc.txt" contents:nil attributes:nil];
fh2 = [NSFileHandle fileHandleForWritingAtPath:@"/Users/chenxiao/Desktop/abc.txt"];
}
(6)、将指定数据写入文件
NSString* myBook = @"疯狂iOS讲义";
[fh2 writeData:[myBook dataUsingEncoding:NSUTF8StringEncoding]];
(7)、关闭文件
[fh2 closeFile];
六、使用NSURL读取网络资源
URL(Uniform Resource Locator)对象代表同意资源定位器,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更复杂的对象引用,例如:对数据库或搜索引擎的查询。通常情况下,URL可以由协议名、主机、端口和资源路径组成,格式如下:
scheme://host:port/path
例如,如下的URL地址:
http://www.crazyit.org/index.php
例如:
(1)、创建NSURL对象
NSURL* url = [NSURL URLWithString:@"http://www.crazyit.org/index.php”];
(2)、获取NSURL对象的协议名
NSLog(@"url的协议名为:%@",[url scheme]);//url的协议名为:http
(3)、获取NSURL对象的主机
NSLog(@"url的主机为:%@",[url host]);//url的主机为:www.crazyit.org
(4)、获取NSURL对象的端口
NSLog(@"url的端口为:%@",[url port]);//url的端口为:(null)
(5)、获取NSURL对象的资源路径
NSLog(@"url的资源路径为:%@",[url path]);//url的资源路径为:/index.php
(6)、使用URL对应的资源来初始化NSString对象
//使用URL对应的资源来初始化NSString对象
NSString* homePage = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
//输出NSString内容,即可看到页面源代码
NSLog(@"%@",homePage);
七、使用NSBundle处理项目相关资源
得到NSBundle对象,接下来就可通过该对象的如下常用方法来获取指定的资源文件:
- (1)、- (NSURL )URLForResource:(NSString )name withExtension:(NSString )ext subdirectory:(NSString )subpath;根据资源名、扩展名从指定子目录中获取资源对应的URL;
- (2)、- (NSURL )URLForResource:(NSString )name withExtension:(NSString *)ext;根据资源名、扩展名获取资源对应的URL;
- (3)、- (NSArray )URLsForResourcesWithExtension:(NSString )ext subdirectory:(NSString *)subpath;根据指定子目录下匹配特定的扩展名的所有资源对应的URL组成的数组;
- (4)、- (NSString )pathForResource:(NSString )name ofType:(NSString *)ext;根据资源名、类型名获取资源对应的路径;
- (5)、 - (NSString )pathForResource:(NSString )name ofType:(NSString )ext inDirectory:(NSString )subpath;从指定的目录下,根据资源名、类型名获取该资源对应的路径;
- (6)、- (NSArray )pathsForResourcesOfType:(NSString )ext inDirectory:(NSString *)subpath;获取指定子目录下,匹配特定类型名所有资源对应的路径组成的数组;
- (7)、- resourcePath:直接根据完整的资源路径来获取对应的资源;
例如:
NSString* filePath = [[NSBundle mainBundle] pathForResource:@"bookinf" ofType:@"txt"];
//使用指定文件的内容来初始化NSString
NSString* content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"content = %@",content);
八、对象归档
归档就是用某种格式把一个或多个对象保存到指定文件中,方便以后从文件中恢复他们。通常来说,归档包含两方面的操作:
- (1)、需要把对象写入指定的文件中;
- (2)、需要从文件中恢复这些对象。
1、使用NSKeyedArchiver归档,NSKeyedUnarchiver解档
用法如下:
- (1)、对于NSArray、NSDictionary对象,直接调用NSKeyedArchiver的archivedDataWithRootObject:data、archiveRootObject:toFile:file类方法经指定对象作为root进行归档;恢复时,则调用NSKeyedUnarchiver的unarchiverObjectWithData:data或unarchiveObjectWithFile:file类方法。
- (2)、以NSMutableData对象作为参数,创建NSKeyedArchiver对象,接下来重复调用NSKeyedArchiver对象的encodeXxx:value forKey:key方法一次归档不同的对象,最后调用finishEncoding方法结束归档即可,接下来重复调用decodeXxxForKey:key方法一次恢复不同的对对象。
例如:
(1)、创建NSDictionary对象
//使用过个value、key的形式创建NSDictionary对象
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89],@"Objective-C",[NSNumber numberWithInt:69],@"Ruby",[NSNumber numberWithInt:75],@"Python",[NSNumber numberWithInt:109],@"Perl", nil];
(2)、获取一个路径
//获取路径
NSString *homePath = NSHomeDirectory();
NSString *path = [homePath stringByAppendingPathComponent:@"test.arc”];
(3)、归档
//对dict进行归档
[NSKeyedArchiver archiveRootObject:dict toFile:path];
(4)、解档
//解档
NSDictionary* dict1 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
//下面代码只是获取NSDictionary中的key-value数据
NSLog(@"Objective-C对应的value:%@",[dict1 valueForKey:@"Objective-C"]);//Objective-C对应的value:89
NSLog(@"Ruby对应的value:%@",[dict1 valueForKey:@"Ruby"]);//Ruby对应的value:69
NSLog(@"Python对应的value:%@",[dict1 valueForKey:@"Python"]);//Python对应的value:75
NSLog(@"Perl对应的value:%@",[dict1 valueForKey:@"Perl"]);//Perl对应的value:109
2、实现NSCoding协议
如果尝试使用NSKeyedArchiver将一个自定义的类对象归档到指定文件中,运行程序将会提示如下错误:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FKApple encodeWithCoder:]: unrecognized selector sent to instance 0x7faf62e46520'
*** First throw call stack:
从信息中可以看出,当程序使用NSKeyedArchiver归档一个自定义的FKApple对象时,系统会自动调用FKApple对象的encodeWithCoder:进行归档;当程序恢复一个自定义的实例时,系统会自动调用该对象的decodeWithCoder:方法进行恢复。所以,如果程序需要归档,恢复任意自定义的实例,那么该类应该实现NSCoding协议,实现该协议就必须实现该协议中定义的如下两个方法:
- initWithCoder::该方法负责恢复该对象。
- encodeWithCoder::该方法负责归档该对象。
例如:FKApple.h的实例部分
#import <Foundation/Foundation.h>
@interface FKApple : NSObject<NSCoding >
@property (nonatomic ,copy)NSString* color;
@property (nonatomic ,assign)double weight;
@property (nonatomic ,assign)int size;
- (id)initWithColor:(NSString *)color weight:(double)weight size:(int)size;
@end
FKApple.m的实现部分
#import "FKApple.h"
@implementation FKApple
- (id)initWithColor:(NSString *)color weight:(double)weight size:(int)size{
if (self = [super init]) {
self.color = color;
self.weight = weight;
self.size = size;
}
return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.color forKey:@"color"];
[aCoder encodeDouble:self.weight forKey:@"weight"];
[aCoder encodeInt:self.size forKey:@"size"];
}
//解档
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
//使用NSCoder依次恢复color、weight、size这3个key
//所对应的value,并将恢复的value赋给当前对象的3个实例变量
self.color = [aDecoder decodeObjectForKey:@"color"];
self.weight = [aDecoder decodeDoubleForKey:@"weight"];
self.size = [aDecoder decodeIntForKey:@"size"];
}
return self;
}
@end
在mian函数中的实现部分
//获取documents路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documents = [paths objectAtIndex:0];
NSString* path = [documents stringByAppendingPathComponent:@"apple.archiv"];
FKApple* apple = [[FKApple alloc]initWithColor:@"红色" weight:3.4 size:20];
//归档
[NSKeyedArchiver archiveRootObject:apple toFile:path];
//解档
FKApple* apple2 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
//获取对象的属性
NSLog(@"苹果的颜色为:%@",apple2.color);//苹果的颜色为:红色
NSLog(@"苹果的重量为:%g",apple2.weight);//苹果的重量为:3.4
NSLog(@"苹果的规格为:%d",apple2.size);//苹果的规格为:20
3、使用NSData完成自定义归档
如果程序需要一次性将多个对象归档到单个档案文件中,可按如下步骤进行:
- 以NSMutableData作为参数,创建NSKeyedArchive对象;
- 重复调用NSKeyedArchiver对象的encodeXxx:forKey:方法归档所有需要归档到一个文件中的对象;
- 调用NSKeyedArchiver对象的finishEncoding方法结束归档;
- 根据需要,程序可以选择将保存归档数据的NSData通过网络传输或输出到磁盘文件上;
例如:
//直接使用value、key的形式创建NSDictionary对象
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89],@"Objective-C",[NSNumber numberWithInt:69],@"Ruby",[NSNumber numberWithInt:75],@"Python",[NSNumber numberWithInt:109],@"Perl", nil];
//创建一个NSSet对象
NSSet* set = [NSSet setWithObjects:@"疯狂iOS讲义",@"疯狂Android讲义",@"疯狂Ajax讲义", nil];
//创建一个FKApple对象
FKApple* apple = [[FKApple alloc]initWithColor:@"红色" weight:3.4 size:20];
//创建一个NSMutableData对象,用于保存归档数据
NSMutableData* data = [NSMutableData data];
//以NSMutableData为参数,创建NSKeyedArchiver对象
NSKeyedArchiver* arch = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[arch encodeObject:dict forKey:@"myDict"];
[arch encodeObject:set forKey:@"set"];
[arch encodeObject:apple forKey:@"myApple"];
//结束归档
[arch finishEncoding];
//将程序NSData缓存区保存的数据写入文件
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documents = [paths objectAtIndex:0];
NSString* path = [documents stringByAppendingPathComponent:@"apple.archiv"];
NSLog(@"path = %@",path);
if ([data writeToFile:path atomically:YES] == NO) {
NSLog(@"归档失败");
}
- (1)、以NSData作为参数,创建NSKeyedUnarchiver对象。
- (2)、复制调用NSKeyedUnarchiver对象的decodeXxx:forKey:方法从一个文件中回复所有归档过的对象。
- (3)、调用NSKeyedUnarchiver对象的finishDecoding方法结束恢复。
NSData* data2 = [NSData dataWithContentsOfFile:path];
//以data2对象作为参数,创建NSKeyedUnichiver对象
NSKeyedUnarchiver* unarch = [[NSKeyedUnarchiver alloc]initForReadingWithData:data2];
//重复调用decodeObjectForKey:方法恢复所有需要恢复的对象
NSDictionary* dict2 = [unarch decodeObjectForKey:@"myDict"];
NSSet* set2 = [unarch decodeObjectForKey:@"set"];
FKApple* apple2 = [unarch decodeObjectForKey:@"myApple”];
//结束恢复
[unarch finishDecoding];
NSLog(@"dict2 = %@",dict2);
NSLog(@"set2 = %@",set2);
NSLog(@"apple2 = %@",apple2);
4、使用归档实现深复制
归档会将整个对象转换为字节数据——包括该对象的所有势力变量,如果该实例变量指向另一个Objecyive-C对象,归档时也会归档该实例变量所指向的Objective-C对象。这表明:当程序归档一个对象时,系统会把对象关联的所有数据都转为字节数据;如果程序从这些字节数据中恢复该对象,恢复出来的对象与原对象将完全相同,但没有任何共用的部分,这就是实现了深复制。