- 浏览: 140805 次
文章分类
最新评论
一旦打开了流,则可在 3 种不同类型的非格式化 I/O 中进行选择,对其进行读、写操作。
(1) 每次一个字符的 I/O。如果流是带缓冲的,则标准 I/O 函数处理所有缓冲。
(2) 每次一行的 I/O。
(3) 直接 I/O,有时也被称为二进制 I/O。fread 和 fwrite 函数支持这种类型的 I/O。每次 I/O 操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数通常用于从二进制文件中每次读或写一个结构。
以下 3 个函数可用于一次读一个字符。
函数 getchar 等同于 getc(stdin)。前两个函数的区别是:getc 可被实现为宏,而 fgetc 不能。这就意味着以下几点。
1、getc 的参数不应当是具有副作用的表达式,以免被计算多次。
2、因为 fgetc 一定是一个函数,所以可以得到其地址。因此允许将 fgetc 的地址作为另一个函数的参数。
为了区分是出错还是到达尾端,必须调用 ferror 或 feof。
在大多数实现中,每个流在 FILE 对象中都维护了两个标志:出错标志和文件结束标志。调用 clearerr 可以清除这两个标志。
从流中读取数据以后,可以调用 ungetc 将字符再压送回流中。
压送回流中的字符以后又可以与压送回的顺序相反的顺序从流中读出。回送的字符,不一定必须是上一次读到的字符。不能回送 EOF,但是当已经到达文件尾端时,仍可以回送一个字符。下次读将返回该字符,再读则返回 EOF。这样做的原因是,一次成功的 ungetc 调用会清除该流的文件结束标记。
当正在读一个输入流,并进行某种形式的切词或记号切分操作时,会经常用到回送字符操作。有时需要先看一看下一个字符,以决定如何处理当前字符。然后就需要方便地将刚查看的字符回送,以便下一次调用 getc 时返回该字符。
用 ungetc 压送回字符时,并没有将它们写到底层文件中或设备上,只是将它们写会标准 I/O 库的流缓冲区中。
对应于上面所述的每个输入函数都有一个输出函数。
同输入函数一样,putchar(c) 等同于 putc(c, stdout),putc 可被实现为宏,而 fputc 不能。
下面再来介绍一下每次输入一行的函数。
gets 从标准输入读,而 fgets 则从指定的流读。
对于 fgets,必须指定缓冲的长度 n。此函数一直读到下一个换行符为止,但不超过 n-1 个字符,读入的字符被送入缓冲区。该缓冲区以 null 字节结尾。如若该行包括最后一个换行符的字符数超过 n-1,则 fgets 只返回一个不完整的行,但是,缓冲区总是以 null 字节结尾,下一次调用会继续读该行。
gets 因为不能指定缓冲区的长度,从而可能造成缓冲区溢出,所以并不推荐使用。它与 fgets 的另一个区别是,gets 并不将换行符存入缓冲区中。
fputs 和 puts 是用于每次输出一行的函数。
函数 fputs 将一个以 null 字节终止的字符串写到指定的流,尾端的终止符 null 不写出。不过这并不一定是每次输出一行,因为字符串不需要换行符作为最后一个非 null 字节。puts 将一个以 null 字节终止的字符串写到标准输出,终止符不写出,但随后又将一个换行符写到标准输出。
注意,如果总是使用 fgets 和 fputs,那么必须记住在每行终止处需要自己处理换行符。
最后,我们再来讨论一下二进制 I/O 操作函数。
在进行二进制 I/O 操作时,一般都是一次读或写一个完整的结构。若使用 getc 或 putc,不仅麻烦还且费时;而若使用 fgets 或 fputs,又可能会因结构中含有 null 字节而停止。因此提供了下列两个函数。
这两个函数有两种常见的用法:
1、读或写一个二进制数组。例如将一个浮点数组的第 2~5个元素写至一个文件上:
if( fwrite(&data[2], sizeof(float), 4, fp) != 4){ /* 处理错误 */ }
2、读或写一个结构。例如:
struct{ /*...*/ }item;
if( fwrite(&item, sizeof(item), 1, fp) != 1){ /* 处理错误 */ }
将这两者结合起来,就可读或写一个结构数组。
fread 和 fwrite 返回读或写的对象数。对于读,如果出错或到达文件尾端,则此数字可以少于 nobj。此时应调用 ferror 或 feof 来判断究竟是哪一种情况。对于写,如果该数字少于 nobj,则表示出错。
使用二进制 I/O 的基本问题是,它只能用于读在同一系统上已写的数据。这对于现在很多通过网络相连起来的异构系统的情况,它们可能就不能正常工作。在不同系统之间交换二进制数据的实际解决办法是使用互认的规范格式。
要定位标准 I/O 流,主要有 3 种方法。
1、ftell 和 fseek 函数,但是它们都假定文件的位置可以存放在一个长整型中。
2、ftello 和 fseeko 函数,它们使用了 off_t 数据类型代替了长整型。
3、fgetpos 和 fsetpos 函数,它们使用一个抽象数据类型 fpos_t 记录文件的位置。这种数据类型可以根据需要定义为一个足够大的数,用以记录文件位置。需要移植到非 UNIX 系统上运行的应用程序应当使用这两个函数。
对于二进制文件,其文件位置是从文件起始位置以字节为单位开始度量。ftell 用于二进制文件时的返回值就是这种字节位置。fseek 中的 whence 的值同 lseek 函数,不过 ISO C 并不要求一个实现对二进制文件支持 SEEK_END 规格说明,因为有些系统要求二进制文件的长度是某个幻数的整数倍,结尾非实际内容部分则填充为 0(但是在 UNIX 中则是支持的)。
对于文本文件,它们的文件当前位置可能不以简单的字节偏移量来度量。因为非 UNIX 系统中可能以不同的格式存放文本文件。为了定位一个文本文件,whence 一定要是 SEEK_SET,而且 offset 只能为 0(后退到文件的起始位置)或是对该文件的 ftell 所返回的值。另外,使用 rewind 函数也可将一个流设置到文件的起始位置。
除了偏移量的类型是 off_t 以外,ftello/fseeko 函数与 ftell/fseek 相同。
fgetpos 将文件位置的当前值存入由 pos 指向的对象中,以后调用 fsetpos 时,可以使用此值将流重新定位至该位置。
(1) 每次一个字符的 I/O。如果流是带缓冲的,则标准 I/O 函数处理所有缓冲。
(2) 每次一行的 I/O。
(3) 直接 I/O,有时也被称为二进制 I/O。fread 和 fwrite 函数支持这种类型的 I/O。每次 I/O 操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数通常用于从二进制文件中每次读或写一个结构。
以下 3 个函数可用于一次读一个字符。
#include <stdio.h> int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void); /* 返回值:若成功,都返回下一个字符;若已到达文件尾端或出错,则都返回 EOF */
函数 getchar 等同于 getc(stdin)。前两个函数的区别是:getc 可被实现为宏,而 fgetc 不能。这就意味着以下几点。
1、getc 的参数不应当是具有副作用的表达式,以免被计算多次。
2、因为 fgetc 一定是一个函数,所以可以得到其地址。因此允许将 fgetc 的地址作为另一个函数的参数。
为了区分是出错还是到达尾端,必须调用 ferror 或 feof。
#include <stdio.h> int ferror(FILE *fp); int feof(FILE *fp); /* 返回值:若条件为真,都返回非 0;否则,都返回 0 */ void clearerr(FILE *fp);
在大多数实现中,每个流在 FILE 对象中都维护了两个标志:出错标志和文件结束标志。调用 clearerr 可以清除这两个标志。
从流中读取数据以后,可以调用 ungetc 将字符再压送回流中。
#include <stdio.h> int ungetc(int c, FILE *fp); /* 返回值:若成功,返回 c;否则,返回 EOF */
压送回流中的字符以后又可以与压送回的顺序相反的顺序从流中读出。回送的字符,不一定必须是上一次读到的字符。不能回送 EOF,但是当已经到达文件尾端时,仍可以回送一个字符。下次读将返回该字符,再读则返回 EOF。这样做的原因是,一次成功的 ungetc 调用会清除该流的文件结束标记。
当正在读一个输入流,并进行某种形式的切词或记号切分操作时,会经常用到回送字符操作。有时需要先看一看下一个字符,以决定如何处理当前字符。然后就需要方便地将刚查看的字符回送,以便下一次调用 getc 时返回该字符。
用 ungetc 压送回字符时,并没有将它们写到底层文件中或设备上,只是将它们写会标准 I/O 库的流缓冲区中。
对应于上面所述的每个输入函数都有一个输出函数。
#include <stdio.h> int putc(int c, FILE *fp); int fputc(int c, FILE *fp); int putchar(int c); /* 返回值:若成功,都返回 c;否则,都返回 EOF */
同输入函数一样,putchar(c) 等同于 putc(c, stdout),putc 可被实现为宏,而 fputc 不能。
下面再来介绍一下每次输入一行的函数。
#include <stdio.h> char *fgets(char *restrict buf, int n, FILE *restrict fp); char *gets(char *buf); /* 返回值:若成功,返回 buf;若已到达文件尾端或出错,返回 NULL */
gets 从标准输入读,而 fgets 则从指定的流读。
对于 fgets,必须指定缓冲的长度 n。此函数一直读到下一个换行符为止,但不超过 n-1 个字符,读入的字符被送入缓冲区。该缓冲区以 null 字节结尾。如若该行包括最后一个换行符的字符数超过 n-1,则 fgets 只返回一个不完整的行,但是,缓冲区总是以 null 字节结尾,下一次调用会继续读该行。
gets 因为不能指定缓冲区的长度,从而可能造成缓冲区溢出,所以并不推荐使用。它与 fgets 的另一个区别是,gets 并不将换行符存入缓冲区中。
fputs 和 puts 是用于每次输出一行的函数。
#include <stdio.h> int fputs(const char *restrict str, FILE *restrict fp); int puts(const char *str); /* 返回值:若成功,都返回非负值;否则,都返回 EOF */
函数 fputs 将一个以 null 字节终止的字符串写到指定的流,尾端的终止符 null 不写出。不过这并不一定是每次输出一行,因为字符串不需要换行符作为最后一个非 null 字节。puts 将一个以 null 字节终止的字符串写到标准输出,终止符不写出,但随后又将一个换行符写到标准输出。
注意,如果总是使用 fgets 和 fputs,那么必须记住在每行终止处需要自己处理换行符。
最后,我们再来讨论一下二进制 I/O 操作函数。
在进行二进制 I/O 操作时,一般都是一次读或写一个完整的结构。若使用 getc 或 putc,不仅麻烦还且费时;而若使用 fgets 或 fputs,又可能会因结构中含有 null 字节而停止。因此提供了下列两个函数。
#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); /* 两个函数的返回值:读或写的对象数 */
这两个函数有两种常见的用法:
1、读或写一个二进制数组。例如将一个浮点数组的第 2~5个元素写至一个文件上:
if( fwrite(&data[2], sizeof(float), 4, fp) != 4){ /* 处理错误 */ }
2、读或写一个结构。例如:
struct{ /*...*/ }item;
if( fwrite(&item, sizeof(item), 1, fp) != 1){ /* 处理错误 */ }
将这两者结合起来,就可读或写一个结构数组。
fread 和 fwrite 返回读或写的对象数。对于读,如果出错或到达文件尾端,则此数字可以少于 nobj。此时应调用 ferror 或 feof 来判断究竟是哪一种情况。对于写,如果该数字少于 nobj,则表示出错。
使用二进制 I/O 的基本问题是,它只能用于读在同一系统上已写的数据。这对于现在很多通过网络相连起来的异构系统的情况,它们可能就不能正常工作。在不同系统之间交换二进制数据的实际解决办法是使用互认的规范格式。
要定位标准 I/O 流,主要有 3 种方法。
1、ftell 和 fseek 函数,但是它们都假定文件的位置可以存放在一个长整型中。
2、ftello 和 fseeko 函数,它们使用了 off_t 数据类型代替了长整型。
3、fgetpos 和 fsetpos 函数,它们使用一个抽象数据类型 fpos_t 记录文件的位置。这种数据类型可以根据需要定义为一个足够大的数,用以记录文件位置。需要移植到非 UNIX 系统上运行的应用程序应当使用这两个函数。
#include <stdio.h> long ftell(FILE *fp); /* 返回值:若成功,返回当前文件位置;否则,返回 -1L */ int fseek(FILE *fp, long offset, int whence); /* 返回值:若成功,返回 0;否则,返回 -1 */ void rewind(FILE *fp); off_t ftello(FILE *fp); /* 返回值:若成功,返回当前文件位置;否则,返回 - 1 */ int fseeko(FILE *fp, off_t offset, int whence); /* 返回值:若成功,返回 0;否则,返回 -1 */ int fgetpos(FILE *restrict fp, fpos_t *restrict pos); int fsetpos(FILE *fp, const fpos_t *pos); /* 返回值:若成功,都返回 0;否则,都返回非 0 */
对于二进制文件,其文件位置是从文件起始位置以字节为单位开始度量。ftell 用于二进制文件时的返回值就是这种字节位置。fseek 中的 whence 的值同 lseek 函数,不过 ISO C 并不要求一个实现对二进制文件支持 SEEK_END 规格说明,因为有些系统要求二进制文件的长度是某个幻数的整数倍,结尾非实际内容部分则填充为 0(但是在 UNIX 中则是支持的)。
对于文本文件,它们的文件当前位置可能不以简单的字节偏移量来度量。因为非 UNIX 系统中可能以不同的格式存放文本文件。为了定位一个文本文件,whence 一定要是 SEEK_SET,而且 offset 只能为 0(后退到文件的起始位置)或是对该文件的 ftell 所返回的值。另外,使用 rewind 函数也可将一个流设置到文件的起始位置。
除了偏移量的类型是 off_t 以外,ftello/fseeko 函数与 ftell/fseek 相同。
fgetpos 将文件位置的当前值存入由 pos 指向的对象中,以后调用 fsetpos 时,可以使用此值将流重新定位至该位置。
发表评论
-
打开伪终端设备
2018-07-09 20:50 1248在伪终端概述一节中已对 PTY进行了初步的介绍。尽管 ... -
伪终端概述
2018-06-02 11:05 1533伪终端就是指,一个应用程序看上去像一个终端,但事实上它 ... -
终端窗口大小和 termcap
2018-05-29 22:39 791多数 UNIX 系统都提供了一种跟踪当前终端窗口大小的 ... -
终端规范模式和非规范模式
2018-05-29 00:25 937终端规范模式很简单:发一个读请求,当一行已经输入后,终 ... -
终端标识
2018-05-23 11:18 566尽管控制终端的名字在多数 UNIX 系统上都是 /de ... -
波特率和行控制函数
2018-05-22 07:53 933虽然大多数终端设 ... -
终端属性和选项标志
2018-05-20 07:40 706tcgetattr 和 tcsetattr ... -
终端特殊输入字符
2018-05-17 06:33 807终端支持下表所示的特殊输入字符。 为了更改 ... -
终端 I/O 综述
2018-05-10 07:56 432终端设备可认为是由内核中的终端驱动程序控制的。每个终端 ... -
POSIX 信号量
2018-05-09 00:03 575在XSI IPC通信之信 ... -
XSI IPC 通信之共享存储
2018-04-25 07:18 943在XSI IPC通信之消息队列和XSI IPC通信之信 ... -
XSI IPC通信之信号量
2018-04-17 23:38 612在XSI IPC通信之消 ... -
XSI IPC通信之消息队列
2018-04-15 10:54 490消息队列是消息的链接表,存储在内核中,由消息队列标识符 ... -
XSI IPC 相似特征介绍
2018-02-08 23:48 479有 3 种称作 XSI IPC ... -
IPC 通信之 FIFO
2018-02-06 22:55 412FIFO 也被称为命名管道,未命名的管道只能在两个相关 ... -
IPC 通信之管道
2018-01-30 22:22 383管道是 UNIX 系统 IPC 的最古老但也是最常用的 ... -
readv/writev 函数及存储映射 I/O
2018-01-19 00:57 878readv 和 writev 函数可用于在一次函数调用 ... -
POSIX 异步 I/O
2018-01-16 21:33 449POSIX 异步 I/O 接口为对不同类型的文件进行异 ... -
fcntl 记录锁
2018-01-06 23:48 584记录锁的功能是:当有进程正在读或修改文件的某个部分时, ... -
守护进程惯例
2018-01-06 23:52 432UNIX 系统中,守护进程遵循下列通用惯例。 ...
相关推荐
总结一下,Linux下C编程进行文件流读写主要涉及`fopen`、`fread`和`fwrite`这三个函数。`fopen`用于打开文件,`fread`用于从文件中读取数据,`fwrite`则用于向文件中写入数据。理解并熟练掌握这些函数的使用是进行...
### VC文件读写函数知识点详解 #### 一、文件的打开函数 在VC环境中,文件的打开主要通过`fopen`或`_wfopen`函数实现。这两个函数都是用来打开或创建一个文件,并将文件与流相关联。 ##### 1.1 `fopen`函数 **...
压缩包中的"格式化读写函数fscanf"可能是一个关于如何使用`fscanf`读取文件内容的实例,包括如何处理各种数据类型和格式。通过查看和分析这个示例,你可以更深入地理解`fscanf`的用法。 综上所述,C语言的格式化...
在描述中提到的"PB文件读写函数"是指专门用于处理PB文件的函数,这些函数已经过封装,以便于开发者在项目中使用。封装的目的在于简化代码,提高代码的可维护性和易用性。封装后的函数通常会隐藏内部的复杂逻辑,只...
该函数实现了三个功能:打开文件、将文件流与文件连接、返回文件指针。 参数filename指向要打开的文件名,mode表示打开状态串,其取值如下: * "r":以只读方式打开文件 * "w":以只写方式打开文件 * "a":以追加...
* tmpfile():生成一个临时文件流 * tmpnam():生成一个唯一的文件名 fopen() fopen() 函数的原型是:`FILE *fopen(const char *filename, const char *mode)`,它实现三个功能:使用而打开一个流、把一个文件和此...
描述中提到的"NTFS附加数据流读写类"可能是一个封装了这些API调用的自定义类库,例如`JWBStreamOP.dll`。这个库可能包含了创建、读取、写入和删除NTFS文件数据流的方法。 要使用这个库,首先需要将其引用添加到VB...
在C++编程中,文件流(File ...以上就是关于文件流读写的`fstream`库以及可能的`FileIOStream`类的详细解释。这个项目的目标可能是创建一个易于使用的类,简化对文件的读写操作,并且提高代码的可读性和可维护性。
在C++编程中,文件流(File Stream)是处理输入/输出操作的重要工具,它使得程序可以方便地读写磁盘上的文件。本教程将详细讲解如何使用纯C++的STL(Standard Template Library,标准模板库)进行文件流处理,并结合...
文件流的概念基于IOStream库,该库为C++提供了一种结构化的、面向对象的方式来读写文件。在本教程中,我们将深入探讨文件流的读写操作,以及如何在C++中实现这些功能。 首先,让我们理解什么是文件流。文件流是程序...
PHP提供了多种文件读写函数。`file_get_contents()`用于读取整个文件内容到字符串中,而`file()`则将文件内容分割为数组,每一行作为一个元素。对于写入文件,`file_put_contents()`是最常用的,它能够将数据写入...
tmpfile()函数用于生成一个临时文件流。其基本语法为:FILE *tmpfile(),返回一个临时文件流。 17. tmpnam()函数:生成一个唯一的文件名 tmpnam()函数用于生成一个唯一的文件名。其基本语法为:char *tmpnam(char ...
`fclose` 函数用于关闭由 `stream` 指向的文件流。当调用 `fclose` 后,任何在缓冲区中未写入磁盘的数据都会被输出,并且与文件关联的文件指针和缓冲区也会被释放。这对于确保所有数据都被正确保存非常重要。 **...
常见的TStream子类包括TMemoryStream(内存流),TFileStream(文件流),TResourceStream(资源流)等。 3. **文件流(TFileStream)**: - TFileStream是TStream的一个实现,用于读写文件。你可以通过指定文件名...
FileOpen()函数用于以指定的读写方式打开指定的文件,同时返回该文件的句柄。该函数的语法为`FileOpen(filename{,filemode{,fileaccess{,filelock{,writemode,{creator,filetype}}}})`,其中`filename`是string类型...
除了单字节和多字节的函数外,C语言还提供了格式化的读写函数fprintf和fscanf,它们允许用户按照指定的格式进行输入输出,非常适用于各种数据的格式化处理。例如,在输出时可以指定小数点位数,而输入时可以按照特定...
`fstream`库(包含在`<fstream>`头文件中)提供了一种面向对象的方式来处理文件,如`ifstream`(输入文件流)和`ofstream`(输出文件流)。这些类提供了如`open()`, `close()`, `read()`, `write()`等成员函数,使得...
在"VB 读写ini文件源码 API函数使用"的场景中,我们将利用Windows API来操作INI文件。 1. **API函数介绍**: - `WritePrivateProfileString`:此API函数用于向INI文件写入数据。它接受四个参数:应用程序名、...