文件IO
流的概念:
计算机有大量不同设备,很多都与IO操作有关,如CD-ROM驱动器、显示器、键盘、鼠标网卡、通信端口等
操作系统为程序员提供简单统一的接口来实现对这些设备的IO操作。就C程序而言,所有的IO只是简单地从
程序移入移出字节的事情,这种操作的对象就是字节流,简称为流,程序员只需要正确地读写数据,其实现
细节是不可见的。
缓冲区:
1、 绝大多数流是完全缓冲的,所谓读写操作实际上是从一块被称为缓冲区的内存区域来回复制数据。
2、 用于输出流的缓冲区只有当它被写满时才会被刷新到设备或文件中。
一次性把被写满的缓冲区写入与逐片把程序产生的输出分别写入相比效率更高。
比如相同的工作量,一次性做完总是比每次做一点需要多次才能完成的效率更高。
3、 同样的道理,输入缓冲区当它为空时通过从设备或文件读取一块较大的输入来填充缓冲区。
4、 使用标准输入和标准输出时,这种缓冲可能会引起混淆,只有当操作系统断定他们与交互设备并无联系
时才会进行完全缓冲。
一个常见的解决办法就是把标准输入和标准输出联系到一起,就是当请求输入时刷新输出缓冲区。一个
很普遍的例子就是在用户必须进行输入之前,提示用户进行输入的信息和以前写入到输出缓冲区的内容会
显示到屏幕上。
5、 有一点需要注意的是许多人调试程序的时候会将printf散布到错误可能出现的位置进行调试。事实上,程
序如果失败,输出缓冲可能不会被立即刷新,结果可能不会立即显示于屏幕上。一个可行的办法就是在printf
后面加上fflush来刷新缓冲区。
文本流和二进制流:
流分为文本流和二进制流。
文本流的有些特性在不同系统中可能不同
其中之一就是文本的最大长度,标准规定最少是254个字符,但还是要视具体系统而定。
另一个就是文本行的结束方式,在MS-DOS系统中,文本文件以/r/n结尾,在Linux系统中为/n结尾,在Linux系统中为/n
二进制流完全根据程序编写的形式写入到文件或设备中,不做任何改变,比较适合非文本数据。
关于EOF*******************************
一个程序最多能打开多少文件?
这和编译器有关,FOPENMAX常量包括了三个标准流,值至少是8
流IO:
在C程序中,为了执行与文件相关的IO任务方便,规定了文件IO的一般概况
1、程序为必须同时处于活动状态的每个文件声明一个指针变量,其类型为FILE*。这个指针指向FILE这个结构
当它处于活动状态是由流使用。
FILE* fopen(char const* name, char const* mode);
FILE* freopen(const char* filename, const char* mode, FILE* stream);
//最后一个参数是需要大开的流,可能是一个先前从fopen函数返回的流,也可能是三个标准,这个函数试图先关闭这个流,然
//后用这顶的文件和模式重新打开这个流,失败返回NULL,成功返回第三个参数值。
name为文件名
mode为权限 文本: r(读) w(写) a(追加)
二进制:rb wb ab
如果打开一个流是用于读的,那么对应的文件必须是已经存在的;如果是用于写的,如果已经存在就覆盖,否则创建;
追加表示如果在源文件内容尾部进行写,文件不存在时创建。
fseek:
fsetpos:
rewind:
fflush:
2、流通过调用fopen而被打开,为了打开一个流必须指出需要访问的文件以及访问方式。(不一定成功)
3、然后才能对该文件进行读取或写入。
4、关闭流保证与其相关联的文件被再次访问,保证任何存储与缓冲区的数据被正确地写入到文件中,
同时释放FILE结构
int fclose(FILE* f); 对于输出流,fclose在关闭文件之前会刷新缓冲区。成功返回0, 否则返回EOF
更严格地说,关闭流也要检查返回值
IO函数以三种基本形式处理数据:单个字符,问本行,二进制数据
区别在于获得输入来源或输入写入的地方不同。
输入 输出 描述
字符: getchar(fgetc/getc) putchar(fputc/putc) 读写单个字符
文本行: gets(fgets)/scanf(fscanf) puts(fputs)/printf(fprintf) 文本行的未格式化读写/格式化读写
二进制数据:fread fwrite 读写二进制数据
注:括号中的函数适用所有输出输出流,其余只适用于标准输入输出流
字符IO
读:从流中读取数据
int fgetc(FILE* stream);
int getc(FILE* stream);
int getchar(void);
将需要操作的流作为参数传给getc和fgetc,getchar始终从标准输入读取。这三个函数从六中读取下一个字符,作为函数
的返回值返回,如果字符不存在更多的字符,函数就返回常量值EOF。之所以读取字符而返回int型值是为了允许函数报告文件的结尾
EOF的值在任何可能出现的字符范围之外。
写:把单个字符写入到流中, 写的时候函数会将整型参数裁剪为一个无符号字符型值
int fputc(int character, FILE* stream);
int putc(int character, FILE* stream);
int putchar(int charater);
其实fgetc和fputc都是真正的函数,而getc, putc, getchar和putchar都是宏。
ungetc(int charater, FILE* stream); //拿出来看一下
格式化的行IO
int scanf(char const* format, ...);
int fscanf(FILE* stream, char const* format, ...); //从stream中读取format格式的字符
int sscanf(char const* string, char const* format, ...); //从string字符串中读取format格式的字符
int printf(FILR* format, ...);
int fprintf(FILE* stream, const char* format, ...);
int sprintf(char* buffer, const char* format, ...); //同上
二进制IO
size_t fread(void* buff, size_t size, size_t count, FILE* stream);
size_t fwrite(void* buff, size_t size, size_t count, FILE* stream);
//size是缓冲区中每个元素的字节数,count是读取或写入的元素数, stream是流
定位函数:
long ftell(FILE* stream); //返回流的当前位置,也就是下一个要读写的位置距离起始位置的偏移量
int fseek(FILE* stream, long offset, int from); //改变下一次读写的位置,stream是需要操作的流,后两个分别为偏移量和从offset到哪里
副作用:1、行末知识字符被清除
2、如果在fseek之前使用ungetc把一个字符返回到流中,那么这个返回的字符会被丢弃,因为在定位操作之后它不再是下一个字符
void rewind(FILE* stream); //将读写指针返回起始位置
from的值可以是:
SEEK_SET:从留的起始位置起offset个字节,offset必须非负
SEEK_CUR:从当前位置其offset个字节,offset可正可负
SEEK_END:从流的尾部起offset个字节,offset如果为正值将定位到文件尾的后面
C语言 IO 部分整理
猜你喜欢
转载自blog.csdn.net/IronMan240/article/details/82378900
今日推荐
周排行