C语言笔记(七)---文件操作及C库文件列表

第十三章 文件

一,C文件概述

从用户的角度看,文件可分为 普通文件设备文件
设备文件 为 显示器、打印机、键盘等。
在操作系统中,把 外部设备 也看作是一个文件来进行管理,把他们的输入、输出等同于对磁盘文件的读和写。

从文件编码的方式看,文件可分为 ASCII码文件二进制码文件 两种。
ASCII文件 也称为 文本文件 ,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对于的ASCII码。

C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。
输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。
因此,把这种文件称作“流式文件”。

本章讨论流式文件的打开、关闭、读、写、定义等各种操作。

二,文件指针

在C语言中,用一个指针变量指向一个文件,这个指针称为 文件指针。

定义说明文件指针的一般形式为: FILE *指针变量标识符;
其中 FILE 应为大写,他实际上是由系统定义的一个结构,该结构中含有 文件名文件状态文件当前位置 等信息。
在编写源程序时不必关心FILE结构的细节。

例如: FILE *fp;
表示fp是指向FILE结构的指针变量,通过fp即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件,实施对文件的操作。
习惯上也笼统地把fp称为指向一个文件的指针。

三,文件的打开与关闭

文件在进行读写操作之前要先打开,使用完毕要关闭。
所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其他操作。
关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。

在C语言中,文件操作都是由库函数来完成的。

1. 文件的打开

文件指针名=fopen(文件名,使用文件方式);

例如:

FILE *fp;
fp=fopen("file a","r");

含义是在当前目录下打开 file a ,只允许进行“读”操作,并使fp指向该文件。

又如:

FILE *fphzk;
fphzk=fopen("c:\\hzk16","rb");

含义是打开 c:\\hzk16,这是一个二进制文件,只允许按二进制方式进行读操作。
两个反斜线 \\ 中的第一个表示转义字符,第二个表示根目录。

使用文件的方式共有12种,下面给出了他们的符号和意义:

  • "rt"=只读打开一个文本文件 "wt"=只写 打开或建立一个文本文件 "at"=追加打开一个文本文件
  • "rb"=只读打开一个二进制文件 "wb" "ab"
  • "rt+"=读写打开一个文件文件 ,允许读和写 "wt+"=读写打开或建立一个文本文件,允许读写 "at+" "rb+" "wb+" "ab+"

对于文件使用方式有以下几点说明:

  • 1)文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是:
    r=read w=write a=append t=text b=binary +=read&write
  • 2)凡用“r”打开一个文件时,该文件必须已经存在,且只能从该文件读出。
  • 3)用“w”打开的文件只能向该文件写入。若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删除,重建一个新文件。
  • 4)若要向一个已存在的文件追加新的信息,只能用“a”方式打开文件。但此时文件必须是存在的,否则将会出错。
  • 5)在打开一个文件时,如果出错,fopen将返回一个空指针NULL。在程序中可以用这一信息来判断释放完成打开文件的工作,并做相应的处理。因此,常用以下程序段打开文件:
 if((fp=fopen("c:\\hzk16","rb")==NULL) {
  printf("\nerror on open C:\\hzk16 file!");
  getch();
  exit(1);
 }
  • 6)把一个文本文件读入内存时,要将ASCII码转换成二进制码,而把文件以文本方式写入磁盘时,也要把二进制码转换成ASCII码,因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换。
  • 7)标准输入文件(键盘)、标准输出文件(显示器)、标准出错输出(出错信息)是由系统打开的,可直接使用。

2. 文件关闭函数:

fclose(文件指针);

正常完成关闭文件操作时,fclose 的返回值为0,如返回非零值则表示有错误发生

四、文件的读写

字符读写函数

fgetc fputc

字符串读写函数

fgets fputs

数据块读写函数

freed fwrite

格式化读写函数

fscanf fprintf

需要 #include <stdio.h>

1. 字符读写函数fgetc和fputc

字符读写函数每次可从文件读出或写入一个字符。

(1)读字符函数fgetc

字符变量=fgetc(文件指针);

