第 10 章 文件操作

49
10 10 第 第第第第 第 第第第第 第第第第第第第第第第第第第第第第第 第第第 [email protected]

description

C 语言大学实用教程. 第 10 章 文件操作. 哈尔滨工业大学计算机科学与技术学院 苏小红 [email protected]. I/O 设备. 输入设备 键盘、鼠标 软盘、硬盘、光驱(以文件的形式) 串行口、并行口、 USB 接口、网络端口 扫描仪、视频采集卡、电视卡、游戏杆、话筒 …… 输出设备 显示器、打印机 软盘、硬盘、 CD-R/DVD-R (以文件的形式) 串行口、并行口、 USB 接口、网络端口 音箱 …… 单纯的输入设备或者单纯的输出设备越来越少. 标准输入输出. 字符界面的操作系统一般都提供标准输入与输出设备 - PowerPoint PPT Presentation

Transcript of 第 10 章 文件操作

Page 1: 第 10 章 文件操作

第第 1010 章 文件操作章 文件操作哈尔滨工业大学计算机科学与技术学院

苏小红[email protected]

Page 2: 第 10 章 文件操作

23/4/24 2

I/OI/O 设备设备 输入设备输入设备

– 键盘、鼠标键盘、鼠标– 软盘、硬盘、光驱(以文件的形式)软盘、硬盘、光驱(以文件的形式)– 串行口、并行口、串行口、并行口、 USBUSB 接口、网络端口接口、网络端口– 扫描仪、视频采集卡、电视卡、游戏杆、话筒扫描仪、视频采集卡、电视卡、游戏杆、话筒– …………

输出设备输出设备– 显示器、打印机显示器、打印机– 软盘、硬盘、软盘、硬盘、 CD-R/DVD-RCD-R/DVD-R (以文件的形式)(以文件的形式)– 串行口、并行口、串行口、并行口、 USBUSB 接口、网络端口接口、网络端口– 音箱音箱– …………

单纯的输入设备或者单纯的输出设备越来越少单纯的输入设备或者单纯的输出设备越来越少

Page 3: 第 10 章 文件操作

23/4/24 3

标准输入输出标准输入输出 字符界面的操作系统一般都提供标准输入与输出设备字符界面的操作系统一般都提供标准输入与输出设备

– DOSDOS 、、 LinuxLinux 、、 Unix……Unix…… 一般情况,标准输入就是键盘,标准输出就是终端显一般情况,标准输入就是键盘,标准输出就是终端显示器示器

– 操作系统有能力重定向标准输入与输出,比如让文件作为标操作系统有能力重定向标准输入与输出,比如让文件作为标准输入,打印机作为标准输出准输入,打印机作为标准输出– 这种重定向程序本身是感觉不到的这种重定向程序本身是感觉不到的自来水厂自来水厂

Page 4: 第 10 章 文件操作

23/4/24 4

DOSDOS 下的标准输入输出重定向下的标准输入输出重定向 程序程序 progprog 如下如下

– main()main(){{ charchar c; c; whilewhile ((c=getchar()) != '\n') ((c=getchar()) != '\n') putchar(++c); putchar(++c);}}

输入重定向输入重定向– prog < infileprog < infile

输出重定向输出重定向– prog > outfileprog > outfile

Page 5: 第 10 章 文件操作

23/4/24 5

流(流( StreamStream )) 水流水流

– ““ 子在川上曰:逝者如斯夫”子在川上曰:逝者如斯夫” 计算机中的流的概念计算机中的流的概念

– 一般称为数据流,也有叫做字节流、比特流的,还有很一般称为数据流,也有叫做字节流、比特流的,还有很具体的文件流、视频流、音频流等具体的文件流、视频流、音频流等 时光不能倒流,但计算机中的很多流都是会倒流的时光不能倒流,但计算机中的很多流都是会倒流的

– 如果你想重新读已经读过的数据,或者要修改已经写入如果你想重新读已经读过的数据,或者要修改已经写入的数据,可以发出流控(的数据,可以发出流控( Flow ControlFlow Control )命令)命令– 不会倒流的数据流也很多,例如网络上的数据流。网络不会倒流的数据流也很多,例如网络上的数据流。网络和数据线等介质只有很小的数据缓冲区,没有大量存储和数据线等介质只有很小的数据缓冲区,没有大量存储的能力 的能力

