C语言深入学习 --- 6.文件操作

本文详细介绍了C语言中文件操作的关键概念,包括文件的定义、打开与关闭、顺序和随机读写、文本与二进制文件的区别、文件结束判定以及文件缓冲区的工作原理。同时提到了与之相关的动态内存管理内容及其实践练习。
摘要由CSDN通过智能技术生成

文章目录

第六章 文件操作

内容:

1.使用文件的意义

2.文件的定义

3.文件的打开和关闭

4.文件的顺序读写

5.文件的随机读写

6.文本文件和二进制文件

7.文件读取结束的判定

8.文件缓冲区

1.使用文件的意义

使用文件可以将数据直接存放在电脑的硬盘上,使得数据的持久化。

2.文件的定义

文件是指一个可独立操作的程序,可是文本、图片、声音、视频等,不同文件可用不同程序来打开。

在程序设计中,一般谈两种文件:程序文件、数据文件(从文件功能的角度去分类的)。

2.1 程序文件

包含源程序文件(.c),目标文件(.obj),可执行程序(.exe)。

2.2 数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,如程序运行需从中读取数据文件,或输出内容的文件。

本章主要讨论数据文件。

2.3 文件名

一个文件需要有唯一的文件标识,以便来用来识别和引用。

文件名包含了三个部分:文件路径+文件名主干+文件后缀

例:c:\test\text.txt

文件标识常被称为文件名

3.文件的打开和关闭

3.1 文件指针

缓冲文件系统中,关键概念在于“文件类型指针”,简称为“文件指针“。

每个被使用的文件都会在内存开辟一个相对应的文件信息区,来存放文件相关信息(比如文件的名字、状态、当前位置等等)。这些信息都存在一个结构体变量中,这个结构体类型有系统声明,名为FILE。

VS2013环境下的stdio.h头文件中有以下文件的类型声明:


struct _iobuf {
        char* _ptr;
        int   _cnt;
        char* _base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char* _tmpfname;
};
typedef struct _iobuf File;

不同编译器的FILE类型包含内容有所不同,但是大同小异。

每打开一个文件时,系统会根据文件情况自动创建一个FILE结构变量,并填充里面的信息。

一般通过一个FILE指针来维护FILE结构变量,使用起来更加便捷。

创建一个FILE*的指针变量:

FILE* pf; //文件指针变量

pf是一个指向FILE类型数据的指针变量,可使pf指向某个文件的文件信息区。通过文件信息区的信息能够访问该文件。通过文件指针变量能够找到与其关联的文件。

3.2 如何打开和关闭

文件在读写时应该先要打开文件,然后在使用结束后应该关闭文件。

打开文件的同时,会返回一个FILE*的指针变量指向该文件,建立了指针与文件之间的联系。

打开文件:fopen函数 关闭文件:fclose函数

FILE* fopen(const char* filename, const char* mode);

int fclose(FILE* stream);

打开方式:

文件使用方式意义指定文件不存在时
”r“(只读)为了输入数据,打开一个已存在的文本文件error
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
”a“(追加)向文本文件尾添加数据建立一个新的文件
”rb“(只读)为了输入数据,打开一个二进制文件errror
”wb“(只写)为了输出数据,打开一个二进制文件建立一个新的我呢见
”ab“(追加)向一个二进制文件尾添加数据errror
”r+“(读写)以可读写方式打开文件errror
”w+“(读写)打开只写文件建立一个新的文件
”a+“(读写)打开一个文件,在文件尾进行读写建立一个新的文件
”rb+“(读写)为了读和写打开一个二进制文件errror
”wb+“(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
”ab+“(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

例:

#include <stdio.h>

int main()
{
    FILE* pf;
    pf = fopen("test.txt","w");
    if (pf != NULL)
    {
        fputs("Hello World",pf);

        fclose(pf);
    }
    return 0;
}

4.文件的顺序读写

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数foutc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fouts所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入函数fread文件
二进制输出函数fwrite文件
4.1 对比一组函数

scanf/fscanf/sscanf

printf/fprintf/sprintf

5.文件的随机读写

5.1 fseek

根据文件指针所在位置和偏移量来定位文件指针。

int fseek(FILE* stream, long int offset, int origin);

origin:

SEEK_CUR //文件指针当前位置

SEEK_END //文件指针末尾

SEEK_SET //文件指针初始位置

#include <stdio.h>

int main()
{
    FILE* pf = fopen("text.txt","w");
    if (pf == NULL)
    {
        perror(fopen);
        return 1;
    }
    fputs("Hello World", pf);
    fseek(pf ,3, SEEK_SET);
    fputs("hh",pf);
    fclose(pf);
    pf = NULL;
    return 0;
}
5.2 ftell

返回文件指针相对于起始地址的偏移量

long int ftell(FILE* stream);
#include <stdio.h>

int main()
{
    int sz = 0;
    FILE* pf = fopen("text.txt","r");
    if (pf == NULL)
    {
        perror(fopen);
        return;
    }
    fseek(pf, 0, SEEK_END);
    sz = ftell(pf);
    fclose(pf);
    pf = NULL;
    printf("%d", sz);
    return 0;
}
5.3 rewind

让文件指针回到文件的起始位置

void rewind(FILE* stream);
#include <stdio.h>

int main()
{
    FILE* pf = fopen("text.txt", "w");
    if (!pf)
    {
        perror(fopen);
        return;
    }
    fputs("This is sample", pf);
    fseek(pf, 6, SEEK_SET);
    rewind(pf);
    fputs("ar",pf);
    fclose(pf);
    pf = NULL;
    return 0;
}

6.文本文件和二进制文件

  • 数据文件被称为文本文件或者二进制文件

数据在内存以二进制的形式存储,没有转换输出到外存,为二进制文件。

外存要求以ASCII码形式存储,那么在存储前需要进行转换。以ASCII字符形式存储的文件为文本文件。

  • 一个数据在内存中的存储:

字符都以ASCII形式存储,数值型既可用ASCII形式存储,也可用二进制形式存储。

如果有一个整数10000,用ASCII形式输出至磁盘,在磁盘中占用5个字节(一个字符占用一个字节),用二进制形式输出,在磁盘占用4个字节。

10000(十进制)的二进制存储
00000000 00000000 00100111 00010000
00110001 00110000 00110000 00110000 00110000 //ASCII形式
00000000 00000000 00100111 00010000  //二进制形式
#include <stdio.h>

int main()
{
    int n = 10000;
    FILE* pf = fopen("text.txt","wb");
    if (!pf)
    {
        perror(fopen);
        return;
    }
    fwrite(&n, sizeof(int), 1, pf);

    fclose(pf);
    pf = NULL;
    return 0;
}

7.文件读取结束的判定

7.1 被错用的feof

在文件读取过程中,不可以实用feof函数的返回值直接用来判断文件的结束与否。

它应用于文件读取结束时,判断是读取失败结束,还是遇到文件尾结束。

1.文件文本读取是否结束,判断返回值是否为EOF,或NULL。

  • fgetc判断是否为EOF.

  • fgets判断返回值是否为NULL.

2.二进制文件的读取结束判断,判断返回值是否小于要读取的个数。

  • fread判断返回值是否小于要读的个数
#include <stdio.h>

int main()
{
    int ch = 0;
    FILE* pf = fopen("text.txt","r");
    if (!pf)
    {
        perror("fopen");
        return;
    }

    while ((ch = fgetc(pf)) != EOF)
    {
        putchar(ch);
    }

    printf("\n");

    if (ferror(pf))
    {
        puts("error\n");
    }
    else if (feof(pf))
    {
        puts("success\n");
    }
    return 0;
}

8.文件缓冲区

ANSIC标准采用缓冲文件系统处理的数据文件,缓冲文件系统指系统自动在内存中为程序中每一个正在使用的文件开辟一块文件缓冲区。从内存向磁盘输出数据会先送到内存中的缓冲区,装满后才一起送到磁盘。如果磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满),然后再从缓冲区逐个将数据送到程序数据区。缓冲区大小本剧C编译系统而定。

#include <stdio.h>
#include <windows.h>

int main()
{
    FILE* pf = fopen("text.txt", "w");
    fputs("hello", pf);
    printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
    Sleep(10000);
    printf("刷新缓冲区\n");
    fflush(pf); //刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
    //fflush 在高版本的VS上不能使用了
    printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
    Sleep(10000);
    fclose(pf);
    //fclose在关闭文件的时候,也会刷新缓冲区
    pf = NULL;
    return 0;
}

上一章:C语言深入学习 — 5.动态内存管理

配套练习:

C语言练习题110例(一)
C语言练习题110例(二)
C语言练习题110例(三)
C语言练习题110例(四)
C语言练习题110例(五)
C语言练习题110例(六)
C语言练习题110例(七)
C语言练习题110例(八)
C语言练习题110例(九)
C语言练习题110例(十)
C语言练习题110例(十一)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值