c语言 文件操作

文件流

文件流概念

C 语言把文件看作是一个字符的序列,即文件是由一个一个字符组成的字符流,因
此 c 语言将文件也称之为文件流。即,当读写一个文件时,可以不必关心文件的格式或
结构。
在这里插入图片描述

文件类型

文件分类

大家都知道计算机的存储,物理上是二进制的,所以文本文件与二进制文件的区
别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文
本文件是基于字符编码的文件,常见的编码有 ASCII 编码,二进制文件是基于值编码
的文件。

文本文件:以 ASCII 码格式存放,一个字节存放一个字符。 文本文件的每一个
字节存放一个 ASCII 码,代表一个字符。这便于对字符的逐个处理,但占用存储空间
较多,而且要花费时间转换。

二进制文件:以值(补码)编码格式存放。二进制文件是把数据以二进制数的格
式存放在文件中的,其占用存储空间较少。数据按其内存中的存储形式原样存放。

请添加图片描述

请添加图片描述

#include <stdio.h>
int main()
{
   
    //short a = 10000;
    //FILE * fp = fopen("ascii.txt", "w");
    //fprintf(fp, "%d", a);
    //fclose(fp);
    //FILE *fp2 = fopen("bin.txt", "w");
    //fwrite(&a, 2, 1, fp2);
    //fclose(fp2);
    //花费时间用于转化
    //占用磁盘空间多,磁盘中的文件,易读
    char *buf = "abcdefg";
    FILE* fp = fopen("ascii2.txt", "w");
    fprintf(fp, "%s", buf);
    fclose(fp);
    //不需要花费时间转化
    //相比于文本,占用磁盘空间小,磁盘文件不易读
    FILE * fp2 = fopen("bin2.txt", "w");
    fwrite(buf, 8, 1, fp2);
    fclose(fp2);
    return 0;
}

乱码原由

举例文本工具,打开文件的过程。拿记事本来说,它首先读取文件物理上所对应
的二进制比特流,然后按照你所选择的解码方式来解释这个流,然后将解释结果显示
出来。一般来说,你选取的解码方式会是 ASCII 码形式(ASCII 码的一个字符是 8 个比
特),接下来,每 8 个比特 8 个比特地来解释这个文件流。
例如文件流 01000000_01000001_01000010_01000011"(下划线''_'',为了增强可读
性手动添加的),第一个 8 比特''01000000''按 ASCII 码来解码的话,所对应的字符是字
符''A'',同理其它 38 比特可分别解码为''BCD'',即这个文件流可解释成"ABCD",
然后记事本就将这个"ABCD"显示在屏幕上。
记事本无论打开什么文件都按既定的字符编码工作(如 ASCII 码),所以当他打
开二进制文件时,出现乱码也是很必然的一件事情了,解码和译码不对应嘛。
例如文件流''00000000_00000000_00000000_00000001''可能在二进制文件中对
应的是一个四字节的整数 int 1,在记事本里解释就变成了"NULL_NULL_NULL_SOH"这
四个控制符。

img_4.png请添加图片描述

文件缓冲

为什么要有缓冲区(buffer) 原因为多种,有两个重点:

1.从内存中读取数据比从文件中读取数据要快得多。

2.对文件的读写需要用到 open、read、write 等系统底层函数,而用户进程每调用
一次系统函数都要从用户态切换到内核态,等执行完毕后再返回用户态,这种切
换要花费一定时间成本(对于高并发程序而言,这种状态的切换会影响到程序性
能)。

请添加图片描述

举个例子,如果程序需要处理 10K 个整数(或者 10K 个字符等等),而这些整数
事先存在某个文件中,如果程序每处理一个整数就要从文件中读一个整数(read 系统
调用),那么每次都要进行硬件 I/O、进程状态切换等操作,这样效率是非常低下的。
如果每次从文件中读出 1K 个整数到内存,程序从内存中读取数据并处理,那么程序的
性能会明显提高,存储这 1K 个整数的内存区域就是一个缓冲区。

#include <stdio.h>   // linux code only
int main()
{
   
  while (1)
  {
   
    printf("abcdefg");  //缓冲区满,则会写入文件。
    usleep(10000);
  }
  return 0;        // 也可以通过 fclose 和 fflush 刷缓冲的
}

文件的打开和关闭

FILE 结构体

在 C 语言中,文件操作都通过 FILE 结构体来实现的。FILE 结构体定义如下:

typedef struct {
   
    short     level;           /* 缓冲区满/空程度 */
    unsigned  flags;           /* 文件状态标志 */
    char  fd;                 /* 文件描述符 */
    unsigned char  hold;        /* 若无缓冲区不读取字符 */
    short  bsize;              /* 缓冲区大小 */
    unsigned char  *buffer;     /*  数据传送缓冲区位置 */
    unsigned char  *curp;       /* 当前读写位置 */
    unsigned  istemp;          /* 临时文件指示 */
    short  token;              /* 用作无效检测 */
} FILE ;                        /* 结构体类型名 FILE */

在开始执行程序的时候,将自动打开 3 个文件和相关的流:标准输入流(stdin)、标
准输出流(stdout)和标准错误(stderr),它们都是 FIEL*型的指针。流提供了文件和程序的
通信通道。

fopen

函数原型:

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

功能:以 mode 的方式,打开一个 filename 命名的文件,返回一个指向该文件
缓冲的 FILE 结构体指针。

参数:

  • filename:要打开的文件名。
  • mode:打开文件的方式。

返回值:成功打开文件,返回一个指向 FILE 结构体的指针;失败返回 NULL。

mode参数:

  • r:以只读方式打开文件。
  • w:以写方式打开文件,若文件不存在则创建文件,若文件存在则清空文件内容。
  • a:以追加方式打开文件,若文件不存在则创建文件,若文件存在则从文件尾部开始写。
  • r+:以读写方式打开文件。
  • w+:以读写方式打开文件,若文件不存在则创建文件,若文件存在则清空文件内容。
  • a+:以读写方式打开文件,若文件不存在则创建文件,若文件存在则从文件尾部开始写。
  • rb:以二进制只读方式打开文件。
  • wb:以二进制写方式打开文件,若文件不存在则创建文件,若文件存在则清空文件内容。
  • ab:以二进制追加方式打开文件,若文件不存在则创建文件,若文件存在则从文件尾部开始写。
  • rb+:以二进制读写方式打开文件。
  • wb+:以二进制读写方式打开文件,若文件不存在则创建文件,若文件存在则清空文件内容。
  • ab+:以二进制读写方式打开文件,若文件不存在则创建文件,若文件存在则从文件尾部开始写。

请添加图片描述

fclose

函数原型:

int fclose(FILE *fp);

功能:fclose()用来关闭先前 fopen()打开的文件. 此动作会让缓冲区内的
数据写入文件中, 并释放系统所提供的文件资源.

参数:

  • fp:一个指向 FILE 结构体的指针。

返回值:成功返回 0;失败返回 EOF。

一次读写一个字符(文本操作)

fputc

函数原型:

int fputc(int c, FILE *fp);

功能:fputc()函数向文件中写入一个字符。

参数:

  • c:要写入的字符。
  • fp:一个指向 FILE 结构体的指针。

返回值:成功返回写入的字符值;失败返回 EOF。

#include <stdio.h>
int main()
{
   
    FILE* fp = fopen("ascii.txt","w");
    if(fp == NULL)
    {
   
        printf("open error\n");
        return -1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可能只会写BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值