Page 6: 第 10 章 文件操作

23/4/24 6

文件(文件( FileFile )的概念)的概念 计算机的内存容易健忘,所以数据必须保存在硬计算机的内存容易健忘,所以数据必须保存在硬盘、软盘、光盘和磁带等“不健忘”的外存上盘、软盘、光盘和磁带等“不健忘”的外存上 这些能大量、永久保存信息的媒介,一般都以文件这些能大量、永久保存信息的媒介,一般都以文件的形式给用户及应用程序使用的形式给用户及应用程序使用 文件文件

– 一般指存储在外部介质上具有名字(文件名)的一组相关一般指存储在外部介质上具有名字(文件名)的一组相关数据的集合数据的集合– 用文件可长期保存数据,并实现数据共享用文件可长期保存数据,并实现数据共享

程序中的文件程序中的文件– 在程序运行时由程序在磁盘上建立一个文件,并通过写在程序运行时由程序在磁盘上建立一个文件,并通过写操作将数据存入该文件;或由程序打开磁盘上的某个已有操作将数据存入该文件;或由程序打开磁盘上的某个已有文件,并通过读操作将文件中的数据读入内存供程序使用文件,并通过读操作将文件中的数据读入内存供程序使用

Page 7: 第 10 章 文件操作

23/4/24 7

文件与流文件与流 在在 CC 语言中,文件可以是磁盘文件、终端显示语言中,文件可以是磁盘文件、终端显示器或打印机等等。器或打印机等等。 程序通过打开操作把流与设备联系起来,文件程序通过打开操作把流与设备联系起来,文件打开后,可以在程序和文件之间交换数据。打开后,可以在程序和文件之间交换数据。 程序通过关闭操作断开流与文件的联系。程序通过关闭操作断开流与文件的联系。 所有流的性质都一样。因为流与设备无关,所所有流的性质都一样。因为流与设备无关,所以能写入磁盘文件的同一函数也能写入另一设以能写入磁盘文件的同一函数也能写入另一设备,如控制台终端等。备,如控制台终端等。 但文件的能力则可能不同。例如,磁盘文件可但文件的能力则可能不同。例如,磁盘文件可以支持随机存取,而键盘则不行。以支持随机存取,而键盘则不行。

Page 8: 第 10 章 文件操作

23/4/24 8

文件的存放文件的存放 可以建立若干目录(文件夹),可以建立若干目录(文件夹),在目录里保存文件,同一级目录在目录里保存文件,同一级目录里保存的文件不能同名。里保存的文件不能同名。 对使用者而言,只要知道文件的对使用者而言,只要知道文件的路径(全目录)和文件名,就能路径(全目录)和文件名,就能使用该文件使用该文件

– C:\home\Sunner\main.cC:\home\Sunner\main.c – 这都是托这都是托 OSOS 的福的福

Software

A:

D:home

E:

C:

TC20WinZip

Sunner

苏小红

Secretsgetnum.hgetnum.cmain.c

Backupmain.c

Page 9: 第 10 章 文件操作

23/4/24 9

文件的格式文件的格式 二进制文件二进制文件

– 是一种字节序列,没有字符变换是一种字节序列,没有字符变换– 按照数据在内存中的存储形式存储到文件按照数据在内存中的存储形式存储到文件– 如整数如整数 127127 ,在内存占,在内存占 22 个字节,为个字节,为 000000000111111000000000111111

11 ,则文件中也存储为,则文件中也存储为 00000000011111110000000001111111 ,占,占 22 个字个字节节 文本文件文本文件 /ASCII/ASCII码文件码文件

– 是一种字符序列是一种字符序列– 文件中存储每个字符的文件中存储每个字符的 ASCIIASCII码码– 如整数如整数 127127 在文件中占在文件中占 33 个字节,分别存放这个字节,分别存放这 33 个字符个字符

的的 ASCIIASCII码,即码,即 4949 ,, 5050 ,, 5555

Page 10: 第 10 章 文件操作

23/4/24 10

文件的格式文件的格式 数据必须按照存入的类型读出,才能恢复其本来面貌 数据必须按照存入的类型读出,才能恢复其本来面貌 公开的标准格式公开的标准格式