说明:
a)读取字符的结果也可以不保存。即 fgetc(fp);

b)在文件内部有一个 位置指针 ,用来指向文件的 当前读写字节
在文件打开时,该指针总是指向文件的第一个字节。
使用 fgetc函数 后,该位置的指针将 向后移动一个字节。
因此可以连续多次使用 fgetc函数 ,读取多个字符。
应注意文件指针和文件内部的位置指针不是一回事:文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,他不需要在程序中定义说明,而是由系统自动设置的。

例子:读入文件c1.doc,在屏幕上输出:

#include<stdio.h>
main() {
  FILE *fp;
  char ch;

  if ((fp=fopen("d:\\jrzh\\example\\c1.txt","rt"))==NULL)  {
    printf("\nCannot open file strike any key exit!");
    getch();
    exit(1);
  }
  ch=fgetc(fp);
  while(ch!=EOF) {
    putchar(ch);
    ch=fgetc(fp);
  }
  fclose(fp);
}

(2)写字符函数fputc

fputc(字符量,文件指针);

说明:
a)每写入一个字符,文件内部位置指针向后移动一个字节。
b)fputc函数 有一个返回值,如写入成功则返回写入的字符,否则返回一个EOF。
可用此来判断写入是否成功。

例子:从键盘输入一行字符,写入一个文件,再把该文件内容读出显示在屏幕上。

#include<stdio.h>
main() { 
 FILE *fp;
 char ch;
 if ((fp=fopen("aaa","wt+"))==NULL)  {
   printf("Cannot open file strike any key exit!");
   getch();
   exit(1);
 }
 printf("input a string:\n");
 ch=getchar();
 while(ch!='\n') {
    fputc(ch,fp);
    ch=getchar();
 }
 rewind(fp);//把内部位置指针移动文件头
 ch=fgetc(fp);
 while(ch!=EOF)  {
   putchar(ch);
   ch=fgetc(fp);
 }
 printf("\n");
 fclose(fp);
}

例子:把命令行参数中的前一个文件名标识的文件,复制到后一个文件名标识的文件中。
如命令行只有一个文件名则把该文件写到标准输出文件(显示器)中。

#include<stdio.h>
main(int argc,char *argv[]) {
  FILE *fp1,*fp2;
  char ch;
  if (argc==1)  {
    printf("have not enter file name strike any key to exit!");
   getch();
   exit(0);
  }
  if((fp1=fopen(argv[1],"rt"))==NULL)  { 
    printf("Cannot open %s\n",argv[1]);
    getch();
    exit(1);
  }
  if (argc==2) 
    fp2=stdout;
  else if ((fp2=fopen(argv[2],"wt+"))==NULL)  {
    printf("Cannot oepn %s\n",argv[2]);
    getch();
    exit(1);
  }
  while ((ch=fgetc(fp1))!=EOF)
     fputc(ch,fp2);

  fclose(fp1);
  fclose(fp2);
}

2. 字符串读写函数fgets和fputs

(1)读字符串函数fgets

fgets(字符数组名,n,文件指针);

n表示从文件中读出的字符串不超过 n-1 个字符。
在读入的最后一个字符后加上串结束标志 \0

例如:fgets(str,n,fp);
说明:
a)在读出 n-1个字符之前,如遇到了换行符或EOF,则读出结束。
b)fgets函数也有返回值,其返回值是字符数组的首地址。

(2)写字符串函数fputs:

fputs(字符串,文件指针);

例如: fputs("abcd",fp);

例子:在文件string中追加一个字符串。

#include<stdio.h>
main() {
  FILE *fp;
  char ch,st[20];
  if ((fp=fopen("string","at+"))==NULL)  {
    printf("Cannot open file strike any key to exit!");
    getch();
    exit(1);
  }
  printf("input a string:\n");
  scanf("%s",st);
  fputs(st,fp);
  rewind(fp);
  ch=fgetc(fp);
  while (ch!=EOF)  { 
    putchar(ch);
    ch=fgetc(fp);
 }
 printf("\n");
 fclose(fp);
}

3. 数据块读写函数fread和fwrite

