4.C语言文件操作
总论
1.fopen
r以只读方式打开文件,该文件必须存在
r+以可读写方式打开文件,文件必须存在
rb+读写打开一个二进制文件,允许读写数据,文件必须存在
rw+读写打开一个文本文件,允许读和写
w 打开只写文件,若文件存在则文件长度清零,即该文件内容会消失,若文件不存在则建立该文件
w+打开可读文件,若文件存在则文件长度清为零,即该文件内容会消失,若文件不存在则建立该文件
a 以附加的方式打开只写文件.若文件不存在,则会建立该文件,如果存在,数据会被加到文件尾,即文件原先的内容会被保留(EOF符不保留)
a+以附加的方式打开可读写的文件.若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留.(原来的EOF符不保留)
- 1.文件基础操作
1.1 打开文件示例
#include <stdio.h> int main()
{
FILE *p = fopen("a.txt","w");//用写的方式打开一个文件
fputs("hello",p);//向文件写入一个字符串
fclose(p);//关闭这个文件
printf("Hello World!\n");
return ;
}
QT w方式打开文件
执行完再执行一遍的时候,文件内容消失,是新的内容
#include <stdio.h>
#include<string.h>; int main()
{
char s[] = {};
FILE *p = fopen("a.txt","w");//用写的方式打开一个文件
while()
{
memset(s,,sizeof(s));
//scanf("%s",s);
gets(s);
if(strcmp(s,"exit")==)
break;
int len = strlen(s);
s[len] = '\n';
fputs(s,p);
}
printf("Hello World!\n");
return ;
}
一个写文件实例
1.2.读文件示例
用fgets函数
int main()
{
char s[] = {};
FILE *p = fopen("a.txt","r");//用读方式打开文件
//feof(p);//如果已经到了文件最后,函数返回真
while(!feof(p))
{
memset(s,,sizeof(s));
fgets(s,sizeof(s),p);//第一个参数是一个内存地址;第二个参数是这块内存的大小;
//第三个参数是fopen返回的指针
//每次读一行
printf("%s",s);
} fclose(p);
return ;
}
读函数实例
1.3.文件加密
void code(char *s)
{
while(*s)//遍历一个字符串
{
(*s)++;
s++;
}
} void decode(char *s)
{
while(*s)
{
(*s)--;
s++;
}
} int main1()//加密
{
char s[] = {};
FILE *p = fopen("a.txt","r");//用读方式打开文件
FILE *p1 = fopen("b.txt","w");//用写的方式打开一个文件
//feof(p);//如果已经到了文件最后,函数返回真
while(!feof(p))
{
memset(s,,sizeof(s));
fgets(s,sizeof(s),p);//第一个参数是一个内存地址;第二个参数是这块内存的大小;
//第三个参数是fopen返回的指针
//每次读一行
code(s);
fputs(s,p1);
} fclose(p);
fclose(p1);
return ;
} int main()//解密
{
char s[] = {};
FILE *p = fopen("b.txt","r");//用读方式打开文件
FILE *p1 = fopen("c.txt","w");//用写的方式打开一个文件
//feof(p);//如果已经到了文件最后,函数返回真
while(!feof(p))
{
memset(s,,sizeof(s));
fgets(s,sizeof(s),p);//第一个参数是一个内存地址;第二个参数是这块内存的大小;
//第三个参数是fopen返回的指针
//每次读一行
decode(s);
fputs(s,p1);
} fclose(p);
fclose(p1);
return ;
}
简单文件加密解密
1.4.文本文件排序(使用冒泡排序)
void swap(int *a,int *b)//交换参数的值
{
int tmp = *a;
*a = *b;
*b = tmp;
} void pupple(int *p,int n)//冒泡排序
{
int i;
int j;
for(i=;i<n;i++)
{
for(j=;j<n-i;j++)
{
if(p[j-]>p[j])
{
swap(&p[j-],&p[j]);
}
}
}
} int main()
{
int index = ; //这是个计数器
int array[] = {}; char buf[]; FILE *p = fopen("1.txt","r");
if(p==NULL)
{
printf("error\n");
}
else
{ while(!feof(p))//如果没有到达文件结尾,那么循环继续
{
memset(buf,,sizeof(buf));//每次去文件之前都把这个buffer清空
fgets(buf,sizeof(buf),p);//从文件中读取一行
array[index] = atoi(buf);//将读取的一行转化为int,赋值给数组成员
index++;
} fclose(p);
} pupple(array,index);//将数组排序 p = fopen("2.txt","w");//用写的方式打开2.txt
int i=;
for(i=;i<index;i++)
{
memset(buf,,sizeof(buf));//每次操作之前都把buf清空
sprintf(buf,"%d\n",array[i]);//将数组的成员转化为字符串
fputs(buf,p);
} fclose(p); return ;
}
文本文件排序
但是这样做的缺点是在栈中分配内存,很容易造成栈溢出,所以我们对main函数进行改进,动态分配数组
int main()//在堆中建立一个数组
{
int index = ; //这是个计数器 FILE *p = fopen("1.txt","r");//第一次打开a.txt目的是要知道这个文件有多少行
while(!feof(p))//如果没有到达文件结尾,那么循环继续
{
index++;
}
fclose(p); int *array = calloc(sizeof(int),index);//在堆中建立一个动态数组 char buf[];
p = fopen("1.txt","r");
index = ;//计数器重新从0开始
if(p==NULL)
{
printf("error\n");
}
else
{ while(!feof(p))//如果没有到达文件结尾,那么循环继续
{
memset(buf,,sizeof(buf));//每次去文件之前都把这个buffer清空
fgets(buf,sizeof(buf),p);//从文件中读取一行
array[index] = atoi(buf);//将读取的一行转化为int,赋值给数组成员
index++;
} fclose(p);
} pupple(array,index);//将数组排序 p = fopen("2.txt","w");//用写的方式打开2.txt
int i=;
for(i=;i<index;i++)
{
memset(buf,,sizeof(buf));//每次操作之前都把buf清空
sprintf(buf,"%d\n",array[i]);//将数组的成员转化为字符串
fputs(buf,p);
} fclose(p); return ;
}
main函数改进,动态分配内存
1.5.解析文本内容,计算文本中的加减乘除
#include <stdio.h>
#include <string.h> int calc_string(const char *s)
{
char buf1[] = {};
char oper1 = ;
char buf2[] = {}; int len = strlen(s);
int i;
for(i=;i<len;i++)
{
if(s[i]=='+' || s[i]=='-' ||s[i]=='*' ||s[i]=='/')
{
strncpy(buf1,s,i);
oper1 = s[i];
break;
}
} int start=i+;
for(;i<len;i++)
{
if(s[i]=='=')
{
strncpy(buf2,&s[start],i-start);
}
} switch(oper1)
{
case '+':
return atoi(buf1) + atoi(buf2);
case '-':
return atoi(buf1) - atoi(buf2);
case '*':
return atoi(buf1) * atoi(buf2);
case '/':
{
int a=atoi(buf2);
if(a)
return atoi(buf1)/atoi(buf2);
else
return ;
} }
} void cutereturn(char *s)//去掉最后最后的回车符
{
int len = strlen(s);
if(s[len-]=='\n')
s[len-]=;
} int main()
{
FILE *p = fopen("calc.txt","r");
FILE *p1 = fopen("res.txt","w");
char buf[];
char buf1[]; if(p)
{
while (!feof(p))
{
memset(buf,,sizeof(buf));
fgets(buf,sizeof(buf),p);//从文件中读取一行记录,字符串最后是一'\'结尾
cutereturn(buf); int value = calc_string(buf);
memset(buf1,,sizeof(buf1));
sprintf(buf1,"%s%d\n",buf,value);
fputs(buf1,p1);
}
} return ;
}
1.6 fscanf与fprintf的用法
int main1()//fsancf
{
FILE *p = fopen("calc.txt","r");
while(!feof(p))
{
char buf[] = {};
//fgets(buf,sizeof(buf),p);
//fscanf(p,"%s",buf);//fscanf与scanf用法基本一致,fscanf是从一个文本读取输入,scanf是从键盘读取输入
int a;
int b;
fscanf(p,"%d+%d",&a,&b);
printf("a=%d,b=%d",a,b);
}
} void main()//fprintf
{
FILE *p =fopen("1.txt","w"); char buf[]="hello world";
int a = ;
int b = ;
fprintf(p,"%s,%d,%d",buf,a,b);//和printf功能一样,fprintf将输入到文件里面
fclose(p);
return ;
}
fscanf与fprintf
- 二进制文本操作
2.1 二进制读取和文本读取的区别
对于传统的windows下的文件是以/r/n作为文件换行,如果是用fgets()或用fputs()函数,会做一个自动的转换,把/r/n转换成/n,写入的时候又转换成/r/n,而如果采用二进制读取的话用fread,不会做转化,/r/n会分开读取.fread不会按照一行一行来操作,而是按照一个整体来操作
void main(void)
{
FILE *p = fopen("calc.txt","rb");//用读二进制的文件的方式打开一个文件
char buf[]={};
fread(buf,sizeof(char),sizeof(buf),p);//第一个参数是缓冲区,第二个参数是读取的时候最小单位大小,
//第三个参数是一次读取多少个单位,第四个是文件指针 printf("%s\n",buf);
return ;
}
fread
int main()
{
FILE *p = fopen("1.txt","wb");
char buf[]={};
buf[]='a';
buf[]='b';
buf[]='\r';
buf[]='\n';
buf[]='c';
fwrite(buf,sizeof(char),,p);
fclose(p);
}
fwrite
2.2二进制文件拷贝
int main()
{
FILE *p = fopen("a.wmv","rb");
FILE *p1 = fopen("2.wmv","wb");
char buf[*];
while(!feof(p))
{
memset(buf,,sizeof(buf));
size_t res = fread(buf,sizeof(char),sizeof(buf),p);//返回从源文件中读取的字节数
fwrite(buf,sizeof(char),res,p1);//从源文件读取多少字节,就往源文件中写入多少字节
}
fclose(p);
fclose(p1);
return ;
}
fread fwrite
2.3二进制文件加密
- 三.文件中常用操作
3.1 在堆中分配内存拷贝文件
int main()
{
struct stat st= {};//定义一个结构,名字叫st
stat("1.txt",&st);//调用完stat函数中之后,文件相关信息就保存在st结构中了
char *array=malloc(st.st_size);//根据文件大小在堆中动态的分配一块内存
FILE *p = fopen("a.wmv","rb");
fread(array,sizeof(char),st.st_size,p);//相当于一下把整个文件放入内存
p=fopen("test.wmv","wb");
fwrite(array,sizeof(char),st.st_size,p);//将堆中的信息一下都写入文件
return ;
}
3.2结构体与二进制文件
struct student
{
char name[];
int age;
}; int main1()
{
struct student st = {"池国维",};
FILE *p=fopen("stu.dat","wb");
fwrite(&st,sizeof(st),,p);
fclose(p);
return ;
} int main()
{
struct student st = {};
FILE *p=fopen("stu.dat","rb");
fread(&st,sizeof(st),,p);
fclose(p);
printf("name=%s,age=%d\n",st.name,st.age);
return ;
}
3.3大文件数据排序
核心思想就是以一个新的数组的下标表示数据中相应的数出现的次数
int main()
{ FILE *p = fopen("big.txt","r");
int array[]={};
while(!feof(p))
{
char buf[]={};
fgets(buf,sizeof(buf),p);
if(buf[] != )//如果读取的行不是空行,那么久执行代码
{
int value = atoi(buf);//将得到的行转化为int
array[value]++;
} }
fclose(p); p = fopen("res.txt","w");
int i;
int j;
for(i=;i<;i++)
{
for(j=;j<array[i];j++)
{
fprintf(p,"%d\n",i);
}
}
fclose(p);
printf("end"); return ;
}
3.4文件位置操作-fseek与ftell
struct student
{
char name[];
int age;
}; int main1()//写文件
{
struct student st[] = {}; int i;
for(i=;i<;i++)
{
printf("please input name:");
scanf("%s",st[i].name);
printf("please input age:");
scanf("%d",&st[i].age);
} FILE *p = fopen("student.dat","wb");
fwrite(st,sizeof(struct student),,p);
fclose(p);
} int main()//读文件
{
struct student st = {};
FILE *p = fopen("student.dat","rb");
// while(!feof(p))
// {
// memset(&st,0,sizeof(struct student));
// if(fread(&st,sizeof(struct student),1,p) == 0)//fread只能往前走,不能往后退
// break;
// printf("name=%s,age=%d\n",st.name,st.age);
// }
//那么如何才能在指定位置读取呢,就需要用到fseek函数 //fseek(p,sizeof(struct student),SEEK_SET);//从文件开始位置向后偏移结构student这么多的字节
memset(&st,,sizeof(struct student));
fread(&st,sizeof(struct student),,p);
printf("name=%s,age=%d\n",st.name,st.age);
fseek(p,-sizeof(struct student),SEEK_CUR);//从当前位置往回偏移
memset(&st,,sizeof(struct student));
fread(&st,sizeof(struct student),,p);
printf("name=%s,age=%d\n",st.name,st.age); printf("ftell = %d\n",ftell(p));//当前文件指针p在第7个字节 fclose(p);
return ;
}
3.5 fflush
fflush(p)将缓冲区的内容立刻写入文件,优势是不会因为停电,或者电脑死机等故障导致缓冲区内容丢失,不好的是硬盘读写次数增加,导致程序效率低下,同时硬盘寿命会变短,修改配置文件的时候,有时候会用,或者做一些不经常修改的数据,但很重要的数据,那么用fflush.
3.6 文件删除和改名
int main()//文件删除和改名
{
remove("2.wmv");
remove("3.wmv");
remove("a.wmv");
rename("1.txt","111.txt");
}
4.C语言文件操作的更多相关文章
- go语言文件操作,这期资料比较详细( 欢迎加入go语言群: 218160862 )
		go语言文件操作,这期资料比较详细 欢迎加入go语言群: go语言深圳群 golang深圳 218160862 点击加入 文件操作 func Open(name string) (file *File ... 
- C语言文件操作
		C语言文件操作,以下以基本的例子和说明来展开怎么通过C语言来进行文件操作. 操作文件,我们得需要知道什么?当然是路径和文件名. 首先我需要知道我操作的文件在哪里,叫什么名字.在C语言中还存在一个打开方 ... 
- C 语言文件操作
		C 语言文件操作 1. 数据流: 程序与数据的交互以流的形式进行.fopen 即打开数据流,fclose 即刷新数据流. 所谓数据流,是一种抽象,表示这段数据像流一样,需要逐步接收,不 ... 
- C语言文件操作函数
		C语言文件操作函数大全 clearerr(清除文件流的错误旗标) 相关函数 feof表头文件 #include<stdio.h> 定义函数 void clearerr(FILE * str ... 
- C语言文件操作解析(五)之EOF解析(转载)
		C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符.但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特 ... 
- 【转】C语言文件操作解析(三)
		原文网址:http://www.cnblogs.com/dolphin0520/archive/2011/10/07/2200454.html C语言文件操作解析(三) 在前面已经讨论了文件打开操作, ... 
- C语言文件操作函数大全(超详细)
		C语言文件操作函数大全(超详细) 作者: 字体:[增加 减小] 类型:转载 本篇文章是对C语言中的文件操作函数进行了详细的总结分析,需要的朋友参考下 fopen(打开文件)相关函数 open,fc ... 
- C语言文件操作  FILE结构体
		内存中的数据都是暂时的,当程序结束时,它们都将丢失.为了永久性的保存大量的数据,C语言提供了对文件的操作. 1.文件和流 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特 ... 
- C语言文件操作相关函数
		在实际应用中,我们往往需要对文件进行操作,下面我将介绍C语言的一些关于操作文件的函数. 一.计算机文件 计算机文件是以计算机硬盘为载体存储在计算机上的信息集合,是存储在某种长期储存设备上的一段数据流. ... 
- 关于C语言文件操作
		关于C语言的文件操作之前我也写过一篇博客来介绍,但是当时写的很不全面,只是简单的使用了一下 ,今天再从新学习一下. 1.文件的写 首先还是先看一个简单的例子: include<stdio.h&g ... 
随机推荐
- 仿hibernate,spring框架手动写
			近期学习了hibernate底层技术和spring 的底层技术,认为非常不错,所以想分享下,要是说的不够具体.能够去下载资源自己查看下载链接 技术的体现是在实际中的.如今大体介绍一下吧 首先介绍hib ... 
- Oracle Table Function
			Oracle Table Function在Oracle9i时引入.完美的兼容了view和存储过程的长处: 应用举例: 1.Table()函数: set feedback off create or ... 
- 主站sinox.org堵塞太厉害,大家用sinox.3322.org訪问
			近期 www.sinox.org域名堵塞太厉害了.差点儿不能訪问,如今大家用sinox.3322.org訪问 sinox.org仅仅是显示正在建设 一直以来sinox.org仅仅是个摆设,并非主要域名 ... 
- Java多线程编程模式实战指南(三):Two-phase Termination模式--转载
			本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-two-phase-t ... 
- C#.Net版本自动更新程序及3种策略实现
			C#.Net版本自动更新程序及3种策略实现 C/S程序是基于客户端和服务器的,在客户机编译新版本后将文件发布在更新服务器上,然后建立一个XML文件,该文件列举最新程序文件的版本号及最后修改日期.如程序 ... 
- Django(part2)
			admin site:django自带了admin site,我们需要创建能访问site的用户 #以交互的方式创建超级用户 manage.py createsuperuser 如果要把model加到a ... 
- QT笔记 -- (5) 实现QWidget的paintEvent函数,在widget上画背景图形
			如图,想在界面上画个弧线和直线,于是继承QWidget得到类MainContainer,并实现了paintEvent函数.然后用类MainContainer定义centralWidget. MainC ... 
- activity的23张表
			--二进制数据表 SELECT * FROM act_ge_bytearray; --属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录, SELECT * FROM act_g ... 
- 50个极好的bootstrap框架
			转自:http://sudasuta.com/bootstrap-admin-templates.html https://www.cnblogs.com/sanhao/p/9184323.html ... 
- 定时清理clientmqueue目录垃圾文件防止占满磁盘空间
			RedHat/CentOS 5.8 默认就有sendmail,而6.4默认没有. 手动清理方法: find /var/spool/clientmqueue/ -type f|xargs rm -f ... 
