踩坑分享C 语言文件操作全攻略:从基础读写到随机访问与缓冲区原理

在 C 语言文件操作是一项至关重要的技能。无论是处理数据存储、日志记录,还是进行数据交互,文件操作都扮演着不可或缺的角色。今天,我们就来全面探讨 C 语言文件操作,从基础的读写操作,到高级的随机访问,再深入了解缓冲区的原理。

一、文件操作基础

1.1 文件指针

位标志是一种利用二进制位来表示不同状态或选项的技术。每个二进制位可以看作是一个开关,0 表示关闭,1 表示打开。通过组合不同的二进制位,我们可以表示多种状态的组合。

在 C 语言中,文件操作主要通过文件指针来实现。文件指针是一个指向 FILE 类型结构体的指针,用于标识一个文件。在使用文件之前,需要先打开文件,获取文件指针。

c

#include <stdio.h> int main() { FILE *fp; // 以只读模式打开文件 fp = fopen("test.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 后续操作 fclose(fp); return 0; }

在上述代码中,fopen 函数用于打开文件,第一个参数是文件名,第二个参数是打开模式。如果文件打开失败,fopen 会返回 NULL,我们可以使用 perror 函数输出错误信息。最后,使用 fclose 函数关闭文件。

1.2 打开模式

C 语言提供了多种打开模式,常见的有:

  • r:只读模式,文件必须存在。
  • w:只写模式,如果文件不存在则创建,如果存在则清空内容。
  • a:追加模式,如果文件不存在则创建,写入的数据会追加到文件末尾。
  • r+:读写模式,文件必须存在。
  • w+:读写模式,如果文件不存在则创建,如果存在则清空内容。
  • a+:读写模式,如果文件不存在则创建,写入的数据会追加到文件末尾。

1.3 基础读写操作

字符读写

使用 fgetc 和 fputc 函数可以进行字符的读写操作。

c

#include <stdio.h> int main() { FILE *fp; char ch; // 以写入模式打开文件 fp = fopen("test.txt", "w"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 写入字符 fputc('H', fp); fputc('e', fp); fputc('l', fp); fputc('l', fp); fputc('o', fp); fclose(fp); // 以读取模式打开文件 fp = fopen("test.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 读取字符 while ((ch = fgetc(fp)) != EOF) { printf("%c", ch); } fclose(fp); return 0; }

在上述代码中,fputc 函数用于将字符写入文件,fgetc 函数用于从文件中读取字符,当读取到文件末尾时,fgetc 会返回 EOF。

字符串读写

使用 fgets 和 fputs 函数可以进行字符串的读写操作。

c

#include <stdio.h> int main() { FILE *fp; char str[100]; // 以写入模式打开文件 fp = fopen("test.txt", "w"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 写入字符串 fputs("Hello, World!\n", fp); fclose(fp); // 以读取模式打开文件 fp = fopen("test.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 读取字符串 while (fgets(str, sizeof(str), fp) != NULL) { printf("%s", str); } fclose(fp); return 0; }

fputs 函数用于将字符串写入文件,fgets 函数用于从文件中读取一行字符串,最多读取 sizeof(str) - 1 个字符,最后一个字符为 '\0'。

格式化读写

使用 fprintf 和 fscanf 函数可以进行格式化的读写操作,类似于 printf 和 scanf 函数。

c

#include <stdio.h> int main() { FILE *fp; int num; // 以写入模式打开文件 fp = fopen("test.txt", "w"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 格式化写入 fprintf(fp, "The number is %d\n", 123); fclose(fp); // 以读取模式打开文件 fp = fopen("test.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 格式化读取 fscanf(fp, "The number is %d", &num); printf("The number read from file is %d\n", num); fclose(fp); return 0; }

fprintf 函数用于将格式化的数据写入文件,fscanf 函数用于从文件中读取格式化的数据。

二、随机访问

2.1 文件位置指针

在文件操作中,有一个文件位置指针,它指向当前文件的读写位置。可以使用 ftell 函数获取当前文件位置指针的值,使用 fseek 函数移动文件位置指针。

c

#include <stdio.h> int main() { FILE *fp; long pos; // 以读写模式打开文件 fp = fopen("test.txt", "r+"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 获取当前文件位置 pos = ftell(fp); printf("Current position: %ld\n", pos); // 移动文件位置指针 fseek(fp, 5, SEEK_SET); // 从文件开头移动 5 个字节 pos = ftell(fp); printf("New position: %ld\n", pos); fclose(fp); return 0; }

ftell 函数返回当前文件位置指针的值,fseek 函数用于移动文件位置指针。fseek 函数的第一个参数是文件指针,第二个参数是偏移量,第三个参数是起始位置,SEEK_SET 表示从文件开头开始,SEEK_CUR 表示从当前位置开始,SEEK_END 表示从文件末尾开始。

2.2 随机读写

通过移动文件位置指针,我们可以实现随机读写操作。

c