可用来读写一组数据,如一个数组元素、一个结构变量的值等。
读数据块函数调用的一般形式为:

fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);

其中,buffer是一个指针,在 fread函数 中,他表示存放输入数据的首地址。在 fwrite函数 中,他表示存放输出数据的首地址。
size 表示数据库的字节数
count 表示要读写的数据块块数

例如: fread(fa,4,5,fp); 含义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。

例子:从键盘输入两个学生数据,写入一个文件中,再读出这两个学生的数据显示在屏幕上。

#include<stdio.h>
struct stu {
  char name[10];
  int num;
  int age;
  char addr[15];
} bota[2],boyb[2],*pp,*qq;

main() {
  FILE *fp;
  char ch;
  int i;
  pp=boya;
  qq=boyb;
  if ((fp=fopen("d:\\stu_list","wb+"))==NULL)  {
    printf("Cannot open file strike any key exit!");
    getch();
    exit(1);
  }

  printf("\ninput data\n");
  for(i=0;i<2;i++,pp++)
    scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);

  pp=boya;
  fwrite(pp,sizeof(struct stu),2,fp);
  rewind(fp);
  fread(qq,sizeof(struct stu),2,fp);
  printf("\n\nname\tnumber   age   addr\n");
  for(i=0;i<2;i++,qq++)
   printf("%s\t%5d%7d    %s\n",qq->name,qq->num,qq->age,qq->addr);

  fclose(fp);
}

四、格式化读写函数fscanf和fprintf:

fscanf(文件指针,格式字符串,输入表列);
fprintf(文件指针,格式字符串,输出表列);

// 例如:
fscanf(fp,"%d%s",&i,s);
fprint(fp,"%d%c",j,ch);

例子:上面的例子的改写:

#include<stdio.h>
struct stu {
  char name[10];
  int num;
  int age;
  char addr[15];
} boya[2],boyb[2],*pp,*qq;

main() {
  FILE *fp;
  char ch;
  int i;
  pp=boya;
  qq=boyb;
  if((fp=fopen("stu_list","wb+"))==NULL)  {
    printf("Cannot open file strike any key exit!");
    getch();
    exit(1);
  }
  printf("\ninput data\n");
  for(i=0;i<2;i++,pp++)
    scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);

  pp=boya;
  for(i=0;i<2;i++,pp++)
    fprintf(fp,"%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);

  rewind(fp);
  for(i=0;i<2;i++,qq++)
    fscanf(fp,"%s %d %d %s\n",qq->name,&qq->num,&qq->age,qq->addr);

  printf("\n\nname\tnumber   age   addr\n");
  qq=boyb;
  for (i=0;i<2;i++,qq++)
    printf("%s\t%5d %7d  %s\n",qq->name,qq->num,qq->age,qq->addr);

  fclose(fp);
}

五,文件的随机读写

1. 文件定位

rewind函数fseek函数

rewind前面介绍过,是把内部位置指针移动到文件首。

fseek(文件指针,位移量,起始点);

"位移量"是long类型数据,以便在文件长度大于64KB时不会出错。
当用常量表示位移量时,要求加后缀L
“起始点”表示从何处开始计算位移量,规定的起始点有三种: 文件首当前位置文件尾
其表示方法如下:
SEEK_SET=0=文件首
SEEK_CUR=1=当前位置
SEEK_END=2=文件末尾

例如:fseek(fp,100L,0);

还要说明的是 fseek函数 一般用于二进制文件。
在文本文件中由于要进行转换,故往往计算的位置会出现错误。

2. 文件的随机读写

在移动位置指针之后,即可用前面介绍的任一种读写函数进行读写。
由于一般是读写一个数据块,因此常用 freadfwrite 函数。

例子:在学生文件stu_list中读出第二个学生的数据

#include<stdio.h>
struct stu {
  char name[10];
  int num;
  int age;
  char addr[15];
} boy,*qq;

