C-文件读写

一.文件的打开与关闭

  • 为了读写文件,我们需要用到定义在stdio.h这个标准库头文件中的一些函数结构
  • 下面按顺序列出我们打开一个文件,进行读写操作所必须遵循的一个流程
    1.调用“文件打开”函数fopen,返回一个指向该文件的指针
    2.检测文件是否打开成功,通过第一步fopen的返回值(文件指针)来判断,如果指针为NULL,则表示打开失败,我们需要停止操作,并且返回一个错误
    3.如果文件打开成功,就可以用stdio.h中的读写函数来读写文件
    4.完成读写操作,关闭文件,调用“文件关闭”函数fclose

1.fopen:打开文件

//函数原型
FILE* fopen(const char* fileName,const char* openMode);
  • fileName:文件名,字符串类型,不可变
  • openMode:打开方式,表明我们打开文件之后要干什么
可用的openMode
  • 函数返回值:FILE指针

2.fclose:关闭文件

//函数原型
int fclose(FILE* pointerOnFile);
  • pointerOnFile:指向文件文件的指针
  • 函数的返回值(int)有两种情况:
    1.0:当关闭操作成功时
    2.EOF(一般是-1):如果关闭失败
  • 关闭这个文件,目的是为了释放占用的文件指针

二.读写文件的不同方法

学习如何对文件进行读出和写入

1.对文件写入

我们学习三个写入的函数

  • fputc:file put character,在文件中写入一个字符
  • fputs:file put string,在文件中写入一个字符串
  • fprint:在文件中写入一个格式化过的字符串,用法与printf几乎相同,只是多了一个文件指针

fputc

int fputc(int character, FILE*pointerOnFile);
  • character:int型变量,表示要写入的字符
  • pointerOnFile:指向文件的指针
  • 函数返回值int:如果写入失败,则为EOF,否则会是另一个值

示例:

//程序用于向test.txt写入字符'A'
#include <stdio.h>
int main(int argc, const char* argv[]) {
    FILE* file = NULL;
    file = fopen("/Users/xulei/Desktop/test.txt", "w");
    if (file == NULL) {
        printf("error");
    }
    fputc('A', file);
    fclose(file);
    return 0;
}

运行之后,会在我所给的路径(桌面)下,创建一个test.txt

test.txt

fputs

int fputs(const char* string, FILE* pointerOnFile);
  • stringr:char型变量,表示要写入的字符串
  • pointerOnFile:指向文件的指针
  • 函数返回值int:如果写入失败,则为EOF,否则会是另一个值

示例:

//程序用于向test.txt写入字符串
#include <stdio.h>
int main(int argc, const char* argv[]) {
    FILE* file = NULL;
    file = fopen("/Users/xulei/Desktop/test1.txt", "w");
    if (file == NULL) {
        printf("error");
    }
    fputs("你好,朋友\n最近怎么样", file);
    fclose(file);
    return 0;
}

运行之后,会在我所给的路径(桌面)下,创建一个test1.txt

test1.txt

fprintf

int fprintf(FILE* stream, const char *format, ...);

不仅可以向文件写入字符串,而且这个字符串可以有由我们来格式化

示例:

//程序用于向test.txt写入字符串
#include <stdio.h>
int main(int argc, const char* argv[]) {
    FILE* file = NULL;
    int age = 0;
    file = fopen("/Users/xulei/Desktop/test2.txt", "w");
    if (file == NULL) {
        printf("error");
    }
    printf("你几岁了?\n");
    scanf("%d",&age);
    fprintf(file, "使用者年龄是%d岁\n",age);
    fclose(file);
    return 0;
}
//运行结果
你几岁了?

2
Program ended with exit code: 0

运行之后,会在我所给的路径(桌面)下,创建一个test2.txt

test2.txt

2.对文件读出

我们学习三个读出的函数

  • fgetc:file get character,在文件中读出一个字符
  • fgets:file get string,在文件中读出一个字符串
  • fscanf:在文件中读出一个格式化过的字符串,用法与scanf几乎相同,scanf是从用户输入读取,而fscanf是从文件读取

fgetc

int fgetc(FILE*pointerOnFile);
  • pointerOnFile:指向文件的指针
  • 函数返回值int:函数返回值是读到的字符,如果不能读到字符,那会返回EOF
  • fgetc函数每读入一个字符,这个虚拟的游标就移动这个一个字符长度,我们就可以用一个循环读出所有的字符
    示例:
