在 c 语言中,文件操作都是由库函数来实现的,主要是分为读和写两种操作:
文件指针
平常所说的文件不同于其他常见的数据类型,比如一个test.txt文档,它有自己的一些属性,比如文件的当前位置、与该文件对应的内存缓冲区地址、文件操作方式等等。对于这些信息都会专门开辟一定内存空间来存储。而且是保存在一个结构体类型的变量中,比如:
struct
{
int fd; //文件号
int cleft; //缓冲区中剩下的字符
int mode; //文件操作模式
char *nextc; //下一个字符位置
char *buff; //文件缓冲区位置
}FILE;
/*FILE是一个存储文件信息的结构体类型的变量*/
在上述代码中可以看到,文件号、文件操作模式等信息都存储在一个结构体中。
对磁盘文件的操作必须是先打开,然后读写操作,最后关闭。
打开文件
函数原型
FILE * fopen(const char * path,const char * mode);
path:需要打开的文件路径mode:文件打开方式
返回值:文件顺利打开后,返回指向该流的文件指针。如果文件打开失败则返回NULL,并把错误代码存在errno中。(errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义)
其中文件打开方式主要有一下几种:
关闭文件
函数原型:
int fclose( FILE *fp );
返回值:如果流成功关闭,fclose 返回 0,否则返回EOF(-1)。(如果流为NULL,而且程序可以继续执行,fclose设定error number给EINVAL,并返回EOF。)
读写文件
常用的文件读写函数主要有:
字符读写函数:fgetc() 和 fputc (getc 和 putc)
字符串读写函数:fgets() 和 fputs()
数据块读写函数:fread() 和 fwrite()
格式化读写函数:fscanf() 和 fprintf()
fread()
函数原型
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
功能:
从一个文件流中读数据,最多读取count个元素,每个元素size字节,如果调用成功返回实际读取到的元素个数,如果不成功或读到文件末尾返回 0。
buffer:用于接收数据的内存地址。
size:要读的每个数据项的字节数,单位是字节(byte)。
count:要读count个数据项,每个数据项size个字节。
stream:文件输入流
返回值:实际读取的元素个数。如果返回值与count不相同,则可能文件结尾或发生错误。从ferror和feof获取错误信息或检测是否到达文件结尾。
fwrite()
函数原型
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
功能:向文件写入一个数据块(注意:这个函数以二进制形式对文件进行操作,不局限于文本文件)。
buffer:是一个指针,对fwrite来说,是要获取数据的地址(即数据来源地址)。
size:要写入内容的单字节数。
count:要进行写入size字节的数据项的个数。
stream:目标文件指针。
返回值:返回实际写入的数据块数目。
fseek()
函数原型
int fseek(FILE *stream, long offset, int fromwhere);
功能
:重定位流(数据流/文件)上的文件内部位置指针(即:
可以移动文件的读写指针到指定的位置,即移动当前文件的位置指针
)。
如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
stream:文件指针。
offset:偏移量。
fromwhere
:指针的起始位置,为下列其中一种
* SEEK_SET:从距离文件开头 offset 位移量为新的读写位置;
* SEEK_CUR :以目前的读写位置往后增加 offset 个位移量;
* SEEK_END :将读写位置指向文件末尾后再增加 offset 个位移量。
ftell()
函数原型
long ftell(FILE *stream);
功能:用于获取文件位置指针当前位置相对于文件首的偏移字节数。(使用fseek()后再调用函数ftell()就能非常容易地确定文件的当前位置。)
strem:文件指针。(注意:文件指针必须是有效的,且必须指向一个通过 fopen() 或 popen() 成功打开的文件。在附加模式(加参数 "a" 打开文件)中 ftell() 会返回未定义错误。)
返回值:
handle
指定的文件指针的位置,也就是文件流中的偏移量。如果出错,返回 FALSE。
约束:因为ftell返回long型,根据long型的取值范围-231~231-1(-2147483648~2147483647),故对大于2.1G的文件进行操作时出错。
改变文件大小
ftruncate()
函数原型
int ftruncate(int fd,off_t length);
功能:将参数fd指定的文件大小改为参数length指定的大小。
fd:为已打开的文件描述词,而且必须是以写入模式打开的文件。
length:要改成的大小,如果原来的文件大小比参数length大,则超过的部分会被删去。
返回值:执行成功则返回0,失败返回-1,错误原因存于errno。
错误代码:
EBADF 参数fd文件描述词为无效的或该文件已关闭。
EINVAL 参数fd 为一socket 并非文件,或是该文件并非以写入模式打开。
说明:fd一般可以fileno(FILE *fp)获取,标示文件当前的大小,lenggth则可由用户定义。此函数一般用在文件初始化或者重新为文件分配空间时。
fileno()
函数原型
int _fileno( FILE *stream );
功能:用来取得参数stream指定的文件流所使用的文件描述符。
stream:文件输入流。
返回值:某个数据流的文件描述符。
下面简单讲一下在iOS 下,对NSData 的文件读写:
读文件
/*
* === FUNCTION ==================================================
* Name: readDataToBuffer:fromPath:
* Description: 从指定 path 的文件读取内容到 buffer
* =================================================================
*/
-(void)readDataToBuffer:(char *)buffer fromPath:(NSString *)path
{
FILE *p_r= fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "r"); //打开文件
if (NULL == p_r)
{
NSLog(@"Open file error to read data !");
return ;
}
fseek(p_r, 0, SEEK_END); //定位到文件末尾
NSInteger dataLength = ftell(p_r); //获取文件长度
fseek(p_r, 0, SEEK_SET); //定位到文件起始位置
fread(buffer, dataLength, 1, p_r); //读取文件到指定的缓冲区
fclose(p_r); //关闭文件
}
写文件
/*
* === FUNCTION ==================================================
* Name: writeData:toPath:
* Description: 把数据写到指定的文件中
* =================================================================
*/
-(void)writeData:(NSData *)data toPath:(NSString *)path
{
FILE *p_w= fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "ab"); //已追加二进制方式打开文件
if (NULL == p_w)
{
NSLog(@"Open file error to write data!");
return ;
}
fseek(p_w, 0, SEEK_END); // 移到文件末尾
fwrite((void *)[data bytes], data.length, 1, p_w); // 写入数据
data = nil;
fclose(p_w); //关闭文件
}
此博文源自 http://blog.csdn.net/shenyuanluo/article/details/48003531
如需转载,请说明博文出处。谢谢!