C文件操作
文件函数说明
此为基础篇文件操作,涉及基础使用函数:
fread、fwrite、fscanf、fprintf、remove、fseek、ftell、rewind、fgetpos、truncate、ftruncate等函数说明。
相关函数说明
fread
/*****************************
* 函数名称:fread
* 函数入口:
* ptr: 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
* size:要读取大大小
* nmemb:读取次数
* stream:文件流
* 函数出口:
* 成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
* 函数说明:
* 读取文件指定 size*nmemb 字节内容放到ptr中,并返回读取大小
* ***************************/
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
fwrite
/*****************************
* 函数名称:fwrite
* 函数入口:
* ptr: 这是指向要被写入的元素数组的指针。
* size:要写入大大小
* nmemb:写入次数
* stream:文件流
* 函数出口:
* 如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误。
* 函数说明:
* 将ptr写入到文件中 size*nmemb 字节内容,并返回读取大小
* ***************************/
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
fscanf
/*****************************
* 函数名称:fscanf
* 函数入口:
* format:这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符。
* stream:文件流
* 函数出口:
* 如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
* 函数说明:
* 从流 stream 读取格式化输入。具体与sscanf类似
* ***************************/
int fscanf(FILE *stream, const char *format, ...);
fprintf
/*****************************
* 函数名称:fprintf
* 函数入口:
* format:这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符。
* stream:文件流
* ...:参数
* 函数出口:
* 如果成功,则返回写入的字符总数,否则返回一个负数。
* 函数说明:
* 发送格式化输出到流 stream 中。
* ***************************/
int fprintf(FILE *stream, const char *format, ...);
remove
/*****************************
* 函数名称:remove
* 函数入口:
* pathname 文件名称
*
* 函数出口:
* 执行成功返回0,失败返回-1,错误代码保存在errno中。
* 函数说明:
* 删除指定文件
* ***************************/
int remove(const char *pathname);
fseek
/*****************************
* 函数名称:fseek
* 函数入口:
* stream:文件流
* offset: 这是相对 whence 的偏移量,以字节为单位。
* whence:相对位置(SEEK_SET(文件头)、SEEK_CUR(文件当前位置)、SEEK_END(文件末尾))
* 函数出口:
* 如果成功,则该函数返回零,否则返回非零值。
* 函数说明:
* 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。
* ***************************/
int fseek(FILE *stream, long int offset, int whence);
ftell
/*****************************
* 函数名称:ftell
* 函数入口:
* stream:文件流
* 函数出口:
* 该函数返回位置标识符的当前值。如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值。
* 函数说明:
* 返回给定流 stream 的当前文件位置。
* ***************************/
long int ftell(FILE *stream);
rewind
/*****************************
* 函数名称:rewind
* 函数入口:
* stream:文件流
* 函数出口:
* 该函数不返回任何值。
* 函数说明:
* 设置文件位置为给定流 stream 的文件的开头。
* ***************************/
void rewind(FILE *stream);
fgetpos
/*****************************
* 函数名称:fgetpos
* 函数入口:
* stream:文件流
* pos:这是指向 fpos_t 对象的指针,该对象包含了之前通过 fgetpos 获得的位置。
* 函数出口:
* 如果成功,该函数返回零值,否则返回非零值,并设置全局变量 errno 为一个正值,该值可通过 perror 来解释。
* 函数说明:
* 设置给定流 stream 的文件位置为给定的位置。参数 pos 是由函数 fgetpos 给定的位置。
* ***************************/
int fsetpos(FILE *stream, const fpos_t *pos);
truncate/ftruncate
#include <unistd.h>
#include <sys/types.h>
/*****************************
* 函数名称:truncate
* 函数入口:
* path 文件路径
* length 指定文件剩余大小
* 函数出口:
* 执行成功则返回0, 失败返回-1, 错误原因存于errno
* 函数说明:
* 截取指定原文件
* ***************************/
int truncate(const char *path, off_t length);
#include <unistd.h>
#include <sys/types.h>
/*****************************
* 函数名称:ftruncate
* 函数入口:
* fd 文件句柄
* length 指定文件剩余大小
* 函数出口:
* 执行成功则返回0, 失败返回-1, 错误原因存于errno
* 函数说明:
* 截取指定原文件
* ***************************/
int ftruncate(int fd, off_t length);
二者错误代码 errno
1 EACCESS 参数path所指定的文件无法存取
2 EROFS 欲写入的文件存在于只读文件系统内
3 EFAULT 参数path指针超出可存取空间
4 EINVAL 参数path包含不合法字符
5 ENAMETOOLONG 参数path太长
6 ENOTDIR 参数path路径并非一目录
7 EISDIR 参数path指向一目录
8 ETXTBUSY 参数path所指的文件为共享程序,而且正被执行中
9 ELOOP 参数path 有过多符号连接问题。
10 EIO I/O存取错误
示例代码
示例1:fread遇到\0将会停止向下读取?
#include "stdio.h"
#include "string.h"
int main(void)
{
FILE *fp;
int a=0;
int c=0;
int i=0;
int j=0;
char buf[]="$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,, NULL";
char buffer [1024];
fp = fopen("test.txt", "w+");
fwrite(buf,strlen(buf)+1,1,fp);//文档末尾写入加入\0
fclose(fp);
fp = fopen("test.txt", "a+");//在文件末尾续写
fputs("123456",fp);
fclose(fp);
fp = fopen("test.txt", "r");
while(1)//判断结束符逐个读取法
{
c=fgetc(fp);
if(feof(fp))
{
break;
}
a++;
fputc(c,stdout);
}
printf("\r\n");
printf("%d\r\n",a);
fclose(fp);
fp = fopen("test.txt", "r");//使用其他方法读取
fread(buffer,1024,1,fp);
// fputs(buffer,stdout);
while(1)
{
printf("%c",buffer[i++]);
if(i==(sizeof(buf)+strlen((char*)"123456"))+1)//最后一个字符未知字符验证fputs不会再末尾自动加\0
{
break;
}
}
printf("\r\n");
fclose(fp);
return(0);
}
运行结果:
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL123456
145
G P G G A , 092204.999 , 4250.5589 , S , 14718.5084 , E , 2 , 04 , 24.4 , 19.7 , M , , , , 0000 ∗ 1 F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000∗1FGPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M, NULL123456T
运行结果分析:
使用fgetc结合feof逐个读取将会读全,由于fputs不会再末尾添加字符串结束符\0,因此打印了未知字符“T”通过使用单个字符打印验证了fread读了全部字符,但是其中包括了字符串结束符,如果使用以下代码打印将会得到字符串结束符\0在NULL后
while(1)
{
printf("[%d]:%c\r\n",i++,buffer[i]);
if(i==(sizeof(buf)+strlen((char*)"123456"))+1)
{
break;
}
}
示例2:判断文件大小
#include "stdio.h"
#include "string.h"
int main(void)
{
char buf[]="$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,, NULL";
printf("string size:%ld--%ld\r\n",sizeof(buf),strlen(buf));//前者包括\0后者将不包括\0
FILE *fp=fopen("./test.txt","w+");
//fwrite(buf,strlen(buf)+1,1,fp);//此处向文件写入了\0文件大小与sizeof大小相同
fwrite(buf,strlen(buf),1,fp);//未写入\0文件大小与strlen大小相同
fseek(fp,0,SEEK_END);//将文件指针偏移到文件末
printf("file size:%ld\r\n",ftell(fp));
fclose(fp);
return(0);
}
运行结果:
写入方式1结果:
string size:139–138
file size:139
写入方式2结果:
string size:139–138
file size:138
运行结果分析:
使用fseek偏移与ftell结合可获取文件实际大小,同时文件属性中实际占用大小也是对应写入方式大小。
示例3:fscanf从标准输入流读入
#include "stdio.h"
int main(void)
{
/*********测试1:从标准输入流读出************/
int a=0,b=0;
char buf[1024]={0};
fscanf(stdin,"%d:%d:%s",&a,&b,buf);//必须按照对应的格式从标准输入流输入内容
printf("%d:%02d:%s\r\n",a,b,buf);
}
运行结果:
输入:2022:02:04
输出:2022:02:04
示例4:fscanf从标准输入流读入
#include "stdio.h"
#include "string.h"
int main(void)
{
char buf[]="Hello today is";
char buffer1[10]={0};
char buffer2[10]={0};
char buffer3[10]={0};
FILE *fp=fopen("./test.txt","w+");
fwrite(buf,strlen(buf)+1,1,fp);
rewind(fp);
fscanf(fp,"%s %s %s",buffer1,buffer2,buffer3);
printf("%ld--%s\r\n",strlen(buffer1),buffer1);
printf("%ld--%s\r\n",strlen(buffer2),buffer2);
printf("%ld--%s\r\n",strlen(buffer3),buffer3);
fclose(fp);
}
运行结果:
5–Hello
5–today
2–is
示例5:fscanf正则表达式测试
#include "stdio.h"
#include "string.h"
int main(void)
{
char buf[]="Hello,today is";
char buffer1[10]={0};
char buffer2[10]={0};
char buffer3[10]={0};
FILE *fp=fopen("./test.txt","w+");
fwrite(buf,strlen(buf)+1,1,fp);
rewind(fp);
fscanf(fp,"%[^,],%s %s",buffer1,buffer2,buffer3);
printf("%ld--%s\r\n",strlen(buffer1),buffer1);
printf("%ld--%s\r\n",strlen(buffer2),buffer2);
printf("%ld--%s\r\n",strlen(buffer3),buffer3);
fclose(fp);
}
运行结果:
5–Hello
5–today
2–is
示例6 fprintf使用
#include "stdio.h"
void mian(void)
{
char buffer1[10]="1987";
char buffer2[10]="10";
char buffer3[10]="10";
char strbuf[30]={0};
FILE *fp=fopen("./test.txt","w+");
fprintf(fp,"%s-%s-%s",buffer1,buffer2,buffer3);
rewind(fp);
fread(strbuf,strlen(buffer1)+strlen(buffer2)+strlen(buffer3)+3,1,fp);
puts(strbuf);
fclose(fp);
}
运行结果:
1987-10-10s
示例7 fgetpos及fsetpos使用
#include "stdio.h"
#include "string.h"
void main(void)
{
fpos_t postion;
char buffer1[10] = "1987";
char buffer2[10] = "10";
char buffer3[10] = "10";
char strbuf[30] = {0};
FILE *fp = fopen("./test.txt", "w+");
fgetpos(fp, &postion);//获取当前文件流的位置
printf("%ld\r\n", postion.__pos);
fprintf(fp, "%s-%s-%s", buffer1, buffer2, buffer3);
//postion.__pos=2;//可以结构体变量进行赋值再设置文件流的位置
fsetpos(fp,&postion);//设置文件流的位置
fread(strbuf, strlen(buffer1) + strlen(buffer2) + strlen(buffer3) + 3, 1, fp);
puts(strbuf);
fclose(fp);
}
运行结果:
0
1987-10-10
示例8 truncate使用
#include "stdio.h"
#include "string.h"
#include "unistd.h"
#include "sys/types.h"
void main(void)
{
int c=0;
char buf[]="$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,,0000*1F$GPGGA,092204.999,4250.5589,S,14718.5084,E,2,04,24.4,19.7,M,,,, NULL";
char buffer[512]={0};
FILE *fp = fopen("./test.txt", "wb+");
fputs(buf,fp);
fclose(fp);
int ret=truncate("./test.txt", 10);//将会截取文件前10字节后面将会被删除
printf("%d\r\n",ret);
perror("truncate");
fp = fopen("./test.txt", "r+");
while(1)
{
c=getc(fp);
if(feof(fp))
{
break;
}
printf("%c",c);
}
fclose(fp);
}
运行结果:
0
truncate: Success
$GPGGA,092