重温C语言(7)之文件输入与输出

https://mp.weixin.qq.com/s/obcOxx9e6edRHcKYIh4YLQ

[toc]

文件

File (文件)是硬盘磁盘上的被命名的存储空间。
C 把文件看作是一系列的字节,每个字节都能被单独读取。

所有文件的内容都是以二进制存储的。文本文件以二进制编码的字符比如ASCLL或Unicode 存储,二进制文件以机器语言代码或树值数据或图片或音乐编码存储。

exit()函数关闭搜有打开的文件并结束程序,exit(0)exit(EXIT_SUCCESS) 表示成功结束程序, eixt(EXIT_FAILURE) 表示结束程序失败。

return 会把控制权交给上级函数,直到最初函数。

fopen()

fopen() 函数用于打开文件,第一个参数是地址,第二个参数是打开文件的模式。返回文件指针(指向FILE的指针)。

模式有如下几个:

模式 含义
"r" 以只读模式打开文件
"w" 写模式,把文件长度截取为0即文件内容被删除,文件不存在则创建新的
"a" 写模式,在文件末尾添加内容,文件不存在则创建新的
"r+" 更新模式,可以读写文件
"w+" 更新模式,文件长度截取为0,文件不存在则创建新的
"a+" 更新模式,只允许在文件末尾添加内容,文件不存在则创建新的,这个模式可以读取整个文件
"rb","wb","ab","rb+","r+b","wb+","w+b","ab+","a+b" 更新模式,以二进制模式打开文件
"wx","wbx","w+x","wb+x,"w+bx" (C11)类似非x模式,但是如果文件已存在或以独占模式打开文件,则打开文件失败

带x字母的写模式,即使fopen()操作失败,原文件的内容也不会被删除。第二,如果环境允许,x模式的独占特性使得其他程序或线程无法访问正在被打开的文件。

getc()

getc(文件指针) 从文件指针指向的文件获取一个字符。

putc()

getc(字符,文件指针) 把字符放入文件指针指向的文件中。

fclose()

fclose(文件指针) 关闭文件指针指向的文件,关闭成功返回 0, 否则返回 EOF,必要的时候刷新缓冲区。

示例(1):

// 预编译器,把stdio.h文件中的所有内容都输入该行所在的位置, stdio.h 包含了供编译器使用的输入输出函数
#include <stdio.h> // <- C 预处理指令


int main() { // <- 函数体开始


    int ch;
    FILE * fp = fopen("../test/test.txt", "r");
    FILE * fpout = fopen("../test/testout.txt", "w");
    ch = getc(fp);
    while ((ch = getc(fp)) != EOF) { // 得到一个输入,判断是否是文件末尾
        putchar(ch);
        putc(ch, fpout);
    }

    if(fclose(fp) != 0){

        printf("关闭test文件失败\n");
    }
    if(fclose(fpout) != 0){
        printf("关闭testout文件失败\n");
    }

    return 0; // <- 函数体结束
}

fprintf()

printf() 类似,但是又多了一个参数,第一个参数是个文件指针,例如:

fprintf(stderr, "error %s", "error");
fprintf(stdout, "error %s", "error");

stderr 指针用于把错误信息发送至标准错误。
stdout 指针用于把信息发送至标准输出。

fprintf(文件指针, "msg %s", "msg");

把信息写入到 文件指针指向的文件中。

fscanf()

scanf() 类似,但是又多了一个参数,第一个参数是个文件指针,例如:

char words[41];
fscanf(stdin, "%40s", words);

从标准输入读取信息到 words 中。

fscanf(文件指针, "%s", words);

读取文件指针指向的文件中的单词到 words 中。

rewind()

rewind(文件指针) 使程序返回到文件开始处。

fgets()

fgets(字符指针, 字符串大小, 文件指针)

会读取到第一个换行符,或者文件末尾,或者指定字符串大小个字符。
fgets()会在字符串末尾加上一个空字符。

fputs()

fputs(字符串地址, 文件指针)

把字符串写入到指定文件中。

fseek() 和 ftell()

fseek(文件指针, 偏移量, SEEK_SET|SEEK_CUR|SEEK_END) 可以在打开的文件中移动到任意字节处。
ftell() 返回 long 类型值表示文件的当前位置。

  • SEEK_SET 文件开始处;
  • SEEK_CUR 当前位置;
  • SEEK_END 文件末尾;
  long last;
    FILE * fp = fopen("../test/test.txt", "rb");
    // 定位到文件末尾
    fseek(fp, 0, SEEK_END);
    int ch;
    last = ftell(fp);
    for (long i = 1; i <= last; ++i) {
        // 定位到文件末尾的前 i 位
        fseek(fp, -i, SEEK_END);
        ch = getc(fp);
        putchar(ch);
    }
    fclose(fp);

