APUE读书笔记-05标准输入输出库(2)

作者 : 开心源码 本文共5518个字,预计阅读时间需要14分钟 发布时间: 2022-05-13 共199人阅读

5、打开和关闭流

三种打开流的方式: fopenfreopenfdopen 其原型如下:

#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);

三者返回:假如成功返回文件指针,假如错误返回 NULL

这里:
fopen 打开路径名由 pathname 指定的文件。

fdopen 可以接受一个已经打开的文件形容符号,将这个文件形容符和标准输入输出流关联。这样可以实现对除了磁盘 normal 文件之外的其余特殊文件进行流的操作(例如,有些特殊文件不能用 fopen 打开,那么可以先通过 open 或者者 pipe 等获取其文件形容符浩,再用这个函数将其与标准流关联)。

freopen 在一个特定的流上(由 fp 指示)打开一个指定的文件(其路径名由 pathname 指示)如若该流已经打开,则先关闭该流。此函数常用于将一个指定的文件打开为一个预约义的流:标准输入、标准输出或者标准出错。

ISO Ctype 参数指定了如下15种值:

                                打开一个标准输入输出流的类型参数+------------------------------------------------------------------------------------+|       type       |                           Description                           ||------------------+-----------------------------------------------------------------|| r or rb          | open for reading                                                ||------------------+-----------------------------------------------------------------|| w or wb          | truncate to 0 length or create for writing                      ||------------------+-----------------------------------------------------------------|| a or ab          | append; open for writing at end of file, or create for writing  ||------------------+-----------------------------------------------------------------|| r+ or r+b or rb+ | open for reading and writing                                    ||------------------+-----------------------------------------------------------------|| w+ or w+b or wb+ | truncate to 0 length or create for reading and writing          ||------------------+-----------------------------------------------------------------|| a+ or a+b or ab+ | open or create for reading and writing at end of file           |+------------------------------------------------------------------------------------+

使用 b 作为 type 的一部分,使标准 I/O 系统可以区分文本文件和二进制文件。但是由于 UNIX 内核并不对这两种文件进行区分,所以在 UNIX 系统环境下指定字符b作为 type 的一部分实际上并没有什么作用。

对于 fdopentype 参数的意义稍有不同。由于该形容符已被打开,所以 fdopen 以写方式打开时并不截短该文件。(例如,若该形容符原来是由 open 函数打开的,该文件那时已经存在,则其 O_TRUNC 标志将决定能否截短该文件。 fdopen 函数不能截短它为写而打开的任一文件。)另外,标准 I/O 以追加方式操作,也不能用于创立该文件(由于如若一个形容符引用一个文件,则该文件肯定已经存在) 。

当用追加方式打开一文件后,则每次写都将数据写到文件的当前尾端处。如若有多个进程用标准 I/O 增加方式打开了同一文件,那么来自每个进程的数据都将正确地写到文件中。

当以读和写类型打开一文件时( type+ 号),具备下列限制:
a)假如中间没有 fflushfseekfsetpos 或者 rewind ,则在输出的后面不能直接跟随输入。
b)假如中间没有 fseekfsetpos 或者 =rewind = ,或者者一个输出操作没有到达文件尾端,则在输入操作之后不能直接跟随输出。

根据上表,下表列出了打开一个流的六种不同方式。

                        六种打开标准输入输出流的方法+-----------------------------------------------------------------+|             Restriction              | r | w | a | r+ | w+ | a+ ||--------------------------------------+---+---+---+----+----+----|| file must already exist              | ? |   |   | ?  |    |    ||--------------------------------------+---+---+---+----+----+----|| previous contents of file discarded  |   | ? |   |    | ?  |    ||--------------------------------------+---+---+---+----+----+----|| stream can be read                   | ? |   |   | ?  | ?  | ?  ||--------------------------------------+---+---+---+----+----+----|| stream can be written                |   | ? | ? | ?  | ?  | ?  ||--------------------------------------+---+---+---+----+----+----|| stream can be written only at end    |   |   | ? |    |    | ?  |+-----------------------------------------------------------------+

注意,在指定 w 或者 a 类型创立一个新文件时,我们无法说明该文件的存取许可权位( open 函数和 creat 函数则能)。假如流引用的不是终端设施,那么系统默认,它被打开时是全缓存的。假如流引用终端设施,则该流是行缓存的。打开流之后,在对该流执行任何操作之前,可使用前面所述的 setbufsetvbuf 改变缓存的类型。

可以调用 fclose 关闭一个打开的流。公告如下:

#include <stdio.h>int fclose(FILE *fp);

返回:假如成功返回0,假如错误返回 EOF

在文件被关闭之前,会将任何缓存中的输出数据刷新,而缓存中的输入数据被丢弃。假如标准 I/O 库已经为该流自动分配了一个缓存,则释放此缓存。当一个进程正常终止时(直接调用 exit 函数,或者从 main 函数返回),则所有带未写缓存数据的标准 I/O 流都被刷新,所有打开的标准 I/O 流都被关闭。

译者注

原文参考