– 如如 bmpbmp 、、 tiftif 、、 gifgif 、、 jpgjpg 和和 mp3mp3 等类型的文件 ,有大量等类型的文件 ,有大量软件能生成和使用这些类型的文件 软件能生成和使用这些类型的文件 也有不公开、甚至加密的文件格式也有不公开、甚至加密的文件格式

– 如如 Microsoft WordMicrosoft Word 的的 docdoc 格式就不公开,所以至今还没有格式就不公开,所以至今还没有WordWord 以外的其它软件能完美地读出以外的其它软件能完美地读出 docdoc 文件 文件

int 100 float 100.0 字符串 "100" 字符串 "END" 64 00 00 00 C8 42 31 30 30 00 45 4E 44 00

D È B 1 0 0 E N D

TEST.BIN 内容(十六进制)

对应的 ASCII 字符

Page 11: 第 10 章 文件操作

23/4/24 11

文件访问文件访问 文件访问的基本模式文件访问的基本模式

– openopen :打开文件,获得对此文件的指针、引用和句柄:打开文件,获得对此文件的指针、引用和句柄等,以证明可以使用此文件等,以证明可以使用此文件– readread :读文件。参数一般指明要读多少字节,读到哪:读文件。参数一般指明要读多少字节,读到哪块内存。每次调用此功能,都是接着上次调用的结束块内存。每次调用此功能,都是接着上次调用的结束位置读。(所以是个输入流)位置读。(所以是个输入流)– writewrite :写文件。参数一般指明把哪块内存的内容写:写文件。参数一般指明把哪块内存的内容写入文件,要写多少字节。每次调用此功能,都是接着入文件,要写多少字节。每次调用此功能,都是接着上次调用的结束位置写。 (所以是个输出流)上次调用的结束位置写。 (所以是个输出流)– closeclose :关闭文件,表明操作结束,不再使用此文:关闭文件,表明操作结束,不再使用此文件。文件使用完毕必须关闭,否则影响系统性能件。文件使用完毕必须关闭,否则影响系统性能– seekseek :随机控制流的当前位置,文件定位:随机控制流的当前位置,文件定位

Page 12: 第 10 章 文件操作

23/4/24 12

CC 语言中的文件访问语言中的文件访问 下面介绍的函数均定义在下面介绍的函数均定义在 <io.h><io.h> 和和 <fcntl.h><fcntl.h> 中中 intint open( open(constconst charchar *pathname, *pathname, intint access); access);

– intint fd = open("C:\\CONFIG.SYS", O_RDWR | O_CREAT); fd = open("C:\\CONFIG.SYS", O_RDWR | O_CREAT); pathnamepathname 是文件名,包含路径。如果不含路径,表示打开当是文件名,包含路径。如果不含路径,表示打开当前目录下的文件前目录下的文件 accessaccess 是打开方式,常用为是打开方式,常用为

O_RDONLYO_RDONLY 、、 O_WRONLYO_WRONLY 、、 O_RDWRO_RDWR 与与O_CREATO_CREAT 、、 O_TRUNCO_TRUNC 、、 O_APPENDO_APPEND 的或运算的或运算

返回值为文件句柄返回值为文件句柄(( File HandleFile Handle ) ) ,留待以后使用。如果,留待以后使用。如果打开失败,返回值为打开失败,返回值为 -1-1

Page 13: 第 10 章 文件操作

23/4/24 13

CC 语言中的文件访问语言中的文件访问 intint read( read(intint handle, handle, voidvoid *buf, *buf, unsignedunsigned len); len);– intint n_read = read(fd, buf, BUFSIZ); n_read = read(fd, buf, BUFSIZ);

handlehandle 是是 openopen获得的文件句柄获得的文件句柄 bufbuf 是保存读入内容的内存指针是保存读入内容的内存指针 lenlen 是最大可以读入的字节数是最大可以读入的字节数 返回值为实际读入的字节数,可能大于返回值为实际读入的字节数,可能大于 lenlen 。。返回返回 00表示读到了末尾,返回表示读到了末尾,返回 -1-1表示出错表示出错

Page 14: 第 10 章 文件操作

23/4/24 14

