一、文件
- 1.1 什么是文件
- 1.2 文件名
二、 文件流的打开与关闭
- 2.1 流
- 2.2 文件指针类型(FILE *)
- 2.3 文件流的打开和关闭
三、 顺序读写
- 3.1 字符函数
- 3.1.1 字符输入 fgetc函数
- 3.1.2 字符输出 fputc函数
- 3.2 未格式化文本行函数
- 3.2.1 未格式化文本行输入 pgets函数
- 3.2.2 未格式化文本行输出 fputs函数
四、随机读写
- 4.1 获取文件当前位置 ftell函数
- 4.2 改变文件当前位置 fseek函数
- 4.3 设置文件当前位置为起始位置 rewind函数
一、文件 1.1 什么是文件
磁盘文件在DOS管理中被定义为存贮在外部介质上的程序或数据的集合,是一批逻辑上有联系的数据。
每个文件都有个文件名作为标识,每个文件在磁盘中的具体存放位置、格式都由 *** 作系统中的文件系统管理,也就是说, *** 作系统是以文件为单位对程序或数据进行管理的。
在C语言中文件的含义更为广泛,不仅包含以上所述的磁盘文件,还包括一切能进行输入/输出的终端设备,它们被看成是设备文件。
如键盘常称为标准输入文件,显示器称为标准输出文件。
即在C语言中文件是由磁盘文件和设备文件组成的,磁盘文件根据功能又分为程序文件和数据文件
1.2 文件名一个文件要有一个唯一的文件标识,以便用户识别和引用,文件名包含3部分:文件路径+文件名主干+文件后缀
例如Windows下: c:\code\test.txt
Linux下: /tmp/file.txt (Linux系统不识别文件后缀名,后缀名是给用户看的)
二、 文件流的打开与关闭 2.1 流
流是一个高度抽象概念
当前计算机具有大量不同设备,很多与I/O *** 作有关。
如:软盘、硬盘、通信端口、视屏适配器等。
每种设备具有不同的特性和 *** 作协议, *** 作系统负责与这些不同设备的I/O细节,并向程序员提供一个更为简单和统一的I/O接口
C语言进一步对I/O接口进行抽象引入流的概念。
根据流的方向分为输入流和输出流。
程序要输入数据只需从输入流中读入;输出数据只需向输出流中写即可。
特定I/O设备的细节对程序员是隐藏的。
说明:每个C语言程序运行时默认打开3个流,分别为标准输入流(stdin)、标准输出流(stdout)、标准错误流(stderr)。
标准输入默认是键盘,标准输出默认是显示器
2.2 文件指针类型(FILE *)每个被使用的文件都会在内存中开辟了一个对应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。
这些信息是保存在一个结构体变量中的。
该结构体类型是FILE类型,在
中定义,我们也将这个结构体变量称为文件流
//VS2013 IDE中头文件对FILE的定义
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
不同的C编译器中FILE类型结构体包含的内容不完全相同,但是大同小异
每当打开一个文件的时候,系统会根据文件的信息自动创建一个FILE类型结构体变量,并填充其中的内容, 为了使用方便,一般都是通过一个FILE * 的指针来维护这个FILE类型结构体变量,所以FILE * 指针指向一个文件流
使用者不必关心细节。
FILE* pf;//文件指针变量
pf是一个指向FILE类型数据的指针变量。
可以使pf指向某个文件的文件信息区(是一个结构体变量),通过该文件信息区中的信息就能够访问该文件
fopen函数功能:
打开一个指定文件,并返回一个指向该文件流(文件信息区)的FILE * 指针
库函数fopen函数声明
FILE * fopen ( const char * filename, const char * mode );
返回值:打开文件成功返回指向该文件流(文件信息区)的FILE * 指针,打开失败返回NULL指针,所以应该检查fopen函数的返回值
filename :需打开文件或设备名字,可以是绝对路径或相对路径写法
mode:文件打开模式
常用模式说明:
r :以只读方式打开文件,该文件必须存在
w :以只写方式打开文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
a :以追加的方式打开只写文件。
若文件不存在,则会创建该文件;如果文件存在,则写入的数据会被加到文件末尾
b :打开二进制文件,配合上面r、w、a使用
fclose函数功能:
刷新文件缓冲区,关闭一个指定文件(释放文件流)
库函数fclose函数声明
int fclose ( FILE * stream );
返回值:关闭成功返回0,失败返回EOF
stream:指向文件流的指针
#include
int main()
{
FILE* pf = fopen("file.txt", "r"); //以只读方式打开一个文件file.txt
if (NULL == pf) //打开失败
{
perror("fopen"); //打印错误信息
return -1; //退出程序
}
//读 *** 作
fclose(pf); //关闭文件
pf = NULL;
return 0;
}
三、 顺序读写
顺序读写:对文件的输入和输出只能按照顺序读写
3.1 字符函数 3.1.1 字符输入 fgetc函数fgetc函数功能:
返回指定流的位置指示器指向的字符,然后位置指示器向前移动一个字符,简单理解就是从指定流读取1个字符
库函数fgetc函数声明
int fgetc ( FILE * stream );
返回值:读取成功返回对应字符的ascii码值。
读取到文件结束标志时,则函数返回EOF并设置流的文件结束指示符(feof)。
如果发生读错误,该函数返回EOF并设置流的错误指示符(ferror)
stream:指向输入流(文件流、标准输入流)的指针
测试1:从文件中读取字符
#include
int main()
{
FILE* pf = fopen("file.txt", "r"); //file.txt存在,内容为hello
if (NULL == pf)
{
printf("%s\n", strerror(errno));
return 1;
}
printf("%c\n", fgetc(pf)); //输出读取第1个字符
printf("%c\n", fgetc(pf)); //输出读取第2个字符
fclose(pf);
pf = NULL;
return 0;
}
输出
h
e
测试2:从标准输入中读取字符
#include
int main()
{
char c = fgetc(stdin);
printf("%c\n", c);
return 0;
}
输入
a
输出
a
3.1.2 字符输出 fputc函数
fputc函数功能:
将一个字符写入流并使位置指示器向前移动,即字符被写入到流的内部位置指示器所指示的位置,然后该位置指示器自动前进1,简单理解就是写1个字符到流中
库函数fputc函数声明
int fputc ( int character, FILE * stream );
返回值:如果成功,则返回所写的字符。
如果发生写错误,则返回EOF并设置错误指示器(ferror)。
character :待写入字符
stream:指向输出流(文件流、标准输出流)的指针
测试1:输出字符到文件
#include
int main()
{
//将字符'a' 'b' 'c' 写入到文件
FILE* pf = fopen("file.txt", "w");
if (NULL == pf)
{
printf("%s\n", strerror(errno));
return 1;
}
fputc('a', pf);
fputc('b', pf);
fputc('c', pf);
fclose(pf);
pf = NULL;
return 0;
}
测试2:输出字符到标准输出
#include
int main()
{
int c = fputc('h', stdout);
c = fputc('e', stdout);
c = fputc('l', stdout);
return 0;
}
屏幕上显示
hel
3.2 未格式化文本行函数
3.2.1 未格式化文本行输入 pgets函数
fgets函数功能:
从流中读取num-1个字符到字符数组str中,或者遇到换行符或文件结束符停止(以最先发生的为准)。
换行符会使fgets停止读取,但函数会认为它是一个有效的字符,并添加’\0’使成为一个字符串
库函数fgetc函数声明
char * fgets ( char * str, int num, FILE * stream );;
返回值:读取成功,函数返回str。
如果在读取中时遇到文件结束符,则设置eof指示器(feof),返回一个空指针(str的内容保持不变)。
如果发生读错误,则设置错误指示符(ferror)并返回一个空指针 (但str所指向的内容可能已经改变)
str :字符数组的数组名
num:最多复制num个字符到str数组
stream:指向输入流(文件流、标准输入流)的指针
测试1:从文件中读取未格式文本行
#include
int main()
{
FILE* pf = fopen("file.txt", "r"); //文件file.txt内容为:Hello World
if (NULL == pf)
{
printf("%s\n", strerror(errno));
return 1;
}
char arr[20] = "#################";
fgets(arr, 5, pf); //读取5-1个字符到arr数组,并添加'printf'到数组,即"Hell"
("%s",) arr;//打印Hell fgets
(,arr5 ,) pf;读取5-1个字符到arr数组,并添加'printf'到数组,即"o Wo" (
"%s",); arr//打印o Wofclose (
);pf=NULL
pf ; return0
; }Hello Wo
#
输出
include
测试2:从标准输入中读取未格式化文本行
intmain
( )char[
{
] arr="##########" ; fgets(
,6arr, stdin) ;printf(
"%s\n",); arrreturn0
; }abcdef
abcde
输入
int fputs ( const char * str, FILE * stream );;
输出
#
3.2.2 未格式化文本行输出 fputs函数
fputs函数功能:
将str指向的字符串写入流。
函数从指定的地址(str)开始复制,遇到’\0’停止。
'\0’不会复制到流中
库函数fputs函数声明
include
返回值:如果成功,将返回一个非负值。
在出错时,函数返回EOF并设置错误指示符(ferror)
str :需写入的字符串起始地址
stream:指向输出流(文件流、标准输出流)的指针
测试1 :输出未格式化文本行到文件
intmain
( )*=
{
FILEfopen pf ( "file.txt","w") ;if(
NULL ==) printf pf(
{
"%s\n",strerror( ))errno;return1
; }fputs
(
"Hello World",); pffputs(
"Hello WuHan",); pffclose(
);pf=NULL
pf ; return0
; }Hello WorldHello WuHan
#
打开file.txt文件发现内容为:
include
所以当要写入多行时需要在字符串中加入换行符,即 fputs(“Hello World\n”, pf);
测试2 :输出未格式化文本行到标准输出
intmain
( )char[
{
] arr1="Hello World\n" ; fputs(
,stdoutarr1) ;fputs(
"Hello Wuhan\n",stdout) ;return0
; }Hello World
Hello Wuhan
long int ftell ( FILE * stream );;
屏幕上显示
#
四、随机读写
随机读写:以任意顺序读写文件的不同位置,文件的读写位置是由文件信息区(文件流)中位置指示器决定
4.1 获取文件当前位置 ftell函数ftell函数功能:
返回流的位置指示器的当前值(文件当前位置)
库函数ftell声明
include
返回值:对于二进制流,这是当前位置距离文件起始位置之间字节数。
对于文本流,数值可能没有意义(因为不同系统换行符不一样,如:windwos换行符为\r\n linux换行符为\n)。
失败返回-1L
stream:指向流的指针
intmain
( )*=
{
FILEfopen pf ( "file.txt","r") ;if(
NULL ==) printf pf(
{
"%s\n",strerror( ))errno;return1
; }long
=
ftell position ( );pf//获取文件当前位置printf (
"文件当前位置:%d\n",); positionfgetc(
);pf//读取位置指示器的字符,读完后位置指示器向前移动= ftell
position ( );pfprintf(
"文件当前位置:%d\n",); positionfclose(
);pf=NULL
pf ; return0
; }0
1
输出
文件当前位置:void rewind ( FILE * stream );
文件当前位置:void rewind ( FILE * stream );
4.2 改变文件当前位置 fseek函数
fseek函数功能:
将流的位置指示器(当前位置)设置为指定位置,成功调用该函数后,清除流的文件结束符和错误内部指示符
库函数ftell声明
#
stream:指向流的指针
rewind函数功能:
将流的位置指示器(当前位置)设置为文件的起始位置,成功调用该函数后,清除流的文件结束符和错误内部指示符
库函数ftell声明
include
stream:指向流的指针
intmain
( )*=
{
FILEfopen pf ( "file.txt","r") ;if(
NULL ==) printf pf(
{
"%s\n",strerror( ))errno;return1
; }long
=
ftell position ( );pf//获取文件当前位置printf (
"文件当前位置:%d\n",); positionfseek(
,3pf, SEEK_SET) ;=ftell
position ( );pfprintf(
"文件当前位置:%d\n",); positionrewind(
);pf=ftell
position ( );pfprintf(
"文件当前位置:%d\n",); positionfclose(
);pf=NULL
pf ; return0
; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)