Download presentation
Presentation is loading. Please wait.
1
C语言大学实用教程 第10章 文件操作 西南财经大学经济信息工程学院 刘家芬
2
I/O设备 输入设备 输出设备 键盘、鼠标 软盘、硬盘(以文件的形式) 串行口、并行口、USB接口、网络端口
扫描仪、视频采集卡、电视卡、游戏杆、话筒 …… 输出设备 显示器、打印机 音箱 键盘上的指示灯其实是计算机的输出。鼠标也开始有反馈功能了。显示器出现了触摸屏……
3
标准输入输出 字符界面的操作系统一般都提供标准输入与输出设备 一般情况,标准输入就是键盘,标准输出就是终端显示器
DOS、Linux、Unix…… 一般情况,标准输入就是键盘,标准输出就是终端显示器 自来水厂
4
DOS下的标准输入输出重定向 程序prog如下 输入重定向 输出重定向
main() { char c; while ((c=getchar()) != '\n') putchar(++c); } 输入重定向 prog < infile.txt 输出重定向 prog > outfile.txt
5
文件(File)的概念 计算机的内存容易健忘,所以数据必须保存在硬盘、软盘、光盘和磁带等“不健忘”的外存上
这些能大量、永久保存信息的媒介,一般都以文件的形式给用户及应用程序使用 文件 一般指存储在外部介质上具有名字(文件名)的一组相关数据的集合 用文件可长期保存数据,并实现数据共享 程序中的文件 在程序运行时由程序在磁盘上建立一个文件,并通过写操作将数据存入该文件; 或由程序打开磁盘上的某个已有文件,并通过读操作将文件中的数据读入内存供程序使用
6
文件的存放 可以建立若干目录(文件夹),在目录里保存文件,同一级目录里保存的文件不能同名。
对使用者而言,只要知道文件的路径(全目录)和文件名,就能使用该文件 C:\home\Sunner\main.c 这都是托OS的福
7
文件的类型 二进制文件 文本文件/ASCII码文件 是一种字节序列,没有字符变换 按照数据在内存中的存储形式存储到文件
如整数127,在内存占2个字节,为 ,则文件中也存储为 ,占2个字节 文本文件/ASCII码文件 是一种字符序列 文件中存储每个字符的ASCII码 如整数127在文件中占3个字节,分别存放这3个字符的ASCII码,即49,50,55
8
文件的格式 数据必须按照存入的类型读出,才能恢复其本来面貌 公开的标准格式 也有不公开、甚至加密的文件格式
如bmp、tif、gif、jpg和mp3等类型的文件 ,有大量软件能生成和使用这些类型的文件 也有不公开、甚至加密的文件格式 如Microsoft Word的doc格式就不公开
9
文件访问 基本模式 open:打开文件 read:读文件 write:写文件 close:关闭文件 seek:文件定位
获得对此文件的指针、引用和句柄等,以证明可以使用此文件 read:读文件 参数一般指明要读多少字节,读到哪块内存。 每次调用此功能,都是接着上次调用的结束位置读(所以是个输入流) write:写文件 参数一般指明把哪块内存的内容写入文件,要写多少字节。 每次调用此功能,都是接着上次调用的结束位置写 (所以是个输出流) close:关闭文件 表明操作结束,不再使用此文件。 文件使用完毕必须关闭,否则影响系统性能 seek:文件定位 随机控制流的当前位置
10
C语言中的文件访问 #include <io.h> #include <fcntl.h>
int open(const char *pathname, int access); int fd = open("C:\\CONFIG.SYS", O_RDWR | O_CREAT); pathname是文件名,包含路径。如果不含路径,表示打开当前目录下的文件 access是打开方式,常用为O_RDONLY、O_WRONLY、O_RDWR与O_CREAT、O_TRUNC、O_APPEND的或运算 返回值为文件句柄(File Handle),留待以后使用。如果打开失败,返回值为-1
11
C语言中的文件访问 int read(int handle, void *buf, unsigned len);
int n_read = read(fd, buf, BUFSIZ); 从文件中读len个字节存到buf开始的地址单元中 handle是open获得的文件句柄 buf是保存读入内容的内存指针 len是最大可以读入的字节数 返回值为实际读入的字节数,可能大于len。返回0表示读到了末尾,返回-1表示出错
12
C语言中的文件访问 int write(int handle, void *buf, unsigned len);
int n_write = write(fd, buf, BUFSIZ); 把从buf开始的len个字节写入文件 handle是open获得的文件句柄 buf是要写入内容的内存指针 len是写入多少字节 返回值为实际写入的字节数,可能小于len。返回-1表示出错
13
C语言中的文件访问 int close(int handle); int ret = close(fd); 把遗留在缓冲区中的数据写入文件
handle是open获得的文件句柄 关闭成功返回0,否则返回-1 驱动器中无盘或盘空间不够时会引起关闭失败
14
C语言中的文件访问 long lseek(int handle long offset int fromwhere); 几个巧妙运用
int pos = lseek(fd, 100L, SEEK_CUR); handle是open获得的文件句柄 offset是相对fromwhere的位置偏移多少,可以为负数 fromwhere: SEEK_SET-----文件开始 SEEK_CUR-----当前位置 SEEK_END-----文件末尾 成功返回移位后的当前位置,从文件头算起;否则返回-1L 几个巧妙运用 curPos = lseek(fh, 0L, SEEK_CUR); 得到当前位置指针的位置 fileLength = lseek(fh, 0L, SEEK_END); 得到文件长度
15
C语言独特的文件访问 下面介绍的函数均定义在<stdio.h>中 int fclose(FILE *fp);
FILE *fopen(const char *filename, const char *mode); FILE *fp = fopen("C:\\CONFIG.SYS", "rw"); filename是文件名 包含路径。如果不含路径,表示打开当前目录下的文件 mode是打开方式 常用为"r"、"w"、"rw"和"a",分别表示只读、只写、读写和添加 "rb"表示只读二进制文件 返回值为指向此文件的指针,留待以后使用 如果打开失败,返回值为NULL int fclose(FILE *fp);
16
文件指针(File Pointer) FILE *fp ; 是FILE型指针变量 标识一个特定的磁盘文件 typedef struct {
short level; /*缓冲区‘满’或‘空’的程度*/ unsigned flags; /*文件状态标志*/ char fd; /*文件描述符*/ unsigned char hold; /*如无缓冲区不读字符*/ short bsize; /*缓冲区的大小*/ unsigned char *buffer;/*数据缓冲区的位置*/ unsigned char *curp; /*指针当前的指向*/ unsigned istemp; /*临时文件指示器*/ short token; /*用于有效性检查*/ }FILE; 在stdio.h文件中定义
17
C语言独特的文件访问 字符读写 int fgetc(FILE *fp); int fputc(int c, FILE *fp);
若读到文件尾,则返回EOF int fputc(int c, FILE *fp); 向fp输出字符c 若写入错误,则返回EOF,否则返回c
18
C语言独特的文件访问 字符串读写 char *fgets(char *s,int n,FILE *fp);
特例 fgets(buf, sizeof(buf), stdin); int fputs(const char *s, FILE *fp);
19
C语言独特的文件访问 格式化读写 int fscanf(FILE *fp, const char *format, ...);
fscanf(fp, "%d,%6.2f", &i, &t); int fprintf(FILE *fp, const char *format, ); fprintf(fp, "%d,%6.2f", i, t);
20
C语言独特的文件访问 按数据块读写 unsigned fread(void *ptr, unsigned size, unsigned nmemb, FILE *fp); 从fp读数据块到ptr size是每个数据块的大小 nmemb是最多允许写的数据块个数 返回实际读到的数据块个数 unsigned fwrite(const void *ptr, unsigned size, unsigned nmemb, FILE *fp); 把ptr指向的数据块写入fp
21
C语言独特的文件访问 文件定位,用于文件的随机读写
打开的文件中有一个位置指针指示当前读写位置 对文件每进行一次顺序读写,文件指针自动指向下一读写位置 int fseek(FILE *fp, long offset, int fromwhere); 把fp的位置指针从fromwhere开始移动offset个字节 fromwhere: SEEK_SET或0-----文件开始 SEEK_CUR或1-----当前位置 SEEK_END或2-----文件末尾 int ftell(FILE *fp); 返回fp的当前位置指针 int rewind(FILE *fp); 让fp的位置指针指向文件首字节
22
C语言独特的文件访问 判断文件是否结束 int feof(FILE *fp); 当文件位置指针指向fp末尾时,返回非0值,否则返回0
23
错误处理 错误处理 通过判断返回值发现错误 出错处理 void perror(const char *s);
文件错误一般都是外界造成的,出错率很高 被删除、修改、磁盘空间满、被其他文件打开 通过判断返回值发现错误 所有文件操作出错时都返回-1 出错处理 打印错误信息给用户,等待用户的处理 void perror(const char *s); 向标准错误输出字符串s,随后附上错误的文字说明
24
Can't open c:\\abc.abc. Error: No such file or directory
错误处理——例10.1 #include <stdio.h> #include <errno.h> #include <io.h> #include <fcntl.h> main() { /* c:\abc.abc文件并不存在 */ int fh = open("c:\\abc.abc", O_RDONLY | O_BINARY); if (fh == -1) /* fh必然为-1 */ perror("Can't open c:\\abc.abc. Error"); } Can't open c:\\abc.abc. Error: No such file or directory
25
两种方式的区别 fopen族的函数包装了open族的函数,提供更强大的功能,但是效率略逊
open族的功能一般由OS直接提供,其使用方式也比较具有通用性,在各种语言里基本一样 open族通常情况能直接反映文件的真实情况,因为它的操作都不假定文件的任何结构
26
实验10 文件复制与追加 程序1: 根据程序提示从键盘输入一个已存在的文本文件的完整文件名,并再输入一个新文本文件的完整文件名
实验10 文件复制与追加 程序1: 根据程序提示从键盘输入一个已存在的文本文件的完整文件名,并再输入一个新文本文件的完整文件名 然后编程将已存在文本文件中的内容全部拷贝到新文本文件中去 利用文本编辑软件,通过查看文件内容验证程序执行结果。
27
实验10 文件复制与追加 main() { …… /*文件拷贝*/ while ((ch = fgetc(fpSrc)) != EOF)
实验10 文件复制与追加 main() { …… /*文件拷贝*/ while ((ch = fgetc(fpSrc)) != EOF) if (fputc(ch, fpDst) == EOF) printf("Copy failed!"); exit(0); } printf("Copy succeed.\n");
28
例10.4 文件复制 #include <stdio.h> #define MAXLEN 80
int CopyFile(const char* srcName, const char* dstName); main() { char srcFilename[MAXLEN]; /* 源文件名 */ char dstFilename[MAXLEN]; /* 目标文件名 */ printf("Input source filename:"); scanf("%s", srcFilename); printf("Input destination filename:"); scanf("%s", dstFilename); if (CopyFile(srcFilename, dstFilename)) printf("Copy succeed.\n"); } else perror("Copy failed:");
29
int CopyFile(const char* srcName, const char* dstName) {
FILE* fpSrc = NULL; FILE* fpDst = NULL; int ch, rval=1; fpSrc = fopen(srcName, "rb"); if (fpSrc == NULL) goto ERROR; fpDst = fopen(dstName, "wb"); if (fpDst == NULL) while ((ch=fgetc(fpSrc)) != EOF) if (fputc(ch, fpDst) == EOF) } /* 确保存盘 */ fflush(fpDst); goto EXIT; ERROR: rval=0; EXIT: if (fpSrc != NULL) fclose(fpSrc); if (fpDst != NULL) fclose(fpDst); return rval; }
30
实验10 文件复制与追加 程序2: 模拟DOS命令下的COPY命令
实验10 文件复制与追加 程序2: 模拟DOS命令下的COPY命令 在DOS状态下键入命令行,以实现将一个已存在文本文件中的内容全部拷贝到新文本文件中去 利用文本编辑软件,通过查看文件内容验证程序执行结果。
31
main(int argc, char *argv[])
{ if (argc != 3) printf("too few parameters!\n"); exit(0); } if (CopyFile(argv[1], argv[2])) /*文件拷贝*/ printf("Copy succeed.\n"); else perror("Copy failed");
Similar presentations