一、文件的概念
文件是计算机中用于存储和组织数据的基本单位,它可以包含各种类型的数据,如程序代码、文本文档、音频文件、视频文件和图像等。这些文件被存储在磁盘或其他存储介质上,以方便用户对数据进行访问、编辑和管理。
在Windows操作系统中,我们可以通过各种文本编辑器(如写字板或记事本)来打开和编辑文本文件。这些文本编辑器是微软程序员开发的应用程序,它们提供了直观的界面,使用户可以方便地对文件进行打开、显示、读写和保存等操作。通过这些编辑器,我们可以轻松地创建新文件、修改已有文件的内容,并将编辑后的结果保存到磁盘上。
对于程序员来说,掌握文件操作是一项基本技能。他们需要能够使用编程语言来创建、写入、读取和处理文件。这些操作在许多软件开发任务中都是必不可少的,例如编写文件传输程序(如飞秋软件)时,就需要能够读取源文件的内容并将其写入目标位置。
文件操作的常见任务包括:
- 创建文件:使用编程语言的内置函数或库来创建一个新的空文件。
- 写入文件:将数据(如文本、图像或二进制数据)写入文件中。这可以通过顺序写入或随机访问文件来实现。
- 读取文件:从文件中读取数据,并将其加载到内存中进行处理。
- 修改文件:对文件的内容进行修改,包括添加、删除或替换数据。
- 删除文件:从存储介质中删除不再需要的文件。
通过掌握这些文件操作技能,程序员可以开发出功能强大、易于使用和可靠的软件应用程序,满足用户对数据处理和存储的需求。无论是开发简单的文本编辑器还是复杂的企业级应用,文件操作都是构建现代软件系统的基础。
1.1 文件的定义
磁盘文件:(我们通常认识的文件)
指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存。
设备文件:
在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输 入、输出等同于对磁盘文件的读和写。
键盘:标准输入文件
屏幕:标准输出文件 其它设备:打印机、触摸屏、摄像头、音箱等 在Linux操作系统中,每一个外部设备都在/dev目录下对应着一个设备文件,咱们在程序中要想操作设备,就必须对与其对应的/dev下的设备文件进行操作。
标准io库函数对磁盘文件的读取特点
文件缓冲区是库函数申请的一段内存,由库函数对其进行操作,程序员没有必要知道存放在 哪里,只需要知道对文件操作的时候的一些缓冲特点即可。
1、行缓冲
标准io库函数,往标准输出(屏幕)输出东西的时候是行缓冲的 所谓的行缓冲就是缓冲区碰到换行符的时候才刷新缓冲区
如果不刷新缓冲区,无法对文件执行读写操作
行缓冲的刷新条件:
#include <stdio.h>
int main(int argc, char const *argv[])
{
//由于printf函数是一个标准io,所以只有刷新缓冲区才可以将数据输出到终端
//printf("hello world");
//刷新缓冲区方法1:使用\n
//printf("hello world\n");
//刷新缓冲区方法2:程序正常结束
//printf("hello world");
//return 0;
//刷新缓冲区方法3:使用fflush函数刷新缓冲区
//printf("hello world");
//fflush:刷新函数。可以刷新指定的缓冲区
//stdout:标准输出,就是对终端进行写操作
//fflush(stdout);
//刷新缓冲区方法4:当缓冲区满的时候自动刷新
//默认行缓冲的大小为1024个字节
int i;
for(i = 1; i < 300; i++)
{
printf("%03d ", i);
}
while(1)
;
return 0;
}
2、全缓冲
标准io库函数 ,往普通文件读写数据的,是全缓冲的,
碰到换行符也不刷新缓冲区,即缓冲区满了,才刷新缓冲区
刷新缓冲区的情况
1.缓冲区满了,刷新缓冲区
2.人为刷新缓冲区 fflush(文件指针)
3.程序正常结束 会刷新缓冲区
3.无缓冲
在读写文件的时候通过系统调用io (read write),对文件进行读写数据 这个时候是无缓冲的,即写数据会立马进入文件,读数据会立马进入内存
写文件的流程
当一个应用程序需要将数据写入文件时,它会按照以下步骤进行操作:
-
应用程序空间:首先,应用程序在用户空间(应用程序空间)中准备要写入的数据。
-
系统调用:然后,应用程序通过系统调用(如
write
或fwrite
)请求操作系统将数据写入文件。这会导致操作系统切换到内核空间。 -
内核空间:在内核空间中,操作系统的内核会接管控制权。它会检查应用程序是否有权限执行该操作,并验证文件路径和文件描述符等参数的合法性。
-
驱动程序:一旦内核确认了操作的合法性,它就会调用相应的文件系统驱动程序。文件系统驱动程序负责与底层存储设备(如硬盘)进行通信。
-
硬盘:最终,数据通过驱动程序传输到硬盘上,并被写入到指定的文件中。
设置缓冲区的目的
通过缓冲可以减少进出内核的次数,以提高效率。
1.2 磁盘文件的分类
一个文件通常是磁盘上一段命名的存储区
计算机的存储在物理上是二进制的,
所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储
从用户或者操作系统使用的角度(逻辑上)把文件分为:
文本文件: 基于字符编码的文件
基于字符编码,常见编码有ASCII、UNICODE等 一般可以使用文本编辑器直接打开
例如:数5678的以ASCII存储形式为:
ASCII码:00110101 00110110 00110111 00111000 歌词文件(lrc):文本文件
二进制文件:基于值编码的文件
- 二进制编码:二进制文件使用二进制编码来存储数据,这意味着每个数据元素都被表示为一串二进制位(bit)。例如,一个整数可以被表示为32位的二进制数,一个字符可以被表示为8位的二进制数。
- 变长编码:二进制文件的编码是变长的,这意味着不同的数据元素可以使用不同长度的二进制编码来表示。这种灵活性使得二进制文件在存储和传输数据时更加高效。
- 自定义编码:二进制文件的编码规则通常是自定义的,根据具体的应用需求而定。例如,一个图像文件可能会使用特定的二进制编码来表示图像的像素数据。
二进制文件通常由文件头和数据区组成。
- 文件头:文件头包含了关于文件的元信息,如文件格式、版本号、文件大小等。这些信息可以帮助程序正确地解析和处理文件中的数据。
- 数据区:数据区包含了文件的实际数据内容。根据文件类型的不同,数据区可以包含各种类型的数据,如图像的像素数据、音频的采样数据等。
二进制文件广泛应用于各种计算机应用中,包括:
- 可执行程序:计算机程序通常以二进制文件的形式存储和执行。
- 多媒体文件:图像、音频和视频文件通常以二进制文件的形式存储,以高效地表示和传输多媒体数据。
- 数据交换:二进制文件也常用于不同程序或系统之间的数据交换,因为它们可以包含复杂的数据结构。
文本文件、二进制文件对比:
译码:
文本文件编码基于字符定长,译码容易些;
二进制文件编码是变长的,译码难一些(不同的二进制文件格式,有不同的译码方式)。
空间利用率:
二进制文件用一个比特来代表一个意思(位操作);
而文本文件任何一个意思至少是一个字符。
二进制文件,空间利用率高
可读性:
文本文件用通用的记事本工具就几乎可以浏览所有文本文件
二进制文件需要一个具体的文件解码器,比如读BMP文件,必须用读图软件。
总结一下: 文件在硬盘上存储的时候,物理上都是用二进制来存储的。
标准io库函数对文件操作的时候,不管文件的编码格式(字符编码、或二进制),而是按字节对文件进行读写,所以咱们管文件又叫流式文件,即把文件看成一个字节流。
二、文件指针
文件指针就是用于标识一个文件的,所有对文件的操作都是用对文件指针进行操作的
定义文件指针的一般形式为:
FILE * 指针变量标识符;
本质上文件指针是一个结构体指针,结构体中包含了当前文件的很多信息,但是在实际编程时, 不需要关系结构体中的成员,只需要使用文件指针即可
对文件操作的步骤
1、对文件进行读写等操作之前要打开文件得到文件指针
2、可以通过文件指针对文件进行读写等操作
3、读写等操作完毕后,要关闭文件,关闭文件后,就不能再通过此文件指针操作文件了
c语言中有三个特殊的文件指针无需定义,在程序中可以直接使用
stdin: 标准输入默认为当前终端(键盘)
我们使用的scanf、getchar函数默认从此终端获得数据
stdout:标准输出 默认为当前终端(屏幕)
我们使用的printf、puts函数默认输出信息到此终端
stderr:标准错误输出设备文件 默认为当前终端(屏幕)
当我们程序出错使用:perror函数时信息打印在此终端