#include <stdio.h> int main() { FILE *fp; int num; // 以读写模式打开文件 fp = fopen("test.txt", "r+"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 写入数据 for (int i = 0; i < 10; i++) { fwrite(&i, sizeof(int), 1, fp); } // 移动文件位置指针 fseek(fp, 3 * sizeof(int), SEEK_SET); // 读取数据 fread(&num, sizeof(int), 1, fp); printf("The number at position 3 is %d\n", num); fclose(fp); return 0; }

fwrite 函数用于将数据写入文件,fread 函数用于从文件中读取数据。通过移动文件位置指针,我们可以在文件的任意位置进行读写操作。

三、缓冲区原理

3.1 缓冲区的概念

在文件操作中,缓冲区是一个临时存储区域,用于减少对磁盘的频繁读写操作。当我们进行文件读写时,数据先被写入缓冲区,当缓冲区满或者调用 fflush 函数时,缓冲区中的数据才会被写入磁盘。同样,当我们从文件中读取数据时,数据先被从磁盘读取到缓冲区,然后再从缓冲区读取到程序中。

3.2 缓冲区类型

C 语言有三种缓冲区类型:

  • 全缓冲:缓冲区满时才进行实际的 I/O 操作,通常用于磁盘文件。
  • 行缓冲:遇到换行符时进行实际的 I/O 操作,通常用于终端输入输出。
  • 无缓冲:不使用缓冲区,数据立即进行 I/O 操作,通常用于标准错误输出。

3.3 缓冲区的控制

可以使用 setvbuf 函数来设置缓冲区的类型和大小。

c

#include <stdio.h> int main() { FILE *fp; char buffer[1024]; // 以写入模式打开文件 fp = fopen("test.txt", "w"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 设置全缓冲 setvbuf(fp, buffer, _IOFBF, sizeof(buffer)); // 写入数据 for (int i = 0; i < 100; i++) { fputc('A', fp); } // 刷新缓冲区 fflush(fp); fclose(fp); return 0; }

setvbuf 函数的第一个参数是文件指针,第二个参数是缓冲区数组,第三个参数是缓冲区类型,_IOFBF 表示全缓冲,_IOLBF 表示行缓冲,_IONBF 表示无缓冲,第四个参数是缓冲区大小。

3.4 缓冲区的刷新

可以使用 fflush 函数来刷新缓冲区,将缓冲区中的数据立即写入磁盘

c

#include <stdio.h> int main() { FILE *fp; // 以写入模式打开文件 fp = fopen("test.txt", "w"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 写入数据 fputs("Hello, World!\n", fp); // 刷新缓冲区 fflush(fp); fclose(fp); return 0; }

fflush 函数可以确保缓冲区中的数据及时写入磁盘,避免数据丢失。

C++ 位标志在枚举类型设计中是一个非常强大的工具,它可以帮助我们高效地表示和处理多个状态的组合。通过合理使用位标志,我们可以节省内存、提高代码的执行效率,并且使代码更加简洁。在使用位标志时,要注意枚举值的设置、类型安全和溢出问题。同时,我们还可以运用一些高级技巧,如动态添加和移除标志、检查所有标志是否都被设置等。希望通过本文的介绍,你对 C++ 位标志在枚举类型设计中的应用有了更深入的理解,能够在实际编程中灵活运用这一技巧。

C 语言的文件操作涵盖了从基础的读写到高级的随机访问,以及缓冲区的管理。通过掌握文件指针、打开模式、读写函数、随机访问和缓冲区原理,我们可以高效地进行文件操作。在实际应用中,需要根据具体需求选择合适的文件操作方式,同时注意缓冲区的管理,以提高程序的性能和数据的安全性。

希望通过本文的介绍,你对 C 语言文件操作有了更全面的了解,能够在实际编程中灵活运用这些知识,处理各种文件操作任务。记住,文件操作是 C 语言编程中非常重要的一部分,熟练掌握它将为你的编程之路增添更多的可能性。

相关推荐
码云数智-大飞1 小时前
滥用Lombok的@EqualsAndHashCode导致线上事故复盘
开发语言
yong99901 小时前
C# 实时查看硬件使用率(CPU 内存 硬盘 网络)
开发语言·网络·c#
不午休の野猫1 小时前
vs + qt环境编译.sln项目时报无法解析的外部符号metaObject && qt_metacast
开发语言·qt
吴声子夜歌2 小时前
Java——接口的细节
java·开发语言·算法
阿拉金alakin2 小时前
深入理解 Java 锁机制:CAS 原理、synchronized 优化与主流锁策略全总结
java·开发语言
myheartgo-on2 小时前
Java—方 法
java·开发语言·算法·青少年编程
雨落在了我的手上2 小时前
如何学习java?
java·开发语言·学习
神仙别闹3 小时前
基于 C# OpenPGP 的文件管理系统
开发语言·c#
番石榴AI3 小时前
纯 CPU 推理!0.1B 超轻量级端到端OCR模型,使用 Java 进行文档解析
java·开发语言·ocr