C语言-文件

所谓“文件”是指一组相关数据的有序集合,该数据的集合的名字就是文件名。文件可以分为很多类,如源程序文件、目标文件、可执行文件、库文件等等。
文件通常是存放在外部介质上的(例如磁盘等),在使用时才会被调入内存中并执行。从用户的角度来看文件可以分为普通文件和设备文件。
普通文件是指存放在磁盘或者其它外部介质上的一个有序的集合,可以是源文件、目标文件、可执行程序等;也可以是一组待输入处理的原始数据,或是一组输出的结果。对于源文件、目标文件、可执行程序可以称作程序文件,而输入输出数据可以称作数据文件。
设备文件是指与主机相联的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把他们的输入输出等同于对磁盘文件的读写。
从文件编码的形式来看,文件可以分为ASCII码文件和二进制码文件。ASCII码文件也称作为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放相应的ASCII码。
二进制文件是以二进制编码的方式来编写文件的。二进制文件虽然可以显示在屏幕上,但是却不能读懂。

文件的指针

在C语言中用一个指针变量指向一个文件,那么这个指针称为文件指针。另外,我们通过文件指针就可以对所指的文件进行各种操作。

一般形式为:
FILE* 文件变量标识符

解释:FILE应该是大写的,它实际上是由系统定义的一个结构体,该结构体包含了文件名、文件状态和文件当前位置等信息,因此在编写程序的时候我们不需要过于关心FILE结构的细节部分。

// 案例1:
FILE *fp;
/*说明:
fp表示FILE结构的指针变量,通过fp可以找到存放某一个文件信息的结构变量,
然后按照结构体提供的信息找到该文件,并对文件进行操作。*/

文件的打开和关闭

文件在进行读写操作之前,要打开文件,当使用完后应关闭文件。打开文件就是建立文件的各种有关信息,并使文件指针指向文件,以便进行其他操作。而关闭文件就是切断文件指针和文件之间的关系,换而言之,就是禁止利用指针操作文件。
在C语言中,文件操作都是由库函数完成的。如fopen 和 fclose。

1. 文件的打开 fopen()

fopen() 函数是用来打开一个文件,其一般的调用形式为:
文件指针名 = fopen(文件名,使用文件的方式);

注释:

  1. 文件指针名:必须被说明为FILE类型的指针变量;
  2. 文件名:被打开文件的文件名;
  3. 使用文件的方式:文件的类型和操作要求
// 案例2:
FILE* fp;
fp = fopen("text","r");
/*说明:
在当前目录下打开文件text,只允许“读”的操作,并且让fp指针指向该文件*/

使用文件的方式有12种,如下所示:

|使用文件方 | 意义                                                              |
|----------|------------------------------:|
|“rt”      | 只读打开一个文本,只允许读|
|“wt”      | 只写打开或者建立一个文件,只允许写数据|
|“at”      | 追加打开一个文件,并在文件末尾写数据|
|“rb”      | 只读打开一个二进制文件,只允许读|
|“wt”      | 只写打开或者建立一个而进制文件,只允许写|
|“ab”      | 追加打开一个二进制文件,并在文件末尾写数据|
|“rt+”     | 读写打开一个文件,允许读和写 |
| “wt+”    | 读写打开或建立一个文件,允许读写|
|“at+”     | 读写打开一个文件,允许读,或在文件末尾追加数据|
|“rb+”     | 读写打开一个二进制文件,允许读写|
|“wb+”     | 读写打开或者建立一个二进制文件,允许读写        |
|“ab+”     | 读写打开一个二进制文件,允许读,或在文件末追加数据|

说明:
由r、w、a、t、b、+六个字符拼成,个字符的意义:

  1. r(read):读
  2. w(write):写
  3. a(append):追加
  4. t(text):文本文件,可省略不写
  5. b(banary):二进制文件
    6.+:读和写
// 案例3:
FILE* fp;
fd = fopen("./text","r");
if (NULL == fd)
{
    printf("open error\n");
    exit(1);
}
// 用读“r”的方式打开文件“./text”;若文件打开失败时,fp为空,输出open error。

