平时用Qt的QFile用的习惯了,发现其实连C语言的文件操作函数都不熟悉,专门用C++写了个通讯录的命令行程序练手,总结一下用到的几个函数,使用这几个函数需要#include <stdio.h>
。
fopen和fclose函数
系统需要在内存中为每个读写的文件开辟一段缓存,缓存中保存文件信息的是FILE结构体,打开文件时就会获得指向FILE的指针。为什么要用缓存呢,因为硬盘读取时很慢的,机械硬盘的读写时间都是毫秒级,而内存读写是纳秒级的,差了一百万倍。
函数原型为fopen(const char* filePath, const char* mode)
和fclose(FILE* file)
。文件打开成功后,会返回指向流的文件指针,如果打开失败则返回NULL,最后一定要用fclose关闭文件。一般是这样使用:
FILE* file = fopen("file.dat","r");
if(file==NULL)
std::cout<<"读取文件失败!"<<endl;
......
fclose(file);
常用的mode有以下几种:
r是只读模式,文件必须存在
r+是可读写模式,文件必须存在
w是只写模式,文件若存在则清空重新写,若不存在则创建文件再写。
w+是可读写模式,文件若存在则清空重新写,若不存在则创建文件再写。
a是以附加方式打开只写文件,若文件不存在则创建文件,若存在则数据添加到文件尾部,原内容保留。
wb是用只写方式打开一个二进制文件,只允许写数据
wt是用只写方式打开一个文本文件,只允许写数据
还可以进行组合模式,例如at+,ab+,wb+
等等。
fread函数
用于读取文件流,原型为size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
。
buffer 是读取的数据存放的内存的指针(可以是数组,也可以是新开辟的空间,buffer就是一个索引)
size 是每次读取的字节数
count 是读取次数
strean 是要读取的文件的指针
一般这样使用,在fopen
打开文件后,读取文件:
FILE* fr = fopen("F:/list.dat","r");
char buff[50]; //定义缓冲区
while(!feof(file))
{
memset(buff,0,sizeof(buff)); // 清空缓冲区
fread(buff,sizeof(char),sizeof(buff),file); //单字节读取
cout<<buff;
}
fclose(fr);
feof函数的原型:int feof(FILE * stream);
,用来检测文件流的位置,判断是否读到了文件结尾。检测到文件结束标识返回1,否则返回0。
feof()与EOF
不同:feof()是函数,用来检测文件的结束;EOF是 End Of File 的缩写,是C语言中标准库中定义的宏,定义为:#define EOF (-1)
程序连续读取file中的50个字符,文件指针会跟着移动,最终会根据文件结束符而停止。目前的问题是 读文件时总是出现大量乱码 ,只有读取用fwrite
写的文件才正常。
fwrite函数
函数原型为size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
。
一般这样使用:
FILE* fa = fopen("F:/list.dat","a+"); //追加式写入
const char* j = "hello world";
fwrite(j,5,1,fa);
向文件追加写入字符串,但只写入前五个,也就是hello
。
fseek函数
函数原型:int fseek(FILE *stream, long offset, int fromwhere);
,用于重定位流数据流的内部指针。
stream:指向打开的文件指针。
offset:以基准点为起始点的偏移量。
fromwhere:基准点,包括`SEEK_SET 文件头`,`SEEK_CUR 当前位置`,`SEEK_END 文件件尾`。
成功,返回0;失败返回-1。
常见用法:
fseek(fp, 100L, SEEK_SET);把stream指针移动到离文件开头100字节处;
fseek(fp, 100L, SEEK_CUR);把stream指针移动到离文件当前位置字节处;
fseek(fp, -100L, SEEK_END);把stream指针移动到离文件尾100字节处;
fgets函数
函数原型char* fgets(char * s, int n,FILE *stream);
s: 字符型指针,指向存储读入数据的缓冲区的地址
n: 从流中读入n-1个字符
stream:指向读取的流
如果读入成功,则返回缓冲区的地址;如果读入错误或遇到文件结尾(EOF),则返回NULL。用fgets读入数据时,先定义一个字符数组或字符指针。一般是这样使用:
FILE* fr = fopen("b.cpp","r");
char s[50];
while(fgets(s,50,fr)!=NULL)
{
cout<<s;
}
第二个参数可以用较小的值,例如文本内容是1234567890
时,如果第二个参数>=11,只需要读一次,否则需要读多次。fgets若没遇到换行符,会接着从前一次的位置继续读入n-1个字符,只要是文本流没关闭。
这个函数用于 读汉字文本时会出现乱码 ,读英文正常。
补充内容
Linux下没有itoa函数,只有atoi
,因为itoa
不是C标准库函数,而是扩展的非标准函数,因编译器而不同,gcc编译器不支持这个函数。
可以用这样的替代方法:
int num = 1234567890;
char s[11];
sprintf(s,"%d",num);
cout<<"conversion:"<<s<<endl;