利用 文件操作柄,也就是 NSFileHandle这类物件,我们 可以更加近距离地 操作 文件。一般来说,操作 文件 需要 下面三个步骤:
- 打开 文件,为 这个文件 创建 文件操作柄;
- 进行 输入/输出操作;
- 关闭 文件。
下面的表格 总结了 可以对文件操作柄所采取的措施:
措施名称 | 描述 |
+(NSFileHandle *)fileHandleForReadingAtPath:path | 打开文件以便读取 |
+(NSFileHandle *)fileHandleForWritingAtPath:path | 打开文件以便写入 |
+(NSFileHandle *)fileHandleForUpdatingAtPath:path | 打开文件以便读写 |
-(NSData *)availableData | 产生的结果为其实施对象中可用的数据 |
-(NSData *)readDataToEndOfFile | 读取文件末尾处之前的数据 |
-(NSData *)readDataOfLength:(NSUInteger)bytes | 读取长度为bytes字节的数据 |
-(void)writeData:data | 将数据data写入文件 |
-(unsigned long long)offsetInFile | 获取当前文件中的操作位置 |
-(void)seekToFileOffset:offset | 将当前文件的操作位置设定为offset |
-(unsigned long long)seekToEndOfFile | 将当前文件的操作位置设定为文件的末尾处 |
-(void)truncateFileAtOffset:offset | 将文件的长度设定为offset |
-(void)closeFile | 关闭文件 |
你 应该注意:利用 文件操作柄 并不能创建 文件。创建 文件 只能利用 文件管理器,也就是 NSFileManager这类物件。所以 向 NSFileHandle这类物件 发送 fileHandleForWritingAtPath: 和 fileHandleForUpdatingAtPath:这两条消息的前提 是 文件 必须存在,如果 文件 并不存在,那么 NSFileHandle这类物件 就会产生出 空值nil。在这两种情况之下,文件的操作位置 都被设定 在文件的开头处。另外 如果 你 习惯于 在UNIX之下编程,你 应该注意到 打开文件 并不能 将 这个文件 剪短。你 得自己 将 文件 剪短。
下面的程序 示范了 如何利用 文件操作柄 来操作 文件:
1 #import <Foundation/NSObject.h> 2 #import <Foundation/NSString.h> 3 #import <Foundation/NSFileHandle.h> 4 #import <Foundation/NSFileManager.h> 5 #import <Foundation/NSAutoreleasePool.h> 6 #import <Foundation/NSData.h> 7 int main(int argc,const char *argv[]) 8 { 9 NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; 10 NSFileHandle *inFile,*outFile; 11 NSData *buffer; 12 //为文件testfile创建文件操作柄,以便读取数据 13 inFile=[NSFileHandle fileHandleForReadingAtPath:@"testfile"]; 14 if(inFile==nil) 15 { 16 NSLog(@"打开文件失败!"); 17 return 1; 18 } 19 //创建文件testfile2 20 [[NSFileManager defaultManager] createFileAtPath:@"testfile2" contents:nil attributes:nil]; 21 //为文件testfile2创建文件操作柄,以便写入数据 22 outFile=[NSFileHandle fileHandleForWritingAtPath:@"testfile2"]; 23 if(outFile==nil) 24 { 25 NSLog(@"打开文件失败!"); 26 return 2; 27 } 28 //将文件testfile2的长度剪短为0 29 [outFile truncateFileAtOffset:0]; 30 //将文件testfile中的数据读取到缓冲区buffer当中 31 buffer=[inFile readDataToEndOfFile]; 32 //将缓冲区buffer中的数据写入到文件testfile2当中 33 [outFile writeData:buffer]; 34 //将两个文件关闭 35 [inFile closeFile]; 36 [outFile closeFile]; 37 //将testfile2的内容显示出来,用以验证之前的操作是否成功 38 NSLog(@"%@",[NSString stringWithContentsOfFile:@"testfile2" encoding:NSUTF8StringEncoding error:nil]); 39 [pool drain]; 40 return 0; 41 }
运行 这个程序过后,可以得到 这样的结果:
1 2012-05-18 15:51:06.184 Sample[1507:707] 编程很有趣! 2 Program ended with exit code: 0
readDataToEndOfFile:这项措施 可以读取 长达1099511627542字节的数据。这 对于你所编写的任何程序来说 都足够大了。你 可以设定 一个循环 利用 缓冲区 在文件之间 传输 数据,这个 可以通过readDataOfLength:这项措施 办到。缓冲区的大小 可以是 8192字节 或者 131072字节,因为 底层的操作系统 一般 以这种大小的数据块 执行 输入/输出操作。
如果 一项措施 直到文件末尾处 都没有读取到 任何数据,那么 这项措施 会产生出 一个空的NSData类型的物件。你 可以对 这个NSData类型的物件 采取 length这项措施 从而 检查 是否 从文件中 读取到 任何数据。
如果 你 打开 一个文件 进行 读、写,那么 文件的操作位置 会被设定 在文件的开头处。你 可以将 文件操作位置 设定为 其它位置,再 进行 读、写操作,比如 将 文件的操作位置 设定 在第10个字节处,就可以这样:
1 [myFileHandle seekToFileOffset:10];
先获取 当前的文件操作位置,然后再 对 这个文件操作位置 加上 或者 减去 一定的字节数,我们 就可以得到 一个相对的文件操作位置。比如,在当前文件操作位置的基础上 向前 跳过 128字节,可以这样:
1 [myFileHandleseekToFileOffset:[myFileHandleoffsetInFile]+128];
如果 要将 当前文件操作位置 向回 移动 5个整数值的长度,那么 我们 可以利用 这样的语句:
1 [myFileHandleseekToFileOffset:[myFileHandleoffsetInFile]-5*sizeof(int)];
(转)文件操作-文件操作柄,NSFileHandle