APUE第5章标准I/O库 笔记

5 篇文章 0 订阅

1.系统调用是以文件描述符进行I/O操作的,标准I/O是c语言,是围绕流stream进行的。

2.文件描述符是STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO分别表示标准输入,输出,出错。流是stdin,stdout,stderr。

3.系统函数open,read,write,close等称为无缓冲函数。因为他们处于c标准的I/O缓冲区的底层。无缓冲函数每次读写都要进入内核,调一个系统调用比调一个用户空间函数慢很多,所以在用户空间开辟缓冲区是必要的。

4.用c标准I/O函数时要时刻注意I/O缓冲区和实际文件可能不一致,必要时调用fflush();

5.网络编程时不希望使用缓冲,所以使用系统函数。

6.标准I/O分为3种类型的缓存:行缓存,全缓存,无缓存。

全缓存:当填满缓冲区时才进行实际I/O操作。在一个流上执行第一次I/O操作,通常调用了malloc函数获得要使用的缓存。

行缓存:当在输入和输出中遇到换行时,标准I/O执行I/O操作。行缓存的长度是有限制的,当行满了后也会执行I/O操作。

无缓存:如stderr

ANSIC要求下列缓存特征:

1.当前仅当标准输入输出不涉及交互设备时,才是全缓存的。

2.标准出错决不会是全缓存的。

可以使用下列函数改变流的缓存模式:

void setbuf(FILE *fp,char *buf);

int setvbuf(FILE *fp,char *buf,int mode,size_t size);

setbuf函数具有打开和关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ(定义在stdio.h头文件中)的缓冲区。

通常在此之后该流就是全缓冲的,但是如果该流与一个终端设备相关,那么某些系统也可以将其设置为行缓冲。为了关闭缓冲,可以将buf参数设置为NULL。

setvbuf通过mode设置缓存模式,_IOFBF全缓存,_IOLBF行缓存,_IONBF无缓存。

强制刷新流int fflush( FILE *stream);如果stream是NULL,则刷新所有流。

7.打开流

#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:
  type  说明
  r或rb  为读而打开
  w或wb  把文件截短至0长,或为写而打开
  a或ab  添加;为在文件尾写而打开,或为写而创建
  r+或r+b或rb+ 为读和写而打开
  w+或w+b或wb+ 把文件截短至0长,或为读和写打开
  a+或a+b或ab+ 为在文件尾读和写而打开或创建

由于unix不区分二进制文件,所以b是无效的。
 int fclose(FILE *fp);//关闭流,刷新缓存中的输出数据,丢弃输入数据,释放缓存。

当以读和写类型打开一个文件时(type中+号),具有下列限制:

如果中间没有fflush、fseek、fsetpos或rewind,则在输出的后面不能直接跟随输入。

如果中间没有fseek、fsetpos或rewind,或者一个输出操作没有达到文件尾端,则在输入操作之后不能直接跟随输出。

8.读和写流
 #include <stdio.h>
 int getc(FILE *fp);//实现可能是宏,宏的效率比函数快,但参数不能有副作用。
 int fgetc(FILE *fp);
 int getchar(void);//等价于getc(stdin)
 返回值:成功则返回下一个字符,到达文件尾部或出错返回EOF;为了区分要使用ferror或者feof函数
 int ferror(FILE *fp);
 int feof(FILE * fp);
 返回值:条件为真返回非0值,否则返回0;
 void cleanerr(FILE *fp);//清除流的出错标志和文件结束标志
 int ungetc(int c, FILE *fp);//将字符送回流中
 返回值:成功返回c,出错返回EOF;
 int putc(int c, FILE *fp)//输出字符,该实现可以是宏
 int fputc(int c, FILE *fp);
 int putchar(int c);//等价于putc(c,stdout);

9.每次一行I/O
 char *fgets(char *restrict buf, int n, FILE *restrict fp);//读取一行但不超过n-1个字符,读入的字符被送入缓存。该缓存以null字符或者换行结尾。成功时

返回字符串,失败返回NULL
 char *gets(char *buf);//不推荐
 int fputs(const char *restrict str, FILE *restrict fp);//写字符串,成功时返回非负值, 失败时返回EOF
 int puts(const char *str);//成功时返回非负值, 失败时返回EOF

10.读写二进制文件,int fread( void *buffer, size_t size, size_t num, FILE *stream );

函数fread()读取[num]个对象(每个对象大小为size(大小)指定的字节数),并把它们替换到由buffer(缓冲区)指定的数组. 数据来自给出的输入流. 函数的返回值是读取的内容数量。

