目录
1 文件驱动器
文件驱动器一般被分为物理驱动器和逻辑驱动器。一个硬盘就是一个物理驱动器,而被系统自动编号的d,e,f等盘符,就是逻辑驱动器。物理驱动器是实实在在能看到的东西,如硬盘驱动器(简称硬盘)、光盘驱动器(简称光驱)、软盘驱动器(简称软驱)。电脑上有几个这样的物理硬件,那就有几个物理驱动器。
新硬盘开始使用前,必须对其进行分区。为了更好地利用硬盘空间,我们通常将其整体空间分成若干个区域,我们在操作系统上看硬盘,比如说Windows的“我的电脑”中,我们看到有“本地磁盘(C)”、“本地磁盘(D)”、“本地磁盘(E)”等,看起来好像有多个硬盘(多个物理驱动器也会表现为上述的形式),其实在逻辑上它们是在一块硬盘上的,这些硬盘分区,称之为逻辑驱动器。逻辑驱动器可以被格式化并指派驱动器号。
至于软盘和光盘,我们一般是不作分区的,若安装上软驱和光驱后,在“我的电脑”里显示“软盘驱动器(或可移动磁盘)(A)”、“CD-ROM(或CD-RW、DVD)驱动器(M)”(M为驱动器号)等,它们都是物理驱动器。不过,一些软件需要读写软盘或必须在光盘上运行,于是便有了一些软件,能将硬盘上的一部分空间模拟成软盘或光盘,使我的电脑中有多个软盘或光盘驱动器,这些我们把它们称为虚拟驱动器而不属于逻辑驱动器的。
硬盘分区有三种,主磁盘分区、扩展磁盘分区、逻辑分区。一个硬盘可以有一个主分区,一个扩展分区,也可以只有一个主分区没有扩展分区。逻辑分区可以若干。 主分区是硬盘的启动分区,他是独立的,也是硬盘的第一个分区,分出主分区后,其余的部分可以分成扩展分区,一般是剩下的部分全部分成扩展分区,也可以不全分,那剩的部分就浪费了。 但扩展分区是不能直接用的,他是以逻辑分区的方式来使用的,所以说扩展分区可分成若干逻辑分区。他们的关系是包含的关系,所有的逻辑分区都是扩展分区的一部分。
2 什么是文件
文件通常是在磁盘或固态硬盘上的一段已命名的存储区。对于操作系统而言,文件更复杂一些,其会包含一些额外的数据用于确定文件的种类。而对于一名普通程序员而言,我们更关心的是如何利用程序处理文件。
所有的文件内容都以二进制形式存储。在C语言中,文件被分为两类:若其中的二进制值代表字符编码,则其为文本文件;若其中的二进制值代表数值数据或图片或音乐编码等,则其为二进制文件。因此,C语言提供了文本模式和二进制模式两种方法对文件进行处理。然而,在UNIX和Linux系统下,这两种模式的实现完全相同。
对于Linux/Windows等系统而言,存在3个标准文件,它们被称为标准输入,标准输出和标准错误输出,C程序会自动打开这3个文件。在默认情况下,标准输入是系统的普通输入设备,即键盘;标准输出和标准错误输出是系统的普通输出设备,即显示屏。
如果采用文件重定向,则可将其他文件视作标准输入或标准输出。而对于标准错误输出,其逻辑稍微有点不同。即使采用重定向的方法将输出指定给文件,发送至标准错误输出的内容仍然会被发送到屏幕上。
3 标准IO
标准文件 | 文件指针 |
---|---|
标准输入 | stdin |
标准输出 | stdout |
标准错误 | stderr |
fopen
/** * @brief 打开文件 * @param pathname 文件的绝对路径 * @param mode 文件打开的模式 * @return 文件句柄(打开成功:文件流指针; 打开失败:NULL) */ FILE *fopen(const char *pathname, const char *mode); /* mode参数: * r或rb 以只读方式打开一个文本文件(不创建文件,文件不存在则报错) * w或wb 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) * a或ab 以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 * r+或rb+ 以可读、可写的方式打开文件(不创建新文件) * w+或wb+ 以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) * a+或ab+ 以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件 */
fclose
/** * @brief 关闭文件 * @param stream 文件流指针(文件句柄) * @note 根据文件句柄关闭文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。 * @return 0:关闭成功; EOF(-1): 关闭失败 */ int fclose(FILE *stream);
fgetc
/** * @brief 根据文件句柄读取一个字符 * @param stream 文件流指针(文件句柄) * @return 成功:返回读取的字符的ASCII码值; 失败:EOF(-1) */ int fgetc(FILE *stream);
fputc
/** * @brief 根据文件句柄写入一个字符 * @param stream 文件流指针(文件句柄) * @param ch 要写入的字符的ASCII码值(将ch转换为unsigned char后写入stream指定的文件中) * @return 成功:返回写入的字符的ASCII码值; 失败:EOF(-1) */ int fputc(int ch, FILE *stream);
fgets
/** * @brief 根据文件句柄读取字符串 * @param s 字符串缓存空间首地址 * @param size 欲读取的字符串大小 * @param stream 文件流指针(文件句柄) * @note 在读取到换行符、或读到文件结尾、或已读取size - 1个字符后停止, 并在字符串末尾自动加上'\0' * @note 在读取到换行符时会将换行符也读入 * @return 成功:返回读取的字符串首地址s; 失败:NULL */ char *fgets(char *s, int size, FILE *stream);
fputs
/** * @brief 根据文件句柄写入字符串 * @param s 字符串缓存空间首地址 * @param stream 文件流指针(文件句柄) * @note 字符串结束符 '\0' 不写入文件 * @return 成功:返回写入文件的字符; 失败:EOF */ int fputs(const char *s, FILE *stream);
fread
/** * @brief 根据文件句柄读取数据 * @param ptr 数据缓存空间首地址 * @param size 读取的数据块大小 * @param nmemb 读取的数据块个数 * @param stream 文件流指针(文件句柄) * @note 读取文件数据总大小为:size * nmemb * @return 成功:实际读取到缓存的数据块个数,如果此值比nmemb小,但大于0,说明读到文件的结尾; 失败:0 */ size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
fwrite
/** * @brief 根据文件句柄写入数据 * @param ptr 数据缓存空间首地址 * @param size 写入的数据块大小 * @param nmemb 写入的数据块个数 * @param stream 文件流指针(文件句柄) * @note 写入文件数据总大小为:size * nmemb * @return 成功:实际写入文件数据的块数目,此值和 nmemb 相等; 失败:0 */ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
ftell
/** * @brief 获取文件句柄的读写指针索引 * @param stream 文件流指针(文件句柄) * @return 成功:当前文件流(文件光标)的读写位置; 失败:-1 */ long ftell(FILE *stream);
fseek
/** * @brief 移动文件句柄的读写指针索引 * @param stream 文件流指针(文件句柄) * @param offset 文件读写指针相对于whence位置的偏移量 * @param whence SEEK_SET:文件开头 SEEK_CUR:当前位置 SEEK_END:文件末尾 * @return 成功:0; 失败:-1 */ int fseek(FILE *stream, long offset, int whence);
rewind
/** * @brief 移动文件句柄的读写指针到文件头 * @param stream 文件流指针(文件句柄) * @note 即将文件读写指针的索引置0 */ void rewind (FILE *stream);
fprintf
/** * @brief 根据文件句柄, 写入格式化字符串到文件中 * @param stream 文件流指针(文件句柄) * @param format 按需的格式化字符串 * @note 成功:返回写入的字符串总数; 失败:-1 */ int fprintf(FILE *stream, const char *format, ...)
fscanf
/** * @brief 根据文件句柄, 读取格式化字符串 * @param stream 文件流指针(文件句柄) * @param format 按需的格式化字符串 * @note 成功:返回成功匹配和赋值的个数; 失败:EOF */ int fscanf(FILE *stream, const char *format, ...)
fgetpos
/** * @brief 获取流 stream 的当前文件位置,并把它写入到 pos */ int fgetpos(FILE *stream, fpos_t *pos)
fsetpos
/** * @brief 设置流 stream 的文件位置。参数 pos 是由函数 fgetpos 给定的位置 */ int fsetpos(FILE *stream, const fpos_t *pos)
ungetc
/** * @brief 将字符c推入到指定流 stream 中,以便它是下一个被读取到的字符 */ int ungetc(int c, FILE *stream)
fflush
/** * @brief 刷新流 stream 的输出缓冲区 * @return 成功:返回0; 失败:返回EOF */ int fflush(FILE *stream)
setvbuf
/** * @brief 定义流 stream 应如何缓冲 * @param stream 文件流指针(文件句柄) * @param buffer 文件数据缓冲区 * @param mode 文件缓存模式 * @param size 文件数据缓冲区大小, 以字节为单位 * @note 应在打开文件后, 且未对流进行其他操作之前, 调用该函数 * @return 成功:返回0; 失败:非0值 */ int setvbuf(FILE *stream, char *buffer, int mode, size_t size) /* mode参数 */ _IOFBF:全缓冲,对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。 _IOLBF:行缓冲,对于输出,数据在遇到换行符或者在缓冲填满时被写入。对于输入,缓冲会在请求输入且缓冲为空时被填充,直到遇到下一个换行符。 _IONBF:无缓冲,不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。
feof
/** * @brief 检查与流stream关联的文件是否到文件尾 * @return 如果检查到了文件尾, 则返回非0值, 否则返回0 */ int feof(FILE *stream)