参考: APUE2/ch05lev1sec5.html

6、关于流的读写

当打开一个 stream 的时候,我们可以有三种方式读写其中的内容.例如: fgetc , fputc .

  1. 字符方式。一次读写一个字符,假如 stream 有缓存那么由标准输入输出函数自己管理缓存。
  2. 行方式。一次读写一行。例如 fputs , fgets .
  3. 直接方式。在 ISO C 中的直接方式,也有时候被称作 binary I/O (二进制方式), object-at-a-time I/O (一次一个对象), record-oriented I/O (面向记录), structure-oriented I/O (面向结构)。每次读写指定的大小。例如 fread , fwrite .

(1)输入函数

有三个函数,可以每次读取输入的一个字符,公告如下:

#include <stdio.h>int getc(FILE *fp);int fgetc(FILE *fp);int getchar(void);

三者返回:假如成功返回下一个字符;否则到达文件结尾返回 EOF ,或者者错误。

三个函数都以单个字符的方式操作流。

getchargetc ( stdin )一样。 getcfgetc 的区别是 getc 可能是一个宏定义而 fgetc 肯定是一个函数的实现。三者都返回一个 unsigned char 并转化成为 int .这样返回值非负。不能用其返回值和 EOF 比较。判断文件结束有另外的方法。

当读取文件错误或者者到达文件结尾的时候,返回值一样,这时候,需要通过 ferrorfeof 才能加以区别。其公告如下:

#include <stdio.h>int ferror(FILE *fp);int feof(FILE *fp);void clearerr(FILE *fp);

两者返回:假如条件符合则返回 true (非0),否则 false

FILE 对象中为每一个 stream 维护一个 error flagend of file flag 。就是通过这两个函数进行判断的。使用 clearerr 可以清理这两个标记。

从流中读取之后,我们也可以通过 ungetc 函数将字符推送到流中,公告如下:

#include <stdio.h>int ungetc(int c, FILE *fp);

返回:假如成功返回c,假如错误返回 EOF

这个函数可以把一个字符推送回到流中,下次读取的时候就会读到那个字符了。

注意这个函数只是把一个字符推送到流里面了,并没有写这个流对应的实际文件。不能把 EOF 推送到 stream 中。当推送一个字符到 stream 中成功的时候,会自动清理 end of file flag

(2)输出函数

我们也可看到相应于前面探讨的输入函数的输出函数,公告如下:

#include <stdio.h>int putc(int c, FILE *fp);int fputc(int c, FILE *fp);int putchar(int c);

三者返回:假如成功返回c,假如错误返回 EOF

这三个函数和 getc , fgetc , getchar 相似,不过是写而不是读取了。 putchar (c)等价于 putc (c, stdout ), putc 可以用宏的方式实现而 fputc 不能用宏实现。

译者注

原文参考

参考: APUE2/ch05lev1sec6.html

7、行输入输出

下面两个函数提供行输入功能:

#include <stdio.h>char *fgets(char *restrict buf, int n, FILE *restrict fp);char *gets(char *buf);

返回:假如成功返回 buf ,假如失败或者者到达文件结尾返回 NULL

两者以行的方式操作流。 fgets 需要指定缓存的大小,而后读取一行,读取的结果包含 new line 和一个 null 结束。假如行长超过了n,那么就读取到n,最后也包含一个 null 字符(需要仔细调查???),反正 fgets 最多读取 n-1 个字符。 gets 已经逐步被淘汰了,由于没有指定缓存大小,不安全,另外它并不把 newline 存放到 buffer 中。

下面是一个例子:

/*程序功能: 使用fgets读取文件的一行,并且打印出来。*/#include <stdio.h>int main(int argc, char *argv[]){        char chars[256];        FILE *f = fopen("./test","r");        while(!feof(f))        {                   fgets(chars,256,f);//注意回车也都读取了                printf("%s",chars,ftell(f));                //printf("%s:%ld",chars,ftell(f));        }           fclose(f);        return 0;}

下面两个函数提供行输出功能:

#include <stdio.h>int fputs(const char *restrict str, FILE *restrict fp);int puts(const char *str);

两者返回:假如成功返回非负,否则返回 EOF

fputs 会把一个 null 结束的字符串写到一个指定的 stream 中。结尾的 null 字节并不会被写入。需要注意的是,这个函数并不肯定是一次一行的输出,由于输出的字符串并不需要把 newline 作为最后的非空字符。一般来说,最后一个非空字符会是 newline 字符,但是这不是必需的。

puts 函数会把 null 字符串写入到标准输出,但是不会写入空字符。另外, puts 还会把一个 newline 字符输出到标准输出。

puts 函数是安全的,而不像相应的 gets 。然而,我们也要避免使用它,否则还要记住它要在输出的最后追加一个 newline 字符。假如我们始终使用 fgetsfputs ,我们会知道我们怎么解决每一行最后的一个 newline 字符。

译者注

原文参考

参考: APUE2/ch05lev1sec7.html

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » APUE读书笔记-05标准输入输出库(2)

发表回复