2. 文件的关闭

fclose()函数是指当文件使用完后,需要关闭文件。其一般形式为:
fclose(文件指针);

// 案例4:
fclose(fp);
// 说明:正常关闭文件时,fclose()函数的返回值是0。若返回一个非零的值,则表示关闭文件时发生错误

文件的读写

文件的读写是有多重方式的,它可以一个字节一个字节的读或写,也可以是一串一串的读或写。文件的读写可以分为下面四类,且它们的头文件均是<stdio.h>。

1. 字符读写函数fgetc 和 fputc

字符的读写函数是以字节为单位读写函数。每一次可以从文件读出或向文件内写入一个字符。
读字符函数fgetc() 的一般形式:
字符变量 = fgetc(文件指针);

说明:将文件中的一个字符读取出来,然后存放在字符变量中。

写字符函数fputs() 的一般形式:
fputs(字符量,文件指针);

说明:将字符量中的字符,存放在想对应的文件中。

// 案例5:
#include<stdio.h>

int main()
{
    FILE* fp = fopen("./text","r");
    if (NULL == fp)
    {
      printf("cann't open the file\n");
      exit(1);
    }
    char ch; 
    // 读取文件中的字符,一个一个的读取。
    ch = fgetc(fp);
    while (EOF != ch)  // EOF表示读到文件的末尾
    {
      printf("%c\n",ch);
      ch = fgetc(fp);
    }
    close(fp);
    // 向文件中写入数据
    fp = fopen("./text1","w");
    if (NULL == fp)
    {
      printf("cann't open the file\n");
      exit(1);
    }
    printf("input a character:");
    scanf("%c",&ch);
    fputc(ch,fp); // 将ch变量中的字符存放到文件“./text1”中。
    return 0;
}

注意:在网文件中写数据的时候,上的那种写法是,直接覆盖文件中的数据,而不是在文件的末尾追加数据。若想不改变文件原来的数据,只想在文件的末尾追加数据,那么需要将文件的打开方式“w”更改为“a”,这样我们就可以在原数据的基础上追加数据。

2. 字符串读写函数fgets 和 fputs

fgets() 的一般形式:
fgets(字符数组名,n,文件指针);

说明:n是一个正整数,表示从文件中读取的字符串不超过n-1个字符,在读入最后一个字符后加上结束符'\0'。

fputs()的一般形式:
fputs(字符数组名,文件指针);

说明:字符数组名,首先其中必须是一个已被初始化的字符数组,即里面有值;也可以用一个字符串常量(或指针变量)代替字符数组名。

//案例6:
#include<stdio.h>

int main()
{
    char ch[20];
    FILE *fp = fopen("./text","rw");
    if (NULL == fp)
    {
      printf("open error\n");
      exit(1);
    }
    printf("input what you want to say:");
    scanf("%s",ch);
    //将字符串ch中的值写在文件text中。
    fputs(ch,fp);
    char ch2[30];
    // 从文件中读取数据,并由ch2字符串变量接收。
    fgets(ch2,sizeof(ch2)-1,fp);
    printf("ch2:%s\n",ch2);
    return 0;
}

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

C语言中不仅提供了字符、字符串的读写方式,同时也提供了数据块的读写方式。它们可用来读写一组数据,如:一个数组元素,一个结构变量的值等。
fread()的一般形式:
fread(buffer,size,count,fp);
fwrite()的一般形式:
fwrite(buffer,size,count,fp);

说明:

  1. buffer 是一个指针,在fread函数中表示存放数据的首地址。在fwrite函数中表示输出数据的首地址;
  2. size 表示数据块的字节数;
  3. count 表示要读写的数据块的块数
  4. fp 表示文件的指针
//案例7:
#include<stdio.h>
struct student
{
    int id;
    char name[20];
    float score;
};