如果返回值小于num,则是发生错误或者到达文件结束。使用feof()ferror()判断到底发生哪个错误。

int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );fwrite()函数从数组buffer(缓冲区)中, 写count个大小为size(大小)的对象到stream(流)指定的流. 返回值是已写的对象的数量。如果少于count则表示出错。

这两个函数常用方法是读写数组,或者是结构体。

#include<stdio.h>
#include<string.h>
struct Data
{
        int a;  
        int b;  
};
int main(void)
{
        FILE*stream;
        Data msg={1,2};
        Data msg2;
        if((stream=fopen("DUMMY.FIL","w+"))==NULL)
        {       
                fprintf(stderr,"Cannotopenoutputfile.\n");
                return 0;
        }       
        /*write some data to the file*/
        fwrite(&msg,sizeof(Data),1,stream);
        /*sizeof(char)=1seektothebeginningofthefile*/
        fseek(stream,0,SEEK_SET);
        /*readthedataanddisplayit*/
        fread(&msg2,sizeof(Data),1,stream);
        printf("%d %d\n",msg2.a,msg2.b);
        fclose(stream);
        //remove("DUMMY.FIL");
        return 0;
}

11.定位流long ftell( FILE *stream );//返回当前的文件位置,出错返回-1

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

函数fseek()为给出的流设置位置数据. origin的值应该是下列值其中之一(在stdio.h中定义):

名称说明
SEEK_SET从文件的开始处开始搜索
SEEK_CUR从当前位置开始搜索
SEEK_END从文件的结束处开始搜索

fseek()成功时返回0,失败时返回非零. 你可以使用fseek()移动超过一个文件,但是不能在开始处之前.
 void rewind(FILE *fp)//函数rewind()把文件指针移到由stream(流)指定的开始处, 同时清除和流相关的错误和EOF标记.
 int fgetpos(FILE *restrict fp, fpos_t *restrict pos)//fgetpos()函数保存给出的文件流(stream)的位置指针到给出的位置变量(pos)中.

 pos变量是fpos_t类型的(它在stdio.h中定义)并且是可以控制在FILE中每个可能的位置对象. fgetpos()执行成功时返回0,失败时返回一个非零值
 int fsetpos(FILE *fp, const fpos_t *pos)//fsetpos()函数把给出的流的位置指针移到由position对象指定的位置. fpos_t是在stdio.h中定义的. fsetpos()执行成功返回0,失败时返回非零.

12.格式化输出

int printf( const char *format, ... );//printf()的返回值是打印的字符数,如果发生错误则返回一个负值

int fprintf( FILE *stream, const char *format, ... );//fprintf()函数根据指定的format(格式)(格式)发送信息(参数)到由stream(流)指定的文件. fprintf()只能和printf()一样工作. fprintf()的返回值是输出的字符数,发生错误时返回一个负值

int sprintf( char *buffer, const char *format, ... );//sprintf()函数和printf()类似, 只是把输出发送到buffer(缓冲区)中.返回值是写入的字符数量

int vprintf( char *format, va_list arg_ptr );

int vfprintf( FILE *stream, const char *format, va_list arg_ptr );

int vsprintf( char *buffer, char *format, va_list arg_ptr );

13.格式化输入

int scanf( const char *format, ... );//scanf()读取匹配format(格式)字符串的输入. 当读取到一个控制字符, 它把值放置到下一个变量. 空白(tabs, 空格等等)会跳过. 非空白字符和输入匹配, 然后丢弃. 如果是一个在%符号和控制符间的数量, 那么只有指定数量的字符转换到变量中. 如果scanf()遇到一个字符集(用%[]控制字符表示), 那么在括号中的任意字符都会读取到变量中. scanf()的返回值是成功赋值的变量数量, 发生错误时返回EOF

int fscanf( FILE *stream, const char *format, ... );//函数fscanf()以scanf()的执行方式从给出的文件流中读取数据. fscanf()的返回值是事实上已赋值的变量的数,如果未进行任何分配时返回EOF

int sscanf( const char *buffer, const char *format, ... );//函数sscanf()和scanf()类似, 只是输入从buffer(缓冲区)中读取

int fileno(FILE *stream);//取得流的文件描述符

14.临时文件

char *tmpnam( char *name );//tmpnam()函数创建一个独特的文件名并保存在name中. tmpnam()最多可以调用TMP_MAX指定的次数

FILE *tmpfile( void );//函数tempfile()用一个独特的文件名打开一个临时文件,并返回一个到该文件的指针.如果发生错误则返回null,程序结束则自动删除该文件


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值