CC 语言中的文件访问语言中的文件访问 intint write( write(intint handle, handle, constconst voidvoid *buf, *buf, unsignedunsigned len); len);– intint n_write = write(fd, buf, n_write = write(fd, buf, BUFSIZ); BUFSIZ);

handlehandle 是是 openopen获得的文件句柄获得的文件句柄 bufbuf 是要写入内容的内存指针是要写入内容的内存指针 lenlen 是写入多少字节是写入多少字节 返回值为实际写入的字节数,可能小于返回值为实际写入的字节数,可能小于 lenlen 。。返回返回 -1-1表示出错表示出错

Page 15: 第 10 章 文件操作

23/4/24 15

CC 语言中的文件访问语言中的文件访问 intint close( close(intint handle); handle);

– intint ret = close(fd); ret = close(fd); handlehandle 是是 openopen获得的文件句柄获得的文件句柄 关闭成功返回关闭成功返回 00 ,否则返回,否则返回 -1-1

Page 16: 第 10 章 文件操作

23/4/24 16

CC 语言中的文件访问语言中的文件访问 longlong lseek( lseek(intint handle handle

longlong offset offset intint fromwhere); fromwhere);– intint pos = lseek(fd, 100L, SEEK_CUR); pos = lseek(fd, 100L, SEEK_CUR);

handlehandle 是是 openopen获得的文件句柄获得的文件句柄 offsetoffset 是相对是相对 fromwherefromwhere 的位置偏移多少,可以为负数的位置偏移多少,可以为负数 fromwherefromwhere 可以是可以是 SEEK_SETSEEK_SET 、、 SEEK_CURSEEK_CUR 或或 SEEK_ENDSEEK_END中的一个,分别表示文件头、当前位置和文件结尾中的一个,分别表示文件头、当前位置和文件结尾 成功返回移位后的当前位置,从文件头算起;否则返回成功返回移位后的当前位置,从文件头算起;否则返回 -1L-1L 几个巧妙运用几个巧妙运用

– curPos = lseek(fh, 0L, SEEK_CUR);curPos = lseek(fh, 0L, SEEK_CUR);– fileLength = lseek(fh, 0L, SEEK_END);fileLength = lseek(fh, 0L, SEEK_END);

得到文件长度得到文件长度

Page 17: 第 10 章 文件操作

23/4/24 17

CC 语言独特的文件访问语言独特的文件访问 下面介绍的函数均定义在下面介绍的函数均定义在 <stdio.h><stdio.h> 中中 FILE *fopen(FILE *fopen(constconst charchar *filename, *filename, constconst charchar *mode); *mode);– FILE *fp = fopen("C:\\CONFIG.SYS",FILE *fp = fopen("C:\\CONFIG.SYS", "rw"); "rw");

filenamefilename 是文件名,包含路径。如果不含路径,表是文件名,包含路径。如果不含路径,表示打开当前目录下的文件示打开当前目录下的文件 modemode 是打开方式,常用是打开方式,常用

为为 "r""r" 、、 "w""w" 、、 "rw""rw" 和和 "a""a" ,分别表示只读、只,分别表示只读、只写、读写和添加写、读写和添加 返回值为指向此文件的指针,留待以后使用。如果打返回值为指向此文件的指针,留待以后使用。如果打开失败,返回值为开失败,返回值为 NULLNULL

Page 18: 第 10 章 文件操作

23/4/24 18

mode :

对应二进制文件

对应文本文件“r” 只读 必须是已存在的文件。“w” 只写 不论该文件是否存在,都新建一个文件。“a” 追加 向文本文件尾增加数据,该文件必须存在“ r+” 读写 打开一个已存在的文件,用于读写。 “w+” 读写 建立一个新文件,可读可写。“a+” 读写 向文件尾追加数据,也可读。 “rb” “wb”“ab”“rb+”“wb+”“ab+”

Page 19: 第 10 章 文件操作

23/4/24 19

文件指针文件指针 FILE FILE *fp ; *fp ;

– 是是 FILEFILE型指针变量型指针变量– 标识一个特定的磁盘文件标识一个特定的磁盘文件– 与文件相关联的每个流都有一个与文件相关联的每个流都有一个 FILEFILE类型的控制结构,类型的控制结构,定义有关文件操作的信息,用户绝对不应修改定义有关文件操作的信息,用户绝对不应修改

