利用 文件操作柄,也就是 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
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
|
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSFileHandle.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSData.h>
int
main
(
int
argc
,
const
char
*argv
[
]
)
{
NSAutoreleasePool
*pool
=
[
[
NSAutoreleasePool
alloc
]
init
]
;
NSFileHandle
*inFile
,
*outFile
;
NSData
*buffer
;
//为文件testfile创建文件操作柄,以便读取数据
inFile
=
[
NSFileHandle
fileHandleForReadingAtPath
:
@"testfile"
]
;
if
(
inFile
==
nil
)
{
NSLog
(
@"打开文件失败!"
)
;
return
1
;
}
//创建文件testfile2
[
[
NSFileManager
defaultManager
]
createFileAtPath
:
@"testfile2"
contents
:
nil
attributes
:
nil
]
;
//为文件testfile2创建文件操作柄,以便写入数据
outFile
=
[
NSFileHandle
fileHandleForWritingAtPath
:
@"testfile2"
]
;
if
(
outFile
==
nil
)
{
NSLog
(
@"打开文件失败!"
)
;
return
2
;
}
//将文件testfile2的长度剪短为0
[
outFile
truncateFileAtOffset
:
0
]
;
//将文件testfile中的数据读取到缓冲区buffer当中
buffer
=
[
inFile
readDataToEndOfFile
]
;
//将缓冲区buffer中的数据写入到文件testfile2当中
[
outFile
writeData
:
buffer
]
;
//将两个文件关闭
[
inFile
closeFile
]
;
[
outFile
closeFile
]
;
//将testfile2的内容显示出来,用以验证之前的操作是否成功
NSLog
(
@"%@"
,
[
NSString
stringWithContentsOfFile
:
@"testfile2"
encoding
:
NSUTF8StringEncoding
error
:
nil
]
)
;
[
pool
drain
]
;
return
0
;
}
|
运行 这个程序过后,可以得到 这样的结果:
|
2012-05-18 15:51:06.184 Sample[1507:707] 编程很有趣!
Program ended with exit code: 0
|
readDataToEndOfFile:这项措施 可以读取 长达1099511627542字节的数据。这 对于你所编写的任何程序来说 都足够大了。你 可以设定 一个循环 利用 缓冲区 在文件之间 传输 数据,这个 可以通过readDataOfLength:这项措施 办到。缓冲区的大小 可以是 8192字节 或者 131072字节,因为 底层的操作系统 一般 以这种大小的数据块 执行 输入/输出操作。
如果 一项措施 直到文件末尾处 都没有读取到 任何数据,那么 这项措施 会产生出 一个空的NSData类型的物件。你 可以对 这个NSData类型的物件 采取 length这项措施 从而 检查 是否 从文件中 读取到 任何数据。
如果 你 打开 一个文件 进行 读、写,那么 文件的操作位置 会被设定 在文件的开头处。你 可以将 文件操作位置 设定为 其它位置,再 进行 读、写操作,比如 将 文件的操作位置 设定 在第10个字节处,就可以这样:
|
[
myFileHandle
seekToFileOffset
:
10
]
;
|
先获取 当前的文件操作位置,然后再 对 这个文件操作位置 加上 或者 减去 一定的字节数,我们 就可以得到 一个相对的文件操作位置。比如,在当前文件操作位置的基础上 向前 跳过 128字节,可以这样:
|
[
myFileHandle
seekToFileOffset
:
[
myFileHandle
offsetInFile
]
+
128
]
;
|
如果 要将 当前文件操作位置 向回 移动 5个整数值的长度,那么 我们 可以利用 这样的语句:
|
[
myFileHandle
seekToFileOffset
:
[
myFileHandle
offsetInFile
]
-
5
*sizeof
(
int
)
]
;
|