fgetpos() 和 fsetpos()

突破 fseek() 和 ftell() 的 long 限制。

fpos_t: 文件定位类型, 它的对象或变量可以指定文件中的一个位置。

int fgetpos(FILE * __restrict, fpos_t * restrict pos); 成功返回0,否则非0,获取当前位置并存入pos, pos 指向的是 fpos_t 类型值,描述文件当前位置到文件开头的字节数字。

int fsetpos(FILE *, const fpos_t * restrict pos); 成功返回0,失败返回非0,设置文件指针指向的位置。

ungetc()

int ungetc(int c, FILE *fp);函数把c指定的字符放回输入流中。如果把一个字符放回输入流,下次调用标准输入函数时将读取该字符。

fflush()

int fflush(FILE *fp); 刷新缓冲区,调用fflush()函数引起输出缓冲区中所有的未写入数据被发送到fp指定的输出文件。

setvbuf()

在打开文件后且未对流进行其他操作之前,调用它创建缓冲区。
int setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size);创建了一个供标准I/O函数替换使用的缓冲区, 成功返回0,否则非0.
fp: 待处理的流;
buf: 待使用的存储区, 如果是 NULL 会自动创建;
mode: _IOFBF 完全缓冲区即缓冲区慢点时候刷新,_IONBF无缓冲 ;
size: size_t 派生整数类型,数组的大小;

fwrite()

函数用于二进制形式的数据写入处理。
size_t fwrite(const void * __restrict __ptr, size_t __size, size_t __nitems, FILE * __restrict __stream); 把二进制数据写入文件, 返回成功写入项目的数量;

size_tunsigned int, 是 sizeof 运算符返回的类型;size表示待写入数据块的大小(以字节为单位);nmemb表示待写入数据块的数量;
例如: 保存 含有10个 double类型值的数组

double a[10];
fwrite(a, sizeof(double), 10, fp);

fread()

函数用于二进制形式的数据写入处理。
size_t fread(void * __restrict __ptr, size_t __size, size_t __nitems, FILE * __restrict __stream); 读取被 fwrite() 写入文件的数据, 返回成功读取项的数量;

例如: 读取含有 10 个 double 类型值的数组,并拷贝到 oa 中,

double oa[10];
fread(oa, sizeof(double), 10, fp);

feof() ferror()

int  feof(FILE *);
int  ferror(FILE *);

文件末尾时,函数返回 EOF,但是文件出错也返回 EOF,这两个函数就是来判断这两个情景的。
当上一次输入调用检测到文件结尾时,feof()函数返回一个非零值,否则返回0。当读或写出现错误,ferror()函数返回一个非零值,否则返回0。

示例

获取文件名

char * s_gets(char * st, int n{
    char * ret_val;
    char * find;
    ret_val = fgets(st, n, stdin);
    if(ret_val){
        find = strchr(st, '\n');//查找换行符  
        if(find)    //如果地址不是NULL,
            *find='\0';     //在此处放置一个空字符
        else
            while(getchar() != '\n')
                continue;
     }

    return ret_val;
}

拷贝

记得要给文件创建缓冲区

if(setvbuf( fa, NULL, _IOFBF, BUFSIZE) != 0){
    fputs("无法创建缓冲区\n", stderr);
    exit(EXIT_FAILURE);
}
void append(FILE * source, FILE * dest){
    size_t bytes;
    static char temp[BUFSIZE];//只分配一次
    while((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0)
    fwrite(temp, sizeof(char), bytes, dest);
}


总结

当输入函数发现已读完缓冲区中的所有字符时,会请求把下一个缓冲大小的数据块从文件拷贝到该缓冲区中。以这种方式,输入函数可以读取文件中的所有内容,直到文件结尾。函数在读取缓冲区中的最后一个字符后,把结尾指示器设置为真。于是,下一次被调用的输入函数将返回EOF。输出函数以类似的方式把数据写入缓冲区。当缓冲区被填满时,数据将被拷贝至文件中。

fopen()函数为标准I/O打开一个文件,并创建一个用于存储文件和缓冲区信息的结构。
feof()和ferror()函数报告I/O操作失败的原因。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容