Page 20: 第 10 章 文件操作

23/4/24 20

文件指针(文件指针( File PointerFile Pointer )) typedeftypedef structstruct {{ shortshort level; /* level; /* 缓冲区缓冲区‘满’或‘空’‘满’或‘空’的程度的程度 **// unsignedunsigned flags; /* flags; /* 文件状态标志文件状态标志 **// charchar fd; /* fd; /* 文件描述符文件描述符 **// unsigned charunsigned char hold; /* hold; /* 如无缓冲区不读字符如无缓冲区不读字符 **// shortshort bsize; /* bsize; /* 缓冲区的大小缓冲区的大小 **// unsigned charunsigned char *buffer;/* *buffer;/* 数据缓冲区的位置数据缓冲区的位置 **// unsigned charunsigned char *curp; /* *curp; /* 指针当前的指向指针当前的指向 **// unsigned unsigned istemp; /*istemp; /*临时文件指示器临时文件指示器 **// shortshort token; /* token; /* 用于有效性检查用于有效性检查 **// }}FILEFILE;; 在在 stdio.hstdio.h 文件中定义文件中定义

Page 21: 第 10 章 文件操作

23/4/24 21

CC 语言独特的文件访问语言独特的文件访问 intint fgetc(FILE *fp); fgetc(FILE *fp); intint fputc( fputc(intint c, FILE *fp); c, FILE *fp); charchar *fgets( *fgets(charchar *s, *s,

intint n, n, FILE *fp); FILE *fp);

intint fputs( fputs(constconst charchar *s, *s, FILE *fp); FILE *fp);

intint fscanf(FILE *fp, fscanf(FILE *fp, constconst charchar *format, *format, ...); ...);

intint fprintf(FILE *fp, fprintf(FILE *fp, constconst charchar *format, *format, ...); ...);

Page 22: 第 10 章 文件操作

23/4/24 22

CC 语言独特的文件访问语言独特的文件访问 size_t fread(size_t fread(voidvoid *ptr, *ptr,

size_t size, size_t size, size_t n, size_t n, FILE *fp); FILE *fp);

size_t fwrite(size_t fwrite(constconst voidvoid *ptr, *ptr, size_t size, size_t size, size_t n, size_t n, FILE *fp); FILE *fp);

intint feof(FILE *fp); feof(FILE *fp); intint fseek(FILE *fp, fseek(FILE *fp,

longlong offset, offset, intint whence); whence);

intint fclose(FILE *fp); fclose(FILE *fp);

Page 23: 第 10 章 文件操作

23/4/24 23

错误处理错误处理 错误处理错误处理

– 文件错误一般都是外界造成的,出错率很高文件错误一般都是外界造成的,出错率很高– 被删除、修改、磁盘空间满、被其他文件打开被删除、修改、磁盘空间满、被其他文件打开

通过判断返回值发现错误通过判断返回值发现错误– 所有文件操作出错时都返回所有文件操作出错时都返回 -1-1

出错处理出错处理– 打印错误信息给用户,等待用户的处理打印错误信息给用户,等待用户的处理

void perror(const char *s);void perror(const char *s);– 向标准错误输出字符串向标准错误输出字符串 ss ,随后附上错误的文字说,随后附上错误的文字说明明

Page 24: 第 10 章 文件操作

23/4/24 24

错误处理错误处理————例例 10.110.1##includeinclude <stdio.h> <stdio.h>##includeinclude <errno.h> <errno.h>##includeinclude <io.h> <io.h>##includeinclude <fcntl.h> <fcntl.h>

main()main(){{

/* c:\abc.abc/* c:\abc.abc 文件并不存在 文件并不存在 **//intint fh = open("c:\\abc.abc", O_RDONLY | O_BINARY); fh = open("c:\\abc.abc", O_RDONLY | O_BINARY);

ifif (fh == -1) (fh == -1) /* fh/* fh 必然为必然为 -1 */-1 */{{perror("Can't open c:\\abc.abc. Error");perror("Can't open c:\\abc.abc. Error");}}

}}

Can't open c:\\abc.abc. Error: No such file or directoryCan't open c:\\abc.abc. Error: No such file or directory

Page 25: 第 10 章 文件操作

23/4/24 25

