文件操作与数据存储
-
为什么使⽤⽂件?
如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件。 -
什么是⽂件?
磁盘(硬盘)上的⽂件是⽂件。
但是在程序设计中,我们⼀般谈的⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类的)。
程序文件
程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows环境后缀为.exe)。
数据文件
⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。
流
流和标准流
我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。
C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。
⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。
标准流
那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?
那是因为C语⾔程序在启动的时候,默认打开了3个流:
• stdin -
标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
stdout
标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
• stderr
标准错误流,⼤多数环境中输出到显⽰器界⾯。
这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。
stdin、stdout、stderr 三个流的类型是: FILE *
通常称为⽂件指针。
C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作。
⽂件指针
缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系
统声明的,取名 FILE.
例如,VS2013 编译环境提供的 stdio.h 头⽂件中有以下的⽂件类型申明:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
文件的打开和关闭
fopen
FILE * fopen ( const char * filename, const char * mode )
⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。
在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了指针和⽂件的关系。
ASIIC 规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件。
mode表⽰⽂件的打开模式,下⾯都是⽂件的打开模式:
“r”
只读打开文件 文件必须存在,否则fopen返回NULL 只能读取文件内容,不能写入 / 修改
“w”
只写创建 / 截断文件 文件不存在则创建;存在则清空(截断)内容 打开后文件指针指向开头,写入会覆盖原有内容
“a”
追加写打开 / 创建文件 文件不存在则创建;存在则保留原有内容 写入内容始终追加到文件末尾,文件指针指向末尾
“r+”
读写打开文件 文件必须存在,否则fopen返回NULL 可同时读写,文件指针初始指向开头
“w+”
读写创建 / 截断文件 文件不存在则创建;存在则清空内容 可同时读写,初始指针指向开头
“a+”
读写打开 / 创建文件(追加读 + 写) 文件不存在则创建;存在则保留原有内容 写入始终追加到末尾;读取可从开头开始
fclose

fclose为关闭文件参数为流的指向的空间
#include<stdio.h>
int main()
{
FILE* pf = fopen("test.txt","r");
if (pf == NULL)
{
perror("fopen");
}
int fclose(pf);
pf = NULL;
return 0;
}
在这个代码中text.txt 文件不存在。所以只能返回空指针,用perror标记错误

文件的读写


函数的原型如上;
读写的函数有很多,我们选几个来讲一下他们的基础用法

fgetc
fgetc int fgetc(FILE *stream)
参数为流指向的文件
首先建立一个文本文件
text.txt
用vs打开

代码如下
int main()
{
FILE* pf = fopen("test.txt","r");
if (pf==NULL)//防止为空指针,提前结束
{
perror("fopen");
return 1;//终止
}
int c = 0;
while ((c=fgetc(pf))!=EOF)//语法格式
{
printf("%c", c);
}
fclose(pf);//关闭文件
pf = NULL;//置为空指针
return 0;
}

fputc和fputs
fputs输出字符串
fputc输出单个字符

fputs读取字符串
int main()
{
FILE* pr = fopen("test.txt","w");
if (pr==NULL)
{
perror("fopen");
return 1;
}
fputs("hello world",pr);
fclose(pr);
pr = NULL;
return 0;
}

scanf fscanf scanf
printf fprintf sprintf辨析
scanf/printf:面向标准输入 / 输出流(键盘 / 屏幕);
fscanf/fprintf:面向文件流;
sscanf/sprintf:面向内存字符串。
scanf int scanf(const char *format, ...); 标准输入(键盘) 从键盘按格式读取数据到变量 直接读取用户输入
fscanf int fscanf(FILE *stream, const char *format, ...); 文件流 从指定文件按格式读取数据到变量 读取文件中的格式化数据
sscanf int sscanf(const char *str, const char *format, ...); 内存字符串 从指定字符串按格式解析数据到变量 解析字符串中的结构化数据

int main()
{
int a = 0;
/*printf("%s","hello world\n");
fprintf(stdout, "%s", "hello world\n");*/
/*scanf("%d",&a);*/
fscanf(stdin,"%d",&a);
printf("%d",a);
system("pause");)
return 0;
}
文件的随机读写
fseek
根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。
int fseek ( FILE * stream, long int offset, int origin )

完




1074





