总论


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二进制文件加密

Code
  • 三.文件中常用操作

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语言文件操作的更多相关文章

  1. go语言文件操作,这期资料比较详细( 欢迎加入go语言群: 218160862 )

    go语言文件操作,这期资料比较详细 欢迎加入go语言群: go语言深圳群 golang深圳 218160862 点击加入 文件操作 func Open(name string) (file *File ...

  2. C语言文件操作

    C语言文件操作,以下以基本的例子和说明来展开怎么通过C语言来进行文件操作. 操作文件,我们得需要知道什么?当然是路径和文件名. 首先我需要知道我操作的文件在哪里,叫什么名字.在C语言中还存在一个打开方 ...

  3. C 语言文件操作

    C 语言文件操作 1. 数据流:     程序与数据的交互以流的形式进行.fopen 即打开数据流,fclose 即刷新数据流.     所谓数据流,是一种抽象,表示这段数据像流一样,需要逐步接收,不 ...

  4. C语言文件操作函数

    C语言文件操作函数大全 clearerr(清除文件流的错误旗标) 相关函数 feof表头文件 #include<stdio.h> 定义函数 void clearerr(FILE * str ...

  5. C语言文件操作解析(五)之EOF解析(转载)

      C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符.但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特 ...

  6. 【转】C语言文件操作解析(三)

    原文网址:http://www.cnblogs.com/dolphin0520/archive/2011/10/07/2200454.html C语言文件操作解析(三) 在前面已经讨论了文件打开操作, ...

  7. C语言文件操作函数大全(超详细)

    C语言文件操作函数大全(超详细) 作者: 字体:[增加 减小] 类型:转载 本篇文章是对C语言中的文件操作函数进行了详细的总结分析,需要的朋友参考下   fopen(打开文件)相关函数 open,fc ...

  8. C语言文件操作 FILE结构体

    内存中的数据都是暂时的,当程序结束时,它们都将丢失.为了永久性的保存大量的数据,C语言提供了对文件的操作. 1.文件和流 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特 ...

  9. C语言文件操作相关函数

    在实际应用中,我们往往需要对文件进行操作,下面我将介绍C语言的一些关于操作文件的函数. 一.计算机文件 计算机文件是以计算机硬盘为载体存储在计算机上的信息集合,是存储在某种长期储存设备上的一段数据流. ...

  10. 关于C语言文件操作

    关于C语言的文件操作之前我也写过一篇博客来介绍,但是当时写的很不全面,只是简单的使用了一下 ,今天再从新学习一下. 1.文件的写 首先还是先看一个简单的例子: include<stdio.h&g ...

随机推荐

  1. linux文件与用户和群组

    文件基本属性 在图片中alogrithm的文件属性为drwxrwxr-x,其中d代表此文件为目录. 后面rwx,rwx,r-x分别代表文件所属者(ower),组(group),其他用户(other)的 ...

  2. Ruby print

    Ruby print

  3. Picking up Jewels

    Picking up Jewels There is a maze that has one entrance and one exit.  Jewels are placed in passages ...

  4. spring boot系统学习(知识点笔记)

    一.http的注解配置 1.@SpringBootAplication=@SpringBootConfiguration(其实就是个@Configuration)+@EnableAutoConfigu ...

  5. Effective Java(一)—— 创建和销毁对象

    在客户端(调用端)获取自身实例的方法: 公有的构造器: 类的静态工厂方法: 1. 使用静态工厂方法代替构造器 Boolean 是对基本类型 boolean 的包装类: public final cla ...

  6. Java 8 Concurrency Tutorial--转

    Threads and Executors Welcome to the first part of my Java 8 Concurrency tutorial. This guide teache ...

  7. CentOS_mysql8.0_错误

    #参考资料 CSND:https://blog.csdn.net/y_server/article/details/78781177 博客园:http://www.cnblogs.com/testwa ...

  8. (转)script标签到底该放在哪里

    一般script标签会被放在头部或尾部.头部就是<head>里面,尾部一般指<body>里[4-5]. 将script放在<head>里,浏览器解析HTML,发现s ...

  9. 解决IE下的li中img多余4px的问题--IE6有的问题

    为了对比明显,这里用img标签占位,但是背景用纯黑色 <ul> <li> <img src="" alt="" />< ...

  10. (转载)Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...