两种方式的区别两种方式的区别 openopen族的功能一般由族的功能一般由 OSOS直接提供,其使用方直接提供,其使用方式也比较具有通用性,在各种语言里基本一样式也比较具有通用性,在各种语言里基本一样 fopenfopen族的函数系包装了族的函数系包装了 openopen族的函数,提供族的函数,提供更强大的功能,但是效率略逊更强大的功能,但是效率略逊 openopen族通常情况能直接反映文件的真实情况,族通常情况能直接反映文件的真实情况,因为它的操作都不假定文件的任何结构因为它的操作都不假定文件的任何结构 fopenfopen族比较适合处理文本文件,或者结构单族比较适合处理文本文件,或者结构单一的文件。会为了处理的方便而改变一些内容一的文件。会为了处理的方便而改变一些内容

Page 26: 第 10 章 文件操作

23/4/24 26

从文件说开去从文件说开去 openopen 、、 readread 、、 writewrite 、、 closeclose 这种模式成为使这种模式成为使用数据流的经典模式用数据流的经典模式

– 比如网络数据流操作就是使用此模式,甚至在一些比如网络数据流操作就是使用此模式,甚至在一些平台上可以和文件采用完全相同的函数操作平台上可以和文件采用完全相同的函数操作 seekseek 并不是所有的流都支持并不是所有的流都支持

– 网络就不支持网络就不支持 对于不能进行流控的流,如果当前数据不立即对于不能进行流控的流,如果当前数据不立即处理,后来流过的数据就会冲走当前数据,永处理,后来流过的数据就会冲走当前数据,永远不能追回。流控成为流处理中的一个专门技远不能追回。流控成为流处理中的一个专门技术术

Page 27: 第 10 章 文件操作

23/4/24 27

例如 : fp=fopen(“a1.txt”,”r”); fp=fopen(“d:\\sqs\\a1.txt”,”r”);

fopen 函数返回指向文件 a1.txt 的指针并赋给fp, 即 fp 指向文件 a1.txt.

若不能实现打开任务 ,fopen 函数将带回一个空指针值 NULL(值为 0) 。

常用打开文件的方法为:if((fp=fopen(“a1.txt”,”r”))==NULL) { printf(“cannot onen this file\n”); exit(0); }

Page 28: 第 10 章 文件操作

23/4/24 28

文件的关闭 :fclose 函数

例如 : fclose(fp);

fclose( 文件指针 );

关闭 fp 所指向的文件。把遗留在缓冲区中的数据写入文件,实施操作系统级的关闭操作。同时,释放与流联系的文件控制快,以后可以再次使用这部分空间。

fclose 函数的返回值:当顺利地执行了关闭操作,则返回值为 0 ;如果返回值为非零值,则表示关闭时有错误。一般只有驱动器中无盘或盘空间不够时,才失败。关闭失败会引起数据丢失、破坏文件和程序中的随机错误

多数情况下,系统限制同时处于打开状态的文件总数,因此,打开文件前先关闭无用文件是必要的

Page 29: 第 10 章 文件操作

23/4/24 29

ch=fgetc (fp);

fgetc 和 fputc 函数fputc (ch,fp); ------ 把字符把字符 chch写到写到 fpfp所指向的文件中去。所指向的文件中去。

--- 从指定文件读入一个字符。该文件应以只读或读写方式打开。

二、文件的字符读写

返回值:若输出成功,则返回输出的字符,否则返回EOF 。

该文件应以写或读写方式打开。

返回值:若输入成功,则返回字符,否则返回一个EOF 。EOF :在 stdio.h 中定义的常量,表示文件结束#define EOF (-1)

Page 30: 第 10 章 文件操作

23/4/24 30

#include “stdio.h”main(){ char c; FILE *fp; if((fp=fopen(“tt.txt”, “w”))==NULL) { printf(“error!\n”): exit(0); } c=getchar(); while(c!=EOF) { fputc(c,fp); c=getchar(); } fclose(fp);}

例:将键盘输入的字符顺序存入磁盘文件 tt.txt中,输入 ctrl+z 结束

程序文件名为 f2.c ,程序运行结果是生成文件 tt.txt ;

Page 31: 第 10 章 文件操作

23/4/24 31

