创建一个文件指针
FILE *fp=fopen(“文件路径”,“打开模式”);
其中打开模式有:
r (read): 只读
w (write): 只写
a (append): 追加
t (text): 文本文件(默认),可省略不写
b (binary):二进制文件
+: 读和写
读取文件(read)
fread()
声明:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
参数:
ptr : 指向带有最小尺寸 size*nmemb 字节的内存块的指针。用来指定读取的文件数据存放的区域
size :要读取的每个数据块的大小,以字节为单位。
nmemb : 数据块的个数,每个数据块的大小为 size 字节。
stream – 这是指向 FILE 对象的指针,该 FILE对象指定了一个输入流。
这里附上使用fread函数读取二进制文件的代码
inline size_t readBinaryFile(const char * filename,unsigned char * data)
{
FILE* fp;
fopen_s(&fp,filename, "rb");
if (fp == NULL) return 0; //空指针则返回0,文件打开失败
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp); //计算文件大小,单位:Byte
fseek(fp, 0, SEEK_SET);
data = (unsigned char *)malloc(sizeof(unsigned char)*size);
fread(data,size,1,fp);
fclose(fp);
return size;
}
这里利用fseek函数将文件指针指向文件末尾,再用ftell函数来获取文件大小size
该函数返回值为读取的文件的大小,单位是byte(字节)
注意如果读取的不是二进制文件而是文本文件,那么应在data数组的末尾补上:
data[size] = '\0';
否则输出文本内容的时候没有字符串结束符将会引发错误。
上述函数还有一个潜在的问题,如果读取的文件大小超过了size_t
的表示范围(也就是data数组的长度超过了系统允许的最大数组长度),就应先将文件数据划分为几段,分别读入不同的数组。
关于size_t
的作用,可以参考这篇文章:为什么size_t重要?(Why size_t matters)
简言之,size_t表示的数据范围是当前平台地址总线的宽度,也就是你所能声明的最大数组长度
fwrite()
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
ptr – 指向要被写入的元素数组的指针。
size – 被写入的每个数据块的大小,以Byte(字节)为单位。
nmemb – 将要写入的数据块的个数,每个数据块的大小为 size 字节。
stream – 指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。
下面同样给出了一个fwrite进行二进制写入的函数。
inline size_t writeBinaryFile(const char* filename, unsigned char* data, size_t size) //size:要写入的数据大小(单位:字节)
{
FILE* fp;
fopen_s(&fp,filename, "wb");
if (fp == NULL) return 0;
size_t written_size= fwrite(data, size, 1 ,fp);
fclose(fp);
return written_size;
}
fscanf()
声明:
int fscanf(FILE *stream, const char *format, …)
参数:
stream : 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
format : 这是 C
字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符。 format 说明符形式为
[=%[*][width][modifiers]type=],以下是百度百科的描述:
参数 | 描述 |
---|---|
* | 这是一个可选的星号,表示数据是从流 stream 中读取的,但是可以被忽视,即它不存储在对应的参数中。 |
width | 这指定了在当前读取操作中读取的最大字符数。 |
modifiers | 为对应的附加参数所指向的数据指定一个不同于整型(针对 d、i 和 n)、无符号整型(针对 o、u 和 x)或浮点型(针对 e、f 和 g)的大小: h :短整型(针对 d、i 和 n),或无符号短整型(针对 o、u 和 x) l :长整型(针对 d、i 和 n),或无符号长整型(针对 o、u 和 x),或双精度型(针对 e、f 和 g) L :长双精度型(针对 e、f 和 g) |
type | 一个字符,指定了要被读取的数据类型以及数据读取方式。具体参见下一个表格。 |
可以把 fscanf 看成是自行设定文件流的 scanf 函数
比如下面两条语句的效果是完全一致的:
fscanf(stdin,"%d",&n);
scanf("%d",&n);
通过重定向标准输入/输出实现文件读写:
freopen()
FILE * freopen ( const char * filename, const char * mode, FILE * stream );
比如现在我们需要在data.in中读取数据,在data.out中写入数据:
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
然后使用scanf,printf等原本从控制台读取和输出的函数时,都会被重定向到指定文件中
最后别忘了关闭文件流:
fclose(stdin);
fclose(stdout);