桓楠百科网

编程知识、经典语录与百科知识分享平台

C语言文件操作:看代码秒懂标准I/O vs 系统I/O!

处理硬盘文件是C语言基本功。主流方法就两种:标准I/O(stdio.h)系统I/O/低级I/O(unistd.h, fcntl.h)。记住:日常首选标准I/O!系统I/O仅在特定需求时才用。

核心差异一句话:标准I/O有“缓冲区”(预加载数据,效率高),系统I/O是原始字节流操作**(控制精细)。

代码对比直击核心

场景1:打开/关闭文件

//  标准I/O:fopen + fclose (FILE*)
#include <stdio.h>
int main() {
    // 打开: "r"(读), "w"(写), "a"(追加), "rb"(读二进制)...
    FILE *file = fopen("data.txt", "r");
    if (!file) { perror("Error opening file"); return 1; } //  务必检查错误!
    // ... 读写操作在此 ...
    fclose(file); //  务必关闭! 释放资源 & 刷新缓冲区
    return 0;
}

//  系统I/O:open + close (文件描述符 int fd)
#include <fcntl.h> // O_RDONLY, O_WRONLY, O_CREAT
#include <unistd.h>
int main() {
    // 打开: O_RDONLY(只读), O_WRONLY|O_CREAT(写+创建), O_APPEND(追加)...
    int fd = open("data.bin", O_RDONLY, 0644); // 0644是文件权限(如需要)
    if (fd == -1) { perror("Error opening file"); return 1; } //  务必检查错误!
    // ... 读写操作在此 ...
    close(fd); //  务必关闭! 释放文件描述符
    return 0;
}

场景2:读取文本文件(一行)

//  标准I/O:简单读行 (fgets)
char buffer[256];
if (fgets(buffer, sizeof(buffer), file) != NULL) {
    printf("Read line: %s", buffer);
} // 缓冲区大小足够,自动处理行尾\n

//  系统I/O:原始读(read) + 自己解析 (更繁琐)
char buffer[256];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1); // -1预留结尾\0位置
if (bytes_read > 0) {
    buffer[bytes_read] = '\0'; //  手动加字符串结束符!
    // 你可能需要遍历buffer找换行符\n来“切分”行
    printf("Read data: %s", buffer);
} else if (bytes_read == 0) { /* EOF */ }
else { perror("Read error"); }

场景3:写入格式化数据到文本文件

//  标准I/O:像printf一样写文件 (fprintf) - 超方便!
int num = 42;
char *text = "Hello";
fprintf(file, "Number: %d\nText: %s\n", num, text); //  自动格式化,带换行

//  系统I/O:需自己拼接格式化字符串 (麻烦!)
char buffer[256];
int num = 42;
char *text = "Hello";
int len = snprintf(buffer, sizeof(buffer), "Number: %d\nText: %s\n", num, text);
if (len >= sizeof(buffer)) { /* 缓冲区溢出风险 */ }
write(fd, buffer, len); //  只写有效部分len, 包含\n

场景4:读写二进制数据(结构体)

//  标准I/O:直接读写整块内存 (fread/fwrite)
struct Data {
    int id;
    float value;
} myData, readData;

myData.id = 1;
myData.value = 3.14f;

// 写入
fwrite(&myData, sizeof(struct Data), 1, file); //  高效写入整个结构体

// 读取
if (fread(&readData, sizeof(struct Data), 1, file) == 1) {
    printf("Read ID: %d, Value: %.2f\n", readData.id, readData.value);
}

//  系统I/O:同样读写字节流 (read/write)
struct Data myData, readData;
myData.id = 1;
myData.value = 3.14f;

// 写入
write(fd, &myData, sizeof(struct Data)); //  直接写内存块

// 读取
ssize_t bytes_read = read(fd, &readData, sizeof(struct Data));
if (bytes_read == sizeof(struct Data)) { /* 成功读取 */ }

核心差异速查表:

特性

标准I/O (stdio.h)

系统I/O (unistd.h)

代表函数

fopen, fprintf, fread, fclose

open, read, write, close

对象

FILE*(文件指针)

int fd(文件描述符)

核心优势

带缓冲区(高效)

精细控制(权限/设备/锁)

关键工具

格式化 (fprintf/fscanf)

原始字节操作

错误处理

检查返回值(NULL, 0等)

检查返回值(-1) & errno

首要选择

YES! (90%场景)

特殊需求(设备/控制权)

选择指南一句话:

  • 做文件?用 fopen+ fprintf/fscanf/fread/fwrite+ fclose(标准I/O)!高效又省心!
  • 玩设备/搞底层?才轮到 open+ read/write+ close(系统I/O)。

必记忠告:

  1. 无论用哪种,必须检查函数返回值! 文件操作容易出错。
  2. 绝对不要忘记关闭文件 (fclose/ close)! 忘记关文件是严重的资源泄漏!
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言