#include “stdio.h”main(){ char c; FILE *fp; if((fp=fopen(“tt.txt”, “r”))==NULL) { printf(“error!\n”): exit(0); } c=fgetc(fp); while(c!=EOF) { putchar(c); c=fgetc(fp); } fclose(fp);}

例:从文件 tt.txt 中顺序读取字符并显示出来。

Page 32: 第 10 章 文件操作

23/4/24 32

#include “stdio.h”main(){ char c; FILE *fp; if((fp=fopen(“tt.txt”, “r”))==NULL) { printf(“error!\n”): exit(0); } c=fgetc(fp); while(c!=EOF) { putchar(c); c=fgetc(fp); } fclose(fp);}

例:从文件 tt.txt 中顺序读取字符并显示出来。

Page 33: 第 10 章 文件操作

23/4/24 33

三、文件的数据块的读写— fread 和 fwrite 函数

函数调用成功返回 count 的值,否则返回 -1 。

fwrite() 函数的功能:将内存中的一组数据写到 fp 所指向的文件中。按照内存中的存储形式输出,为二进制文件。fwrite(buff, size, count, fp)

所要写入文件的数据在内存中的起始地址写入文件的每个数据项的字节数

写入文件的数据项数

指向写入文件的指针

Page 34: 第 10 章 文件操作

23/4/24 34

从键盘输入 n 个同学 的学号,姓名和成绩存入文件。#include “stdio.h”typedef struct student STUD;struct student{ int num; char name[12]; int score;} ;

例 1:文件的数据块写的操作

Page 35: 第 10 章 文件操作

23/4/24 35

main(){ STUD stu; /*stu为结构体变量 */ FILE *fp; char filename[12]; int i,n; scanf(“%s”,filename); if((fp=fopen(filename, “wb” ))==NULL) { printf(“can’t open the file!\n”); exit(0); } scanf(“%d”, &n); fwrite(&n,2,1,fp); for(i=0; i<n; i++) { scanf(“%d %s %d”, &stu.num, stu.name, &stu.score); if( fwrite( &stu, sizeof(STUD), 1, fp) != 1 ) /*写入一个数据项 */ { printf(“file write error!”); exit(0); } } fclose(fp);}

program1

Page 36: 第 10 章 文件操作

23/4/24 36

main(){ STUD stu[30]; /*stu[30]为结构体数组 */ FILE *fp; int i,n; char filename[12]; scanf(“%s”,filename); if((fp=fopen(filename, “wb” ))==NULL) { printf(“can’t open the file!\n”); exit(0); } scanf(“%d”,&n); fwrite(&n,2,1,fp); for(i=0; i<n; i++) scanf(“%d %s %d”, &stu[i]. num,stu[i].name, &stu[i].score);

fwrite( stu, sizeof(STUD), n, fp); /*一次写入 n个数据项 */ fclose(fp);}

program2

Page 37: 第 10 章 文件操作

23/4/24 37

fread(buff, size, count, fp)

fread() 函数:功能:在 fp 所指向的文件中读取一组数据并将其放到内存中去。

函数调用成功返回 count 的值,否则返回 -1 。

待读文件的数据在内存中的起始地址从文件读入的每个数据项的字节数

从文件读入的数据项数

指向待读文件的指针

Page 38: 第 10 章 文件操作

23/4/24 38

例 2 :文件的数据块读的操作#include “stdio.h”typedef struct student STUD;struct student{ int num; char name[12]; int score;} ;

main(){ STUD stu; FILE *fp; int i,n; char filename[12]; scanf(“%s”,filename); if((fp=fopen(filename, “rb”))==NULL) { printf(“can’t open the file!\n”);

exit(0); }

Page 39: 第 10 章 文件操作

23/4/24 39

fread(&n,2,1,fp); printf(“n=%d”,n); for(i=0; i<n; i++) { if(fread( &stu, sizeof(STUD), 1, fp) != 1 )/* 读入一个 */ { printf(“file read error!”);

exit(0); } printf(“%d\t%s\t%d\n”,stu.num, stu.name, stu.score); } fclose(fp);}

Page 40: 第 10 章 文件操作

23/4/24 40