main() {
  FILE *fp;
  char ch;
  int i=1;
  qq=&boy;
  if((fp=fopen("stu_list","rb"))==NULL)  {
    printf("Cannot open file strike any key to exit!");
    getch();
    exit(1);
  }

  rewind(fp);
  fseek(fp,i*sizeof(struct stu),0);
  fread(qq,sizeof(struct stu),1,fp);
  printf("\n\nname\tnumber   age   addr\n");
  printf("%s\t%5d  %7d   %s\n",qq->name,qq->num,qq->age,qq->addr);
}

六,文件检测函数

1. 文件结束检测函数feof函数

feof(文件指针)
功能:判断文件是否处于文件结束位置,如文件结束,返回值为1,否则为0.

2,读写文件出错检测函数

ferror(文件指针);
功能:检查文件在用各种输入输出函数进行读写时是否出错,如ferror返回值为0表示未出错,否则表示出错。

3,文件出错标志和文件结束标志置0函数

cleanerr(文件指针);
功能:本函数用于清除出错标志和文件结束标志,使他们为0值。

七、C库文件

分为两类:
一类是扩展名为 .h 的文件,称为头文件,在前面的包含命令中我们已多次使用过。
.h 文件中包含了 常量定义、类型定义、宏定义、函数原型以及各种编译选择设置等信息。

另一类是函数库,包括了 各种函数的目标代码,供用户在程序中调用。通常在程序中调用一个库函数时,要在调用之前包含该函数原型所在的 .h 文件。

下面给出Turbo C的全部".h"文件。

ALLOC.H 说明内存管理函数(分配、释放等)
ASSERT.H 定义assert调试宏
BIOS.H 说明调用IBM-PC ROM BIOS子程序的各个函数
CONIO.H 说明调用DOS控制台I/O子程序的各个函数
CTYPE.H 包含有关字符分类及转换的各类信息(如isalpha和toascii等)
DIR.H 包含有关目录和路径的结构、宏定义和函数、
DOS.H 定义和说明MSDOS和8086调用的一些常量和函数
ERRON.H 定义错误代码的助记符
FCNTL.H 定义在与open库子程序连接时的符号常量
FLOAT.H 包含有关浮点运算的一些参数和函数
GRAPHICS.H 说明有关图形功能的各个函数,图形错误代码的常量定义,正对不同驱动程序的各种颜色值,及函数用到的一些特殊结构
IO.H 包含低级I/0子程序的结构和说明
LIMIT.H 包含各环境参数、编译时间限制、数的范围等信息
MATH.H 说明数学运算函数,还定义了HUGE VAL 宏,说明了matherr和matherr子程序用到的特殊结构
MEM.H 说明一些内存操作函数(其中大多数也在STRING.H中说明)
PROCESS.H 说明进程管理的各个函数,spawn...和EXEC...函数的结构说明
SETJMP.H 定义longjmp和setjmp函数用到的jmp buf类型,说明这两个函数
SHARE.H 定义文件共享函数的参数
SIGNAL.H 定义SIG[ZZ(Z] [ZZ)]IGN和SIG[ZZ(Z] [ZZ)]DFL常量,说明rajse和signal两个函数
STDARG.H 定义读函数参数表的宏。(如vprintf,vscanf函数)
STDDEF.H 定义一些公共数据类型和宏
STDIO.H 定义Kernighan和Ritchie在Unix System V 中定义的标准和扩展的类型和宏。还定义标准I/O预定义流:stdin、stdout和stderr,说明I/0流子程序。
STDLIB.H 说明一些常用的子程序:转换子程序、搜索/排序子程序等。
STRING.H 说明一些字符串操作和内存操作函数
SYS\STAT.H 定义在打开和创建文件时用到的一些符号常量
SYS\TYPES.H 说明ftime函数和timeb结构
SYS\TIME.H 定义时间的类型time[ZZ(Z] [ZZ)]T。
TIME.H 定义时间转换子程序asctime、localtime和gmtime的结构,ctime、difftime、gmtime、localtime和stime用到的类型,并提供这些函数的原型
VALUE.H 定义一些重要常量,包括依赖于机器硬件的和为与Unix System V相兼容而说明的一些常量,包括浮点和双精度的范围。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容