C语言第十三章文件操作

文件操作 学习内容

1、C语言中的流

2、标准输入输出及其重定向

3、文件的分类

4、文件的打开和关闭

5、文件的读写

 

文件操作的基本规则:打开文件-操作文件-关闭文件

 

何谓文件(Files)

存储在外部介质上具有名字的一组相关数据的集合

  数据一般以文件的形式为用户及应用程序使用

  文件1、泛指磁盘文件;2、OS对于例如终端显示器或打印机等设备,以文件形式来管理的。

使用文件后,可以实现程序数据分离,数据共享,实现数据长久的保存

 

文件存储的方式

建立若干目录(文件夹,directory\folder)

  在目录里保存文件

  同一级目录里保存的文件不能同名

对使用者而言,只要知道文件的路径(path,全目录)和文件名,就能使用改文件

  D:\home\Sunner\main.c

  Windows用反斜杠\分割路径

  UNIX用斜杠/

文件存储在外存中

外存

  内存容量小,容易健忘,掉电即失

  外存容量大、断电后数据不丢失,可重复使用,永久保存,不健忘

磁盘(Magnetic disks)

  磁盘表面涂有磁性物质

  磁性单元的N-S极的两种指向表示0-1

光盘(CD、DVD)

  光盘表面有一层特殊介质

  介质的高低不平的交替表示0-1

U盘(Flash Memory)

  闪存,可用电擦除的ROM

  一种电化学存储介质,电流的通断表示0-1

 

文件的分类

1、按文件的逻辑结构

记录文件--由具有一定结构的记录组成(定长和不定长)

流式文件stream--由一个个字符(字节)数据顺序组成,数据流,字节流

 

流(stream)--计算机的基础设施infrastruture,类似于现实世界里的水电煤气等基础设施

通过一个流(通常和键盘相关)获得全部的输入

通过另一个流(通常和屏幕相关)写出全部的输出

较大规模的程序:

  可能需要额外的流,如磁盘文件、网络端口、打印机等。

 

C语言中的标准流

stdio.h提供了三种标准流

  系统定义三个标准文件,分别对应于终端设备:stdin、stdout、stderr。它们共同构成了计算机的基础设施,是备用的,不能声明、打开和关闭。

scanf(),getchar(),gets()等通过stdin获得输入

printf(),putchar(),puts()等用stdout进行输出

Tips:stdout和stderr在默认情况下都指向屏幕,有和区别呢?

  输出到stdout的内容先保存到缓冲区(buffer)

  而输出到stderr的内容则直接输出到屏幕

 

输入/输出重定向 redirection

某些操作系统允许标准输入/输出重定向文件

  *DOS和UNIX允许程序从文件获得输入或向文件写数据

  这种重定向,程序本身是感觉不到的

输入重定向(Input Redirection)

  *D:\>demo< infile.txt

  *从终端(键盘)输入数据改成从文件中读入数据

输出重定向(Output Redirection)

  D:\>demo > outfile.txt

  从终端(显示器)输出数据重定向到文件

 

文件的分类

2、文件按数据的组织形式可以分为:

文本文件(Text file)

二进制文件(Binary file)

  C程序的源代码--文本文件

  可执行的C程序--二进制文件

文本文件和二进制文件有什么区别呢?

 

二进制文件与文本文件的区别:

  按照数据在内存中的存储形式(二进制)存储到文件

  二进制文件存储的字节不一定表示字符,无需ASCII码表进行字符变换,读写速度快

二进制文件的缺点:

  不易阅读,妨碍调试过程

  尤其注意可移植性问题

    二进制文件与不同类型的计算机及其存储数据方式相关。

    存储int型2字节,4字节?先存高位字节,低位字节?与机器字长、对齐方式alignment以及big-endian/little-endian等相关

 

总之,二进制文件保存数据,不仅要按照存入时的类型,还要按存入时的格式读出,才能恢复期本来面貌。

公开的标准文件格式

  如bmp、tif、gif、jpg和mp3等类型的文件,有大量软件生成和使用这些类型的文件

不公开或加密的文件格式

  如Microsoft Word的doc格式就不公开,所以至今没有Word以外的其他软件能完美地读出doc文件

 

实际上,文件就是一种字节序列,无论何种形式。

对于程序员来说,区分文本文件和二进制文件:

文本文件--按行划分

  所以必须用特殊的字符标记行的结尾

  某些OS还可能用特殊的字符标记文件的末尾

    例如DOS将Ctrl+Z设定为文件的结束符

二进制文件---不是按行划分的,可合法地包含任何字符,故不可能留出文件结束符

 

文件与流的关系

程序通过文件打开操作将流与设备联系起来,文件打开后,可在程序和文件之间交换数据

  由程序在磁盘上建立文件(建立文件)

  文件打开后,通过写操作将数据存入该文件(写入数据)

  由程序打开磁盘上的某个已有文件,通过读操作将文件中的数据读入内存供程序使用(读取数据)

程序通过文件关闭操作来断开流与文件的联系

 

文件指针(File Pointer)

C程序中的流的打开和关闭是通过文件指针实现的

文件指针的类型为FILE *

FILE  *  fp;

  --定义了FILE型指针变量*fp,标识一个特定的磁盘文件

  --Tips:与文件相关联的每个流都有一个FILE类型的控制结构

    定义有关文件操作的信息,用户绝对不应修改

 

通过文件指针对文件进行操作的时候动态保存的数据结构如下:

 

文件打开操作

文件打开操作一定要判文件打开是否成功!!

 

为什么要返回文件指针(句柄,handle)呢?

