linux文件读写总结,Linux系统C语言读写文件总结 (二)

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,并被定义在头文件中。到这儿了就可以回想下这三个特殊文件对应的文件描述符。

3. 缓冲

标准I/O提供了三种类型的缓冲:

(1)全缓冲。

(2)行缓冲。

(3)不带缓冲。

4. 打开和关闭流

打开流,成功返回文件指针,否则返回NULL

#include

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

int fclose(FILE *fp);

5. 读和写流(非格式化)

三种不同类型的非格式化I/O:

(1)每次一个字符的I/O。

输入函数

#include

int getc(FILE *fp);

int fgetc(FILE *fp);

int getchar(void);成功则返回下一个字符,若已达到文件结尾或出错则返回EOF。

getc可以实现为宏(更快),而fgetc则只能是函数;getchar等价于getc(stdin)。

其对应的输出函数为

#include

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

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

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

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

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, F

double精度浮点数

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

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

有符号十进制,基数为10

i

有符号十进制,基数由输入格式决定

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

long ftell(FILE *fp);

//成功则返回当前文件位置指示,出错返回-1L

int fseek(FILE *fp, long offset, in whence);

//成功返回0,出错返回非0值

void rewind(FILE *fp);

//将一个流设置到文件的起始位置

#include

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

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时,可以使用此值将流重新定位至该位置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值