文件
(一)C文件的基础知识
1. 问题引入
我们生活中有哪些文件呢?
①我们写好的课件保存到磁盘就是一个文件
②使用手机拍照,照片就是一个文件
③我们使用邮件添加附件就是以文件形式保存
④我们上传或者下载视顿也是一个文件
…
2. 文件的概念
-
文件一般是指存储在外部介质(如磁盘)上的。
-
操作系统是以文件为单位进行数据管理.
3. 文件的分类
- 在程序设计中,主要用到两种文件:
①程序文件
包括我们的源程序(后缀为.c)、目标文件(后缀为.obj). 可执行文件(后缀为.exe)等。 这种文件的内容是程序代码。
②数据文件
文件内容不是程序,而是供我们读写的数据信息。
4. 数据文件的分类
数据文件可以分为两种:
①磁盘文件
指一组相关数据的有序集合通常存储在外部介质[如磁盘]上,使用时才调入内存。
②设备文件
在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。例如键盘是输入文件,显示屏和打印机是输出文件。
5. 磁盘文件的分类
1 计算机的存储在物理上是二进制的,所以物理.上所有磁盘文件本质上是一样的:以字节为单位进行顺序存储。
2.在逻辑上可以将磁盘文件分为二进制文件和文本文件。
①文本文件
基于字符编码,常见的有ASCII、UNICODE等,一般可以使用文件编辑器直接打开。
②二进制文件
基于值编码,将内存中的数据按照其在内存中的存储形式原样输出到磁盘。
6. 文件指针
-
在c语言中用一个指针变量指向一个文件,这个指针称为文件指针。
. -
每个被使用的文件都会在内存中开辟一个相应的文件信息区,用来存放文件的有关
信息,而这些信息被保存到一个结构体变量中。 -
文件类型声明如下:
typedef struct
{
short level; //缓冲区"满"或者"空”的程度
unsigned flags; //文件状态标志
char fd; //文件描述符
unsigned char hold; //如无缓冲区不读取字符
short bsize; //缓冲区的大小
unsigned char *buffr: //数据缓冲区的位置
unsigned ar //指针,当前的指向
unsigned istemp; //临时文件,指示器
short token; //用于有效性的检查
}FILE;
-
为了方便起见,我们一般不对FILE变量进行命名,而是使用指针的方式。
-
c语言中有三个特殊的文件指针由系统默认打开,用户无需定文即可直接使用:
stdin: 标准输入,默认为当前终端(键盘),我们使用的scanf、getchar 函数默认从此终端获得数据。
stdout:标准输出,默认为当前终端(屏幕),我们使用的printf. puts 函数默认输出信息到此终端。
stderr:标准出错,默认为当前终端(屏幕),我们使用的perror函数默认输出信息到此终端。
指向文件的指针变量并不是指向外部介质数据文件的开头,而是指向内存中的文件信息的开头。
.
7. 文件操作流程
“三步走”方法:
①打开文件fopen()
②读写文件
a.按字符读写fgetc(),fputc()
b.按字符串读写fgets(),fputs()
c.文件结尾feof()
③关闭文件felose()
(二)打开与关闭文件
1. 打开文件
-
所谓打开文件就是给文件在内存中建立相应的文件信息区(存放文件的相关信息]和文件缓冲区(用来暂时存放输入输出数据)。
-
在打开文件的同时,需要指定指针变量去指向该文件,这样就能建立起指针变量与文件之间的联系了,我们就可以使用指针变量去操作文件了.
-
任何文件在使用前必须打开,打开方式为:
FILE * fopen(const char * filename, const char * mode);
功能:打开文件
参数:
filename:需要打开的文件名,根据需要加上路径
mode:打开文件的模式设置
返回值:
成功:文件指针
失败: NULL
2. 打开文件之filename参教
FILE *fp = NULL;
//相对路径:
//打开当前目录1.txt文件:源文件(源程序)所在目录
fp = fopen(“1.txt”,"r”);
//打开当前目录(demo)下2.txt文件
fp = fopen("./demo/ 2.txt",“r”);
//打开当前目录上一级目录(相对当前目录) 3.txt 文件
fp = fopen("…/3.txt",“r”);
//绝对路径:
//打开c盘test目录下一个叫4.txt文件
fp = fopen(“C://test//4.t”,“r”);
3. 打开文件之mode参数
打开模式 | 含义 |
---|---|
r或rb | 以只读方式打开一个文本文件(不创建文件,若文件不存在则报错) |
w或wb | 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a或ab | 以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 |
r+或rb+ | 以可读、可写的方式打开文件(不创建新文件) |
r+或rb+ | 以可读、可写的方式打开文件(不创建新文件) |
w+或wb+ | 以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a+或ab+ | 以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件 |
4.关闭文件
-
所谓关闭文件撤销文件信息区(存放文件的相关信息)和文件缓冲区(用来暂时存放输入输出数据),使文件的指针变量不在指向该文件。
-
任何文件在使用后应该关闭:
a.打开的文件会占用内存资源,如果总是打开不关闭,会消耗很多肉存。
b.一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用fopen打开文件会失败。
c.如果没有明确的调用fclose关闭打开的文件,那么程序在退出的时候。操作系统会统一关闭。
- 关闭文件的一-般形式为:
int fclose(FILE *stream);
功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:
stream: 文件指针
返回值:
成功: 0
失败: -1
(三)顺序读写文件
1. 按字符读写文件
-
写文件
int fputc(int ch, FILE * stream);
功能: 将ch转换为unsigned char后写入stream指定的文件中
参数:
ch: 需要写入文件的字符
stream; 文件指针
返回值:
成功:成功写入文件的字符
失败:返回-1
-
文件结尾
在C语言中,EOF表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是
以字符的ASCI代码值的形式存放。我们知道,ASCII 代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。
当把数据以二进制形式存放到文件中时,就会有-1值的出现,因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题,ANSI C 提供一个feof函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。
-
读文件
int fgetc(FILE * stream];功能: 从stream指定的文件中读取一个字符
参数:
stream:文件指针
返回值:
成功:返回读取到的字符
失败: -1
2. 按字符串写文件
int fputs(const char *str, FILE * stream);
功能: 将str所指定的字符串写入到stream指定的文件中,字符串结束符’\0’不写入文件。
参数:
str:字符串
stream:文件指针
返回值:
成功: 0
失败: -1
3. 按字符串读文件
char fgets(Char str, int size, FILE *steam);
功能: 从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size -1 个字符为止,最后会自动加上字符\0’ 作为字符串结束。
参数:
str:; 字符串
size:指定最大读取字符串的长(size - 1)
stream:文件指针
返回值:
成功:成功读取的字符串
读到文件尾或出错: NULL
4. 按照格式化写文件
int fprintf(FILE * stream, const char * format,…);
功能: 根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符\0’为止。
参数:
stream:已经打开的文件
format:字符串格式,用法和printf()y一样
返回值:
成功:实际写入文件的字符个数
失败: -1
5. 按照格式化读文件
int fscanf(FILE * stream, const char * format,…);
功能:从stream指定的文件读取字符串,并根据参数format 字符串来转换并格式化数据。
参数:
stream:已经打开的文件
format:字符串格式,用法和scanf()一样
返回值:
成功:参数数目,成功转换的值的个数
失败:-1文件的字符个数
失败:-1
6. 用二进制的方式写文件
size_t fwrite(const void "ptr, size_t size, size_t nmemb,FILE *stream);
功能: 以数据块的方式给文件写入内容
参数:
ptr:准备写入文件数据的地址
size: size_t 为unsigned int类型,此参数指定写入文件内容的块数据大小
nmemb:写入文件的块数,写入文件数据总大小为: size *nmemb
stream:已经打开的文件指针
返回值:
&加粗样式nbsp; 成功:实际成功写入文件数据的块数目,此值和nmemb相等
失败: 0
7. 用二进制的方式读文件
size_t fread(void *ptr, size_tsize, size_t nmemb, FILE *stream);
功能: 以数据块的方式从文件中读取内容
参数:
ptr:存放读取出来数据的内存空间
size: sizet 为unsigned int类型,此参数指定读取文件内容的块数据大小
nmemb:读取文件的块数,读取文件数据总大小为: size * nmemb
stream:已经打开的文件指针
返回值:
成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
失败: 0
8. window和Linux文本文件的区别
b是二进制模式的意思,b只是在Windows有效,在Linux用r和rb的结果是一样的。
Unix和Linux下所有的文本文件行都是\n结尾,而Windows所有的文本文件行都是\r\n结尾
在Windows平台下,以“文本”方式打开文件,不加b:
当读取文件的时候,系统会将所有的"\r\n" 转换成"\n"
当写入文件的时候,系统会将"\n" 转换成“"\r\n" 写入
以二进制”方式打开文件,则读\写都不会进行这样的转换
在Unix/Linux平台下,“文本”与“二进制”模式没有区别,"\r\n" 作为两个字符原样输入输出
(四)随机读写文件
1. fseek
int fseek(FILE *stream, long offset, int whence);
功能: 移动文件流(文件光标)的读写位置。
参数:
stream:已经打开的文件指针
offset:根据 whence 来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对whence 往右移动,如果是负数,则相对于 whence 往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。
whence:其取值如下:
SEEK_SET:从文件开头移动 offset 个字节
SEEK_CUR:从当前位置移动 offset 个字节
SEEK_END:从文件末尾移动 offset 个字节
返回值:
成功: 0 失败: -1
2. ftell
long ftell(FILE *stream);
功能: 获取文件流(文件光标)的读写位置。
参数:
stream:已经打开的文件指针
返回值:
成功:当前文件流(文件光标)的读写位置
失败: -1
3.rewind
void rewind(FILE *stream);
功能: 把文件流(文件光标)的读写位置移动到文件开头。
参数:
stream:已经打开的文件指针
返回值: 无返回值
(五)文件缓冲区
1. 文件缓冲区的概念
所谓缓冲文件系统是指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送
到磁盘去。
如果从磁盘向计算机读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(给程序变量) 。
2. 文件缓冲区的存取
磁盘文件,一般保存在硬盘、 U 盘等掉电不丢失的磁盘设备中,在需要时调入内存
在内存中对文件进行编辑处理后,保存到磁盘中
程序与磁盘之间交互,不是立即完成,系统或程序可根据需要设置缓冲区,以提高存取效率
3. 文件缓冲区的刷新
int fflush(FILE *stream);
功能: 更新缓冲区,让缓冲区的数据立马写到文件中。
参数:
stream:文件指针
返回值:
成功: 0
失败: -1
自学自用,难免存在错误,如有错误,请给予指正。在这里将自己的心得和学习过程分享给大家,为大家提供一些思路,希望大家在学习的道路上少走一些弯路。
部分资源来源于网络,如有侵权,请联系本人予以删除!