Linux系统C语言读写文件总结 (二)
来源:互联网 发布:odysseus windows 编辑:程序博客网 时间:2024/05/09 22:40
1. 概述
这里所说的是标准I/O库。以标准二字限定,是因为接下来介绍的I/O函数由ISO C标准说明并在诸多操作系统上都进行了实现,包括UNIX like OS, Linux, Mac, Windows等。标准I/O库处理了很多细节,例如缓冲区分配,以优化长度执行I/O等。这些处理使得用户不必担心如何使用正确的块长度,从而大大提高了开发效率。
标准I/O库实际上就是在我在上一片博客(Linux系统C语言读写文件总结 (一))中提到的基本I/O操作函数(read,write等)的一个封装。标准I/O函数操作对应的是于文件相关的流(用文件指针FILE *进行表示),而不是文件描述符(fd)。一个FILE结构中包括了实际操作文件的文件描述符,指向用于该流缓冲区的指针,缓冲区的长度,当前在缓冲区中的字符数以及出错标志等等。
此外流的定向分为面向单字节的和多字节字符集。freopen函数可以用来清除流的定向,fwide函数可以用来设置流的定向。
2. 标准输入,标准输出和标准出错
有几个特殊的流,对应于标准输入,标准输出和标准出错。他们的文件指针分别是stdin, stdout和stderr,并被定义在头文件<stdio.h>中。到这儿了就可以回想下这三个特殊文件对应的文件描述符。
3. 缓冲
标准I/O提供了三种类型的缓冲:
(1)全缓冲。
(2)行缓冲。
(3)不带缓冲。
4. 打开和关闭流
打开流,成功返回文件指针,否则返回NULL
#include<stdio.h> FILE *fopen(const char *restrict pathname, const char *restrict type); FILE *freopen(const char *restrict pathname, const char *restrict type, FILE *restrict fp); FILE *fdopen(int filedes, const char *type);type指定对该I/O流的读写方式,ISO C规定该参数有15种不同的值,如下
type说明r或rb
w或wb
a或ab
r+或r+b或rb+
w+或w+b或wb+
a+或a+b或ab+为读而打开
把文件截短至0长,或为写而创建
添加;为在文件尾写而打开,或为写而创建
为读和写而打开
把文件截短至0长,或为读和写而打开
为在文件尾读和写而打开或创建
注:这里r+, w+, a+都可以对文件进行写。区别在于以r+方式打开,文件位置指向文件开头;以w+方式打开,会将原文件长度截短为0;以a+方式打开会将文件位置指向文件结尾处,并且将结尾处作为文件位置的开始,fseek函数也不能将文件位置指向开头处。所以这也就解释了我的疑问:为什么会有r+的存在。
关闭流,成功返回0,否则返回EOF
#include<stdio.h> int fclose(FILE *fp);
5. 读和写流(非格式化)
三种不同类型的非格式化I/O:
(1)每次一个字符的I/O。
输入函数
#include<stdio.h> int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void);成功则返回下一个字符,若已达到文件结尾或出错则返回EOF。
getc可以实现为宏(更快),而fgetc则只能是函数;getchar等价于getc(stdin)。
其对应的输出函数为
#include<stdio.h> int putc(int c, FILE *fp); int fputc(int c, FILE *fp); int putchar(int c);成功则返回c,否则返回EOF。
putc可以实现为宏(更快),而fputc则只能是函数;putchar等价于putc(c, stdout)。
(2)每次一行的I/O。
输入函数
#include<stdio.h> char *fgets(char *restrict buf, int n, FILE *restrict fp); char *gets(char *buf);成功则返回buf,若已达到文件结尾或出错则返回NULL。
fgets从指定流读,而gets从标准输入读。fgets必须指定缓冲区的长度n,此函数一直读到下一个换行符为止,但是不超过n-1(缓冲区以null结尾)个字符,读入的字符被送入缓冲区。
gets这是一个不推荐使用的函数。因为用户不能指定缓冲区的长度,可能造成缓冲区溢出。
其对应的输出函数为
#include<stdio.h> char *fputs(const char *restrict str, FILE *restrict fp); char *puts(const char *str);成功则返回非负值,否则返回EOF。
尽量避免使用gets和puts。使用fgets和fputs时需要记住在每行终止处必须处理换行符。
(3)直接I/O(二进制I/O)。
#include<stdio.h> size_t fread(void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp); size_t fwrite(const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp);返回值:读或写的对象数。
例子:
a. 写一个数组
float data[10]; if(write(&data[2], sizeof(float), 4, fp) != 4) err_sys("fwrite error");
b. 写一个结构体
struct{ short cout; long total; char name[NAMESIZE]; }item; if(fwrite(&item, sizeof(item), 1, fp) != fp) err_sys("fwrite error");
6. 格式化I/O
格式化输出
#include<stdio.h> int printf(const char *restrict format, ...); int fprintf(FILE *restrict fp, const char *restrict format, ...);//若成功则返回输出的字符数,若输出出错则返回负值 int sprintf(FILE *restrict buf, const char *restrict format, ...); int snprintf(FILE *restrict buf, size_t n, const char *restrict format, ...);//若成功则返回存入数组的字符数,如编码出错则返回负值
其中的format的描述形式如:%[flags][fldwidth][precision][lenmodifier]convtype
flags选项如下表
标志说明-在字段内左对齐输出+总是显示带符号转换的符号(空格)如果第一个字符不是符号,则在其前面加上一个空格#指定另外一种转换形式(例如,对于十六进制格式,加0x前缀)0添加前导0(而非空格)进行填充
fldwidth说明转换的最小字段宽度,如果转换得到的字符较少,则用空格填充它。字段宽度是一个非负十进制数,或是一个星号(*)。
precision说明整型转换后最少输出数字位数,浮点数转换后小数点后的最少位数,字符串转换后的最大字符数。精度时一个句号(.),后接一个可选的非负十进制整数或一个星号(*)。
转换类型选项如下表
转换类型说明d, i有符号十进制o无符号八进制u无符号十进制x, X无符号十六进制f, Fdouble精度浮点数e, E指数格式的double精度浮点数g, G解释为f, F或e, E,取决于被转换的值a, A十六进制指数格式的double精度浮点数c字符(若带长度修饰符l,则为宽字符)s字符串(若带长度修饰符l,则为宽字符)p指向void的指针n将到目为止,所写的字符数写入到指针所指向的无符号整型中%%字符C宽字符(XSI扩展,等效于lc)S宽字符串(XSI扩展,等效于ls)
格式化输入
#include<stdio.h> int scanf(const char *restrict format, ...); int fscanf(FILE *restrict fp, const char *restrict format, ...); int sscanf(FILE *restrict buf, const char *restrict format, ...); //若成功则返回指定的输入项数,如输入出错或在任意变换前已经到达文件结尾则返回EOF
format格式转换说明如下:%[*][fldwidth][lenmodifier]convtype
除转换说明和空白字符外,格式字符串中的其他字符必须与输入匹配。若有一个字符不匹配,则停止后续处理,不再读输入的其他部分。
*用于抑制转换。
fldwidth说明最大宽度(即最大字符数)。
lenmodifier说明要用转换结果初始化的参数大小。
转换类型选项如下表。与print族有些类似,但是也有所差别。一个差别是,存储在无符号类型中的结果可在输入时带上符号。例如,-1可被转换成4,294,967,295赋予无符号整型变量。
转换类型说明d有符号十进制,基数为10i有符号十进制,基数由输入格式决定o无符号八进制(输入可选地有符号)u无符号十进制,基数为10(输入可选地有符号)x无符号十六进制(输入可选地有符号)a, A, e, E, f, F, g, G浮点数c字符(若带长度修饰符l,则为宽字符)s字符串(若带长度修饰符l,则为宽字符)[匹配列出的字符序列,以 ] 终止[^匹配列出字符序列以外的所有字符,以 ] 终止p指向void的指针n将到目为止读取的字符数写入到指针所指向的无符号整型中%%字符C宽字符(XSI扩展,等效于lc)S宽字符串(XSI扩展,等效于ls)
7. 定位流
#include<stdio.h> long ftell(FILE *fp); //成功则返回当前文件位置指示,出错返回-1L int fseek(FILE *fp, long offset, in whence); //成功返回0,出错返回非0值 void rewind(FILE *fp); //将一个流设置到文件的起始位置
#include<stdio.h> off_t ftello(FILE *fp); //成功返回当前文件位置指示,出错则返回-1 int fseeko(FILE *fp, off_t offset, int whence); //成功则返回0,出错则返回非0值除了offset的类型时off_t而非long外,ftello函数和ftell相同,fseeko和fseek相同
#include<stdio.h> int fgetpos(FILE *restrict fp, fpos_t *restrict pos); int fsetpos(FILE *fp, const fpos_t *pos); //成功则返回0,出错则返回非0值这两个函数时ISO C标准引入的。如果程序要移植到非UNIX系统,则可以使用该函数。其中fgetpos将文件位置指示器的的当前值存入到由pos指向的对象中。在以后调用fsetpos时,可以使用此值将流重新定位至该位置。
- Linux系统C语言读写文件总结 (二)
- Linux系统C语言读写文件总结 (一)
- linux下的系统级c语言文件读写操作
- Linux C语言文件读写
- C语言中常用的文件读写方法(二)
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- C语言文件读写操作总结
- LINUX C语言文件的读写(非二进制)
- Linux与C语言的文件读写
- c语言读写文件
- 软件自动化测试工具介绍
- UIButton详解
- iOS开发之 MVVM的架构设计与团队协作的重要性
- stl的sort和手写快排的运行效率哪个比较高?
- 666666666
- Linux系统C语言读写文件总结 (二)
- 鸟哥的Linux私房菜-学习笔记-第二章【Linux 如何学习】
- 8888888888888888
- 删除链表中(不带头结点)值为value的结点,返回删除的个数
- js的字符串替换函数replace
- rails校验
- shell 统计出上个月中旬到本月中旬的所有工作日
- Libevent源码学习(一) 支持多种网络模型原理
- 修改文件后浏览器自动刷新解决方案