--以后关闭文件时要用

--因FILE结构较大,传回这个结构的首地址效率比传回整个结构效率高

 

文件关闭操作

为什么要关闭文件,因为文件的写入操作是将数据写入到缓冲区中的,执行了文件关闭操作后,操作系统会将缓冲区中的最后一部分数据全部flush到文件中,整个时候才能生成一个完整的文件。

 

各种文件的操作成功与否一定要进行判断!!

 

文件打开后一定要关闭。否则,可能引起数据丢失,甚至影响其他文件的打开,多数情况下,系统限制同时打开状态的文件总数。因此,打开文件前先关闭无用文件是必要的的。

 

文件打开方式(mode)

 

文件操作的常用函数:

 

 

按字符读写文件

 

例:从键盘输入一串字符,转存到磁盘文件上demo.txt

 

例:将0-127之间的ASCII字符写入demo.bin二进制文件中,并读取该文件内容并显示(用写字板和vc打开)

二进制文件读操作经典代码:

 

按字符串读写文件

使用fgets的重定向来替换gets,可以防止缓冲区溢出,具有重要意义

 

按格式读写文件

例:修改例12.7,计算每个学生的4门课程的平均分,将学生的各科成绩及平均分输出到文件score.txt中

例:从上面的文件中score.txt读出每个学生的4门课的平均分,各科成绩及平均分。

注意:读的时候和写的时候的格式要一样

 

fprintf()最普遍的应用:

1、向标准错误流写出错信息

fprintf(stderr,"Error: file can't be opened\n);

即使用户重定向stdout,向stderr写入的信息也保证会出现在屏幕上

2、输出调试信息,报告程序运行到了哪里,那里的状态是什么

1 int Add(int para1, int para2)
2 {
3     int a, b;
4     fprintf(stderr,"DEBUG: Call foo() with %d and %d\n",para1,para2);
5     a = para1;
6     b = para2;
7     return a*b;
8 }

 

按数据块来读写文件

例:在前几个实例基础上,计算每个学生的4门课程的平均分,将学生的各科成绩及平均分输出到student.txt中,然后再从文件中读出数据并显示到屏幕上

允许程序在单步中读和写比较大的数据块,虽然可以用于文本流,但主要还是用于二进制流。刚才的例子是用在文本流上。

 

文件的随机读写

如何实现文件的随机读写呢?

文件从头到尾按字节从0开始顺序编址,用以表示数据的存储位置

文件位置指针(Position pointer,文件位置标记)

  -指示打开文件的当前读写位置

  -对文件每读写一次,文件指针自动指向下一个读写位置,方便地进行顺序读写

  -利用文件定位函数,还可实现随机读写

 

文件定位

设定文件位置指针的函数

void rewind(FILE *fp);

使文件位置指针重新指向文件的开始位置

long ftell(FILE *fp);

返回当前文件位置指针(相对于文件起始位置的字节偏移量)

int fseek(FILE *fp, long offset, int fromwhere);

改变文件位置指针,实现随机读写。将文件位置指针从fromwhere开始移动offset个字节,指示下一个要读取的数据的位置

fp:指向fopen()打开的文件的指针

offset:位置指针的偏移量(字节数),long 型,加l或L

fromwhere:起始位置  (SEEK_SET或0----文件开始,SEEK_CUR或1----当前位置,SEEK_END或2----文件末尾)

 

文件缓冲

从磁盘驱动器传出或传入信息,性对较慢

提高读写效率的诀窍----缓冲(buffering)

输出缓冲

  --写入文件的数据,实际是存储在内存的缓冲区内

  --当缓冲区满或关闭文件时,缓冲区自动”清洗"(写入输出设备)

  --主动清洗输出流,用fflush(fp);

输入缓冲

  --来自输入设备的数据存在输入缓冲区内

  --从缓冲区读数据代替了从设备本身读数据

 

文件缓冲提高效率的原因所在

  --缓冲发生在屏幕的后天,自动完成,如getchar()

  --从缓冲区读数据或向缓冲区写数据,几乎不花时间

  --仅花时间将缓冲区内容传递给磁盘文件,或反之

  --一次性的大块移动比频繁的字符移动快得多

 

缓冲型和非缓冲型文件系统

缓冲型文件系统

  --系统自动在内存中为每个正在使用的文件开辟一个缓冲区,读写文件时,数据先送缓冲区再传给C程序或外存

  --利用文件指针标识文件

  --缓冲型文件系统中的文件操作,也称高级文件操作

  --高级文件操作函数ANSI C定义的文件操作函数,具有跨平台和可移植的能力

非缓冲文件系统

  --不自动设置文件缓冲区,缓冲区需由程序员自己设定

  --没有文件指针,使用称为文件号的整数来标识文件

fopen族的函数 open族的函数
将很多功能从不同OS的范畴转移到了标准语言库的范畴,实现了以独立于实现的方式来执行I/O

功能一般由OS直接提供,在不同的OS上有细微差别

较适合处理文本文件,或结构单一的文件,会为了处理方便而改变一些内容 通常能直接反映文件的真是情况,因为它的操作都不假定文件的任何结构
功能更强大,但效率略逊色  

本章小结

1、文件的分类

2、文件操作函数

  --文件的打开和关闭

  --文件的顺序读写

  --文件的随机读写

 

有没有图形的标准函数呢?

  标准C没有,编译器可能带有图形库,或者使用第三方提供的图形库,当然也可以自己编写图形库。

 

posted @ 2020-10-03 17:35  s0cket  阅读(404)  评论(0)    收藏  举报