int main()
{
    struct student boy[2];
    int i = 0;
    for (;i < 2; i++)
    {
      printf("input the student's infomation(id, name, score):");
      scanf("%d%s%f",&boy[i]->id,boy[i]->name,&boy[i]->score);
    }
    
    FILE* fp;
    fp = fopen("./student.text","w+");
    if (NULL == fp)
    {
      printf("open file error\n");
      exit(1);
    }
    
    fwrite(boy,sizeof(struct student),2,fp);
    rewind(fp);
    struct student stu[2];
    fread(stu,sizeof(struct student),2,fp);
    printf("id\tname\tscore\n");
    for (i = 0; i < 2; i++)
    {
      printf("%d\t%s\t%f\n",stu[i]->id,stu[i]->name,stu[i]->score);
    }
    return 0;
}

4. 格式化读写函数fscanf 和 fprintf

fscanf、fprintf和scanf、printf的区别:
fscanf和fprintf函数的读写不是对键盘和显示器的,而是对磁盘文件;不过它们都是格式化读写函数。

fscanf 的一般形式:
fscanf(文件指针, 格式字符串, 输入列表);
fprintf 的一般形式:
fprintf(文件指针, 格式字符串, 输出列表);

//案例8:
#include<stdio.h>
int main()
{
    char caBuf[3][32] = {'\0'};
    int i = 0;
    
    for (; i < 3; i++)
    {
      printf("input :");
      scanf("%s", caBuf[i]);
    }
    
    FILE *fp;
    fp = fopen("./MyInput", "wb+");
    if (NULL == fp)
    {
      printf("open file error\n");
      exit(1);
    }
    for (i=0; i < 3; i++)
    {
      fprintf(fp, "%s", caBuf[i]);
    }
    rewind(fp);
    char sMsg[32] = {'\0'};
    for(i=0; i < 3; i++)
    {
      fscanf(fp, "%s", sMsg);
      printf("sMsg: %s\n", sMsg);
    }
    fclose(fp);
    return 0;
}

文件定位

有的时候我们在读写文件时,不想从开头或者末尾开始读或者写;想读取中间的内容,或者是想将一段数据插入到文件中间,我们该怎么做?这时候,我们就需要引入新的知识,文件的定位。

文件定位函数

在文件定位中,主要有两个函数:rewind()和fseek().
rewind() 在前面已经使用,并进行一定的说明,不过在这里还是要重申一下,其一般形式为:
rewind(文件指针);

功能:文件内部的文件指针转移到文件首部。

fseek() 的一般形式:
fseek(文件指针, 位移量, 起始点);

参数说明:
文件指针:被指向移动的文件;
位移量:表示移动的字节数;
起始点:表示从何处开始计算位移量,规定有三种:文件首部(SEEK_SET,1),当前位置(SEEK_CUR,0)和文件尾部(SEEK_END, 2)。

// 案例10:
fseek(fp, 100, 0);
//表示:把文件位置指针移到距离首部100个字节处。

注意事项:fseek()一般用于二进制文件。在文本文件中由于要进行转换,故往往计算位置会出现错误

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

推荐阅读更多精彩内容

  • [TOC] UNIX的哲学,万物皆文件. 打开关闭文件 FILE * fopen(const char *file...
    robinguo2012阅读 719评论 0 0
  • 文件指针 FILE * 指针变量标识符作用:通过该指针即可找到存放某个文件信息的结构变量,然后按结构变量提供的信息...
    永断阎罗阅读 456评论 0 3
  • 语言中对文件进行操作必须首先打开文件,打开文件主要涉及到fopen函数。fopen函数的原型为 FILE* fop...
    朱森阅读 792评论 0 1
  • 文件操作是实际应用的重要部分,本文基于C程序设计(谭浩强版)所写。 C语言文件读写 fopen,fclose(打开...
    静候那一米阳光阅读 371评论 0 0
  • 或许再过几个年头,我们都会分开,可是终归我们曾经相遇过,我对你最大的期望便是健康就好! 很多时候,我们觉得我们是主...
    失忆路人甲yu阅读 290评论 0 0