#include <stdio.h>
int main(int argc, const char * argv[]) {
    FILE* file = NULL;
    int currentCharacter = 0;
    file = fopen("/Users/xulei/Desktop/test2.txt", "r");
    if (file == NULL) {
        printf("error");
    }
    do {
        currentCharacter = fgetc(file);//读取一个字符
        printf("%c",currentCharacter);//显示读取的字符
    } while (currentCharacter != EOF);
    printf("\n");
    fclose(file);
    return 0;
}
//运行结果
使用者年龄是2岁
\377
Program ended with exit code: 0
//\377,其实就是-1,也就是EOF,表示读到末尾
/*
\是C语言的转义字符的起始标识。
当\后面直接接数字的时候,会被处理成对应的8进制。
于是\377也就是8进制377对应的ascii码值,将其转为二进制为
3 = 11
7 =111
于是值为11 111 111
也就是16进制的0xff, 10进制值为255。
这个是单字节无符号数所能表示的最大值,作为有符号数时,值为-1
*/

fgets

char *fgets(char *string, int characterNumberToRead, FILE* pointerOnFile);

这个函数每次最多读一行,因为它遇到第一个'\n'(换行符)会结束读取

示例:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    FILE* file = NULL;
    char string[1000] = " ";//保证数组足够大
    file = fopen("/Users/xulei/Desktop/test1.txt", "r");
    if (file == NULL) {
        printf("error");
    }
    while (fgets(string, 1000, file) != NULL) {//只要某一行不是空值就读取它
        printf("%s\n",string);
    }
    fclose(file);
    return 0;
}
//运行结果
你好,朋友

最近怎么样
Program ended with exit code: 0

fscanf

int fscanf(FILE* stream, const char *format, ...);

此函数原理和scanf是一样的,负责从文件中读取规定样式的内容

示例:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    FILE* file = NULL;
    int score[3] = {30,19,32,};
    //文件写入
    file = fopen("/Users/xulei/Desktop/test3.txt", "w");
    if (file == NULL) {
        printf("error");
    }
    for (int i = 0; i < 3; i++) {
        fputc(i, file);
    }
    fclose(file);
    //文件读取
    file = fopen("/Users/xulei/Desktop/test3.txt", "r");
    if (file == NULL) {
        printf("error");
    }
    fscanf(file, "%d %d %d",&score[0],&score[1],&score[2]);
    printf("%d %d %d",score[0],score[1],score[2]);
    printf("\n");
    fclose(file);
    return 0;
}
//运行结果
30 19 32
Program ended with exit code: 0

三.在文件中移动

前面我们提到一个虚拟的游标,现在我们仔细学一下
每当我们打开一个文件时,实际上都存在一个游标,标识你当前在文件中所处的位置,可以类比我们编辑文本时的光标

三个与文件中游标移动有关的函数:

  • ftell:告诉目前在文件中那个位置
  • fseek:移动文件中的游标到指定位置
  • rewind:将游标重置到文件的开始位置

ftell

返回一个long型的整数值,表明目前游标所在位置

long ftell(FILE* pointerOnFile);

fseek

此函数能使游标在文件(pointerOnFile指针所指)中从位置(origin所指)开始移动一段距离(move所指)

int fseek(FILE* pointerOnFile, long move, int origin);
  • move:可以是一个正整数,表明向前移动;0,不移动;负整数,表明回退
  • origin:它有三个取值
    1.SEEK_SET:文件开始处
    2.SEEK_CUR:游标当前所处位置
    3.SEEK_END:文件末尾

例子:

fseek(file, 5, SEEK_SET);
//这行代码将游标放置到距离文件开始处5个位置的地方。

fseek(file, -3, SEEK_CUR);
//这行代码将游标放置到距离当前位置往后3个位置的地方

fseek(file, 0, SEEK_END);
//这行代码将游标放置到文件末尾。

rewind

相当于使用fseek来使游标回到0的位置

void remind(FILE* pointerOnFile);
//相当于fseek(file,0,SEEK_SET);

四.文件的重命名和删除

两个简单的函数:

  • rename:重命名一个文件
  • remove:删除一个文件

rename

int rename(const char *oldName, const char *newName);

如果函数执行成功,则返回0,否则返回非0的int型值

示例:

int main(int argc, char *argv[]){
  rename("test.txt", "renamed_test.txt");
  return 0;
}

remove

int remove(const char *fileToRemove);

fileToRemove就是我们要删除的文件名

示例:

int main(int argc, char *argv[]){
  remove("test.txt");
  return 0;
}

五.数据块读写函数fread 和 fwrite

读数据块数据的格式: fread(buffer,size,count,fp);
写数据块数据的格式: fwrite(buffer,size,count,fp);

  • buffer -- 是一个指针,在fread函数中,它表示存放输入数据的首地址。在fwrite函数中,它表示存放输出数据的首地址。

  • size -- 表示数据库的字节数

  • count -- 表示要读写的数据库块数

  • fp -- 表示文件指针

fread(fa,4,5,fp); --> 意义: 是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续5次,即读5个实数到fa中

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

推荐阅读更多精彩内容