目录
二进制I/O:fread()和fwrite()
fwrite()函数
描述
C 库函数 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 把 ptr 所指向的数组中的数据写入到给定流 stream 中。
声明
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
参数
- ptr -- 这是指向要被写入的元素数组的指针。
- size -- 这是要被写入的每个元素的大小,以字节为单位。
- nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。
返回值
如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误。
用法
#include<stdio.h>
int main ()
{
FILE *fp;
char str[] = "This is runoob.com";
fp = fopen( "file.txt" , "w" );
fwrite(str, sizeof(str) , 1, fp );
fclose(fp);
return(0);
}
让我们编译并运行上面的程序,这将创建一个文件 file.txt,它的内容如下:
This is runoob.com
现在让我们使用下面的程序查看上面文件的内容:
#include <stdio.h>
int main ()
{
FILE *fp;
int c;
fp = fopen("file.txt","r");
while(1)
{
c = fgetc(fp);
if( feof(fp) )
{
break ;
}
printf("%c", c);
}
fclose(fp);
return(0);
}
fread()函数
描述
C 库函数 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从给定流 stream 读取数据到 ptr 所指向的数组中。
声明
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
参数
- ptr -- 这是指向带有最小尺寸 size*nmemb 字节的内存块的指针。
- size -- 这是要读取的每个元素的大小,以字节为单位。
- nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流。
返回值
成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
用法
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char c[] = "This is runoob";
char buffer[20];
/* 打开文件用于读写 */
fp = fopen("file.txt", "w+");
/* 写入数据到文件 */
fwrite(c, strlen(c) + 1, 1, fp);
/* 查找文件的开头 */
fseek(fp, 0, SEEK_SET);
/* 读取并显示数据 */
fread(buffer, strlen(c)+1, 1, fp);
printf("%s\n", buffer);
fclose(fp);
return(0);
}
让我们编译并运行上面的程序,这将创建一个文件 file.txt,然后写入内容 This is runoob。接下来我们使用 fseek() 函数来重置写指针到文件的开头,文件内容如下所示:
u'nunThis is runoob
feof()函数和ferror()函数
feof()函数
描述
C 库函数 int feof(FILE *stream) 测试给定流 stream 的文件结束标识符。
声明
int feof(FILE *stream)
参数
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
返回值
当设置了与流关联的文件结束标识符时,该函数返回一个非零值,否则返回零。
ferror()函数
描述
C 库函数 int ferror(FILE *stream) 测试给定流 stream 的错误标识符。
声明
int ferror(FILE *stream)
参数
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
返回值
如果设置了与流关联的错误标识符,该函数返回一个非零值,否则返回一个零值。
如果标准输入函数返回EOF,则通常表明函数已到达文件结尾。然而,出现读取错误时,函数也会返回EOF。feof()和ferror()函数用于区分这两种情况。当上一次输入调用检测到文件结尾时,feof()函数返回一个非零值,否则返回0.当读写出现错误时,ferror()函数返回一个非零值,否则返回0。
ungetc()函数
描述
C 库函数 int ungetc(int char, FILE *stream) 把字符 char(一个无符号字符)推入到指定的流 stream 中,以便它是下一个被读取到的字符。
int ungetc()函数把c指定的字符放回输入流中。假设要读取下一个冒号之前的所有字符,但是不包括冒号本身,可以使用getchar()或getc()函数读取字符到冒泡,然后用ungetc()函数把冒号放回输入流中。 ANSI C标准保证每次只能放回一个字符。
声明
int ungetc(int char, FILE *stream)
参数
- char -- 这是要被推入的字符。该字符以其对应的 int 值进行传递。
- stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了输入流。
返回值
如果成功,则返回被推入的字符,否则返回 EOF,且流 stream 保持不变。
举例
#include <stdio.h>
int main ()
{
FILE *fp;
int c;
char buffer [256];
fp = fopen("file.txt", "r");
if( fp == NULL )
{
perror("打开文件时发生错误");
return(-1);
}
while(!feof(fp))
{
c = getc (fp);
/* 把 ! 替换为 + */
if( c == '!' )
{
ungetc ('+', fp);
}
else
{
ungetc(c, fp);
}
fgets(buffer, 255, fp);
fputs(buffer, stdout);
}
return(0);
}
假设我们有一个文本文件 file.txt,它的内容如下。文件将作为实例中的输入:
this is runoob
!c standard library
!library functions and macros
让我们编译并运行上面的程序,这将产生以下结果:
this is runoob
+c standard library
+library functions and macros
标准I/O的机理
通常,使用标准I/O的第1步是调用fopen()打开文件。fopen()函数不仅打开一个文件,还创建了一个缓冲区以及一个包含文件和缓冲区数据的结构。另外,fopen()返回一个指向该结构的指针,以便其他函数知道如何找到该结构。假设把该指针赋给一个指针变量fp,我们说fopen()函数“打开一个流”。如果以文本模式打开该文件,就获得一个文本流;如果以二进制模式打开该文件,就获得一个二进制流。
这个结构通常包含一个指定流中当前位置的文件指示器。除此之外,它还包含错误和文件结尾的指示器、一个指向缓冲区开始出的指针、一个文件标识符和一个计数(统计实际拷贝进缓冲区的字节数)。
主要考虑文件输入。通常,使用标准I/O的第2步是调用一个在stdio.h中的输入函数,如fscanf()、getc()、或fgets()。一调用这些函数,文件中的缓冲大小数据块就被拷贝到缓冲区中。缓冲区的大小因实现而异,一般是512字节或是它的倍数,如4096或16384(随着计算机硬盘容量越来越大,缓冲区的大小也越来越大)。最初调用函数,除了填充缓冲区外,还要设置fp所指向的结构中的值。尤其要设置流中的当前位置和拷贝进缓冲区的字节数。通常,当前位置从字节0开始。
在初始化结构和缓冲区后,输入函数按要求从缓冲区读取数据。在它读取数据时,文件位置指示器被设置为指向刚读取字符的下一个字符。由于stdio.h系列的所有输入函数都使用相同的缓冲区,所以调用任何一个函数都将从上一次函数停止调用的位置开始。
当输入函数发现已读完缓冲区中的所有字符时,会请求把下一个缓冲大小的数据块从文件拷贝到该缓冲区中。以这种方式,输入函数可以读取文件中的所有内容,知道文件结尾。函数在读取缓冲区中的最后一个字符后,把结尾指示器设置为真。于是,下一次被调用的输入函数将返回EOF。
输出函数以类似的方式把数据写入缓冲区。当缓冲区被填满时,数据将拷贝至文件中。