main() { STUD stu[20]; …… fread(&n,2,1,fp); printf(“n=%d”,n); if(fread( stu, sizeof(STUD) , n , fp ) ! = n )/* 读入 n 个 */ { printf(“file read error!”);

exit(0); } for(i=0; i<n; i++) printf(“%d\t%s\t%d\n”, stu[i].num, stu[i].name, stu[i].score); fclose(fp); }

Page 41: 第 10 章 文件操作

23/4/24 41

四、文件的格式化读写 ( 文本文件 )

将输出项 arg1,arg2…argn按指定 format格式写入 fp 所指的文件中 ,即输出到磁盘文件;格式: fprintf(fp,format,arg1,arg2,…,argn);

格式: fscanf(fp,format,&arg1,&arg2,…&argn); fscanf 函数

fprintf 函数

按指定 format格式从 fp 所指的文件中读取数据依次送入arg1,arg2…argn 的内存单元;

arg1,arg2,…argn(&arg1,&arg2,…&argn) 输出 / 输入项表列 format :为格式字符串 fp: 为指向 fopen 函数打开的文件的指针

Page 42: 第 10 章 文件操作

23/4/24 42

fprintf ( fp,“%d,%6.2f”,i,t ) ;

将整型变量 i 和实型变量 t 的值按%d 和 %6.2 的格式输出到 fp 指向的文件中。

最好给出长度 , 读写统一

fscanf ( fp,“%d,%6.2f”,&i,&t ) ;

Page 43: 第 10 章 文件操作

23/4/24 43

例 1 :文件的格式化写操作#include “stdio.h”typedef struct student STUD;struct student{ int num; char name[12]; int score;} ;main(){ STUD stu; FILE *fp; int i,n; char filename[12]; scanf(“%s”,filename);

Page 44: 第 10 章 文件操作

23/4/24 44

if((fp=fopen(filename, “w”))==NULL) /* 新建一个文件 */ { printf(“can’t open the file!\n”); exit(0); } scanf(“%d”,&n); fprintf(fp, “%4d”,n); for(i=0; i<n; i++) { scanf(“%d%s%d”,&stu.num, stu.name, &stu.score); fprintf(fp, “%6d%10s%3d”,stu.num, stu.name, stu.score); } fclose(fp);}

Page 45: 第 10 章 文件操作

23/4/24 45

例 2 :文件的格式化读操作#include “stdio.h”typedef struct student STUD;struct student{ int num; char name[12]; int score;} ;main(){ STUD stu; FILE *fp; int i,n; char filename[12]; scanf(“%s”,filename);

Page 46: 第 10 章 文件操作

23/4/24 46

if((fp=fopen(filename, “r”))==NULL) /* 新建一个文件 */ { printf(“can’t open the file!\n”); exit(0); } fscanf(fp,“%6d”,&n); printf(“n=\n”,n); for(i=0; i<n; i++) { fscanf(fp, “%6d%10s%3d”,&stu.num,stu.name,&stu.score); printf(“%d\t%s\t%d\n”,stu.num,stu.name,stu.score); } fclose(fp);}

Page 47: 第 10 章 文件操作

23/4/24 47

五、文件的定位 文件指针 : 打开的文件中有一个位置指针指示动迁的读写位置,对文件每进行一次读写,文件指针自动指向下一个读写位置 , 则可方便地进行顺序读写 ,利用定位函数还可实现随机读写 .

fp 为指向 fopen 函数打开的文件的指针。

rewind () 函数功能:使文件指针重新指向文件的开头位置。 此函数没有返回值

形式: rewind(fp)

Page 48: 第 10 章 文件操作

23/4/24 48

fp :为指向 fopen 函数打开的文件的指针;offset :文件指针的位移量,字节数, long型,加 l 或L ;from :起始位置 0---- 文件开始 1-----当前位置 2----- 文件末尾

fseek() 函数:利用该函数可以改变文件指针的位置,从而实现随机读写

形式: fseek(fp,offset,from) ;

ftell() 函数:取得文件指针的当前位置,用字节数, long类型。

Page 49: 第 10 章 文件操作

23/4/24 49

六、出错的控制 ferror() 函数

形式: ferror(fp);

功能:检查输入输出函数的调用是否正确,返回非 0值,表示出错。 feof() 函数形式: feof(fp);

功能:检测文件是否结束,返回非 0值,表示结束。