第13章 文件输入/输出
ANSI要求提供的两种文件视图是文本视图和二进制视图。
c程序自动为您打开3个文件:这三个文件称为
标准输入(standard input):指一般的输入设备,通常指键盘;getchar()、gets()、scanf()读取文件。
标准输出(standard output),标准错误输出(standard error output):通常为显示器; putchar()、puts()和printf()输出内容。
exit() 函数关闭所有打开的文件并终止程序。
fopen() 在成功打开一个文件后,此函数返回一个文件指针(file pointer),文件指针是一种指向FILE的指针:FILE是stdio.h中定义的一种派生
类型。指针fp并不指向实际的文件,而是指向一个关于的信息的数据包,其中包括文件I/O使用的缓冲区信息。
ch = getc(fp); //表示从指针fp指定的文件中获得一个字符
putc(ch, fpout); //以下语句表示将字符ch写入到FILE指针fpout指定的文件中。
文件结尾:
int ch;
FILE * fp;
fp = fopen("hello.txt", "r");
ch = getc(fp); //获取初始输入
while (ch != EOF) while ((ch = getc(fp)) != EOF)
{
putchar(ch);
ch = getc(fp);
}
fclose(), fclose(fp)函数关闭由指针fp指定的文件,同时根据需要刷新缓冲区。如果成功关闭,fclose()函数返回值为0,否则返回EOF。
统计文件字符程序:
include<stdio.h>
#include<stdlib.h>
int main(int argc, char * argv[])
{
long count = 0; //统计字符个数
char ch;
FILE * fp; //文件指针
if (argc != 2)
{
printf("Input error.\n");
exit(1); //参数1非正常终止
}
if ((fp = fopen(argv[1], "r")) == NULL) //打开文件失败
{
printf("Cann't open file : %s\n", argv[1]);
exit(1);
}
while((ch = getc(fp)) != EOF )
{
putc(ch, stdout);
count++;
}
printf("This file %s has %ld characters!\n", argv[1], count);
return 0;
}
文件I/O:fprintf()、fscanf()、fgets()、fputs():
fprintf():
fprintf()会根据参数format 字符串来转换并格式化数据, 然后将结果输出到参数stream 指定的文件中, 直到出现字符串结束('\0')为止。
fscanf():
scanf()会自参数stream 的文件流中读取字符串, 再根据参数format 字符串来转换并格式化数据。格式转换形式请参考scanf(). 转换后的结构存于对应的参数内。
fscanf遇到空格和换行时结束,注意空格时也结束。
gets():遇到回车符号"\n"为止。
#include<stdio.h>
#include<stdlib.h>
#define MAX 40
int main()
{
FILE * fp;
char words[MAX];
if ((fp = fopen("words", "a+")) == NULL) //以读、写追加的方式打开一个文件
{
fprintf(stdout, "Can't open file \"words\".\n"); //有错误,将错误输出到显示器
exit(1);
}
puts("Enter words to add to the file:press the Enter:");
while (gets(words) != NULL && words[0] != '\0') //输入字符串,遇到'\n'结束
{
fprintf(fp, "%s", words); //将输入的字符串输入到fp所指向的文件中
}
puts("File content:");
rewind(fp); // 文件指针回到原处
while (fscanf(fp, "%s", words) == 1) //从fp指向的那个文件中读取内容,遇到空格结束
{
puts(words);
}
if (fclose(fp) != 0)
{
fprintf(stderr, "Error closing file\n");
}
return 0;
}
fgets():
fgets()函数的第一个参数和gets()函数一样,是用于存储输入的地址(char * 类型),第二个参数为整数,表示出入的字符串的最大长度。
最后一个参数是文件指针,指向要读取的文件。可以反之存储溢出.
fgets(buf, MAX, fp); //buf是一个char数组的名称,MAX是字符串的最大长度,fp是一个FILE指针
fgets()读取到它所遇到的第一个换行符的后面,或者读取比字符串的最大长度少一个字符,或者读取到文件的末尾。
然后fgets()函数向末尾添加一个空字符以构成一个字符串。所以,字符串的最大长度代表字符的最大数目再加上一个空字符。会将换行符保留。
fputs() 函数接收两个参数,依次是一个字符串参数和一个文件指针。其不会添加换行符。
#include<stdio.h>
#define MAXLINE 20
int main()
{
char line[MAXLINE];
while (fgets(line, MAXLINE, stdin) != NULL && line[0] != '\n' )
{
fputs(line, stdout);
}
return 0;
}
fseek():
fseek()函数允许你像对待数组那样对待一个文件,在fopen()打开的文件中直接移动到任意字节处。第二个参数必须为long类型。
fseek(fp, 0L, SEEK_SET); //找到文件的开始处
fseek(fp, 10L, SEEK_SET); //找到文件的第10个字节
fseek(fp, 2L, SEEK_CUR); //从文件的当前位置向前移动2个字节
fseek(fp, 0L, SEEK_END); //到达文件结尾处
fseek(fp, -10L, SEEK_END); //从文件结尾处退回10个字节
如果一切正常,fseek()的返回值为0。如果有错误出现,则fseek()的返回值为-1。
ftell()函数为long类型,它返回文件的当前位置。
将一个英文的文本文件逆序输出:
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE * fp;
char ch;
long count, last;
if ( (fp = fopen("words", "rb")) == NULL) //只读和二进制模式
{
printf("Can't open caocao file.\n");
exit(1);
}
fseek(fp, 0L, SEEK_END); //定位到文件结尾处
last = ftell(fp); //返回距离文件开始处的字节数目
for (count = 1L; count < last; count++)
{
fseek(fp, -count, SEEK_END);
ch = getc(fp); //从指针fp指定的文件中获得一个字符
putchar(ch);
}
}
二进制I/O:fread()和fwrite():
fwrite():
double earnings[10];
fwrite(earnings, sizeof(double), 10, fp);
这一调用将earnings数组中的数据写入文件,数据分成10块,每块都是double大小。fwrite()返回成功写入的项目数。如果有写入错误的话,返回值会小于10。
fread():
double earnings[10];
fread(earnings, sizeof(double), 10, fp);
和fwrite()的参数一样,该调用将10个double值复制到earnings数组中。
c程序将输入看作字节流;流的来源可以是文件、输入设备(如键盘),甚至可以是另一程序的输出。
类似,c程序将输出也看作字节流;流的目的地可以是文件,视频显示的等。