Linux系统编程 - 文件操作
一、Linux文件类型(7种)
| 类型标识 | 说明 | 示例/命令 |
|---|---|---|
- |
普通文件(文本、二进制、图片等) | .c, .out, 1.txt |
d |
目录文件 | .vimplus/ |
l |
软链接文件(符号链接) | .vimrc -> /home/linux/.vimplus/.vimrc |
c |
字符设备文件(顺序访问) | /dev/rtc0 |
b |
块设备文件(随机访问) | /dev/sda(硬盘) |
s |
套接字文件(网络通信) | 网络相关文件 |
p |
管道文件(进程通信) | 进程间通信文件 |
二、man帮助手册使用
# 查看所有man帮助分类
man man
# 查看命令(第1类)
man ls # 等价于 man 1 ls
# 查看系统调用函数(第2类)
man 2 open
man 2 read
man 2 write
# 查看标准库函数(第3类)
man 3 fopen
man 3 printf
man 3 fgets
# 查看配置文件格式(第5类)
man 5 passwd
三、命令行参数处理
/**
* argc: 命令行参数个数
* argv: 命令行参数字符串数组
* 示例: ./a.out 1 2 3 4 5 6
* argc = 7 (程序名+6个参数)
*/
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("参数个数 argc = %d\n", argc);
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
四、文件打开模式
| 模式 | 说明 | 注意事项 |
|---|---|---|
"r" |
只读方式打开,位置在文件开头 | 文件必须存在 |
"r+" |
读写方式打开,位置在文件开头 | 文件必须存在 |
"w" |
只写方式打开,位置在文件开头 | 文件不存在则创建,存在则清空 |
"w+" |
读写方式打开,位置在文件开头 | 文件不存在则创建,存在则清空 |
"a" |
追加写方式打开,位置在文件末尾 | 文件不存在则创建 |
"a+" |
追加写/读方式打开,写时在末尾,读时在开头 | 文件不存在则创建 |
五、文件操作基本流程
#include <stdio.h>
int main()
{
// 1. 打开文件
FILE *fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("fopen failed");
return -1;
}
// 2. 读写操作
// ... 各种读写函数
// 3. 关闭文件
fclose(fp);
return 0;
}
六、标准I/O函数详解
1. 打开文件
FILE *fopen(const char *pathname, const char *mode);
/**
* pathname: 文件路径+文件名
* mode: 打开模式(见上表)
* 返回值: FILE结构指针,包含文件属性和读写位置
*/
2. 关闭文件
int fclose(FILE *stream);
/**
* stream: 文件流指针
* 注意: 必须调用fclose释放系统资源
*/
3. 字符读写函数
写入一个字符
int fputc(int c, FILE *stream);
/**
* c: 要写入的字符
* stream: 文件流指针
* 返回值: 成功返回写入的字符,失败返回EOF
*/
读取一个字符
int fgetc(FILE *stream);
/**
* stream: 文件流指针
* 返回值: 成功返回读取的字符,失败或文件结束返回EOF
*/
示例:文件复制(字符方式)
cpp
#include <stdio.h>
int copy_file_char(const char *src, const char *dest)
{
FILE *fp_src = fopen(src, "r");
if (!fp_src) return -1;
FILE *fp_dest = fopen(dest, "w");
if (!fp_dest) {
fclose(fp_src);
return -1;
}
int ch;
while ((ch = fgetc(fp_src)) != EOF) {
fputc(ch, fp_dest);
}
fclose(fp_src);
fclose(fp_dest);
return 0;
}
4. 字符串读写函数
写入字符串
int fputs(const char *s, FILE *stream);
/**
* s: 要写入的字符串
* stream: 文件流指针
* 返回值: 成功返回非负值,失败返回EOF
*/
读取字符串
char *fgets(char *s, int size, FILE *stream);
/**
* s: 字符数组缓冲区
* size: 最大读取字符数(包括结尾的\0)
* stream: 文件流指针
* 返回值: 成功返回s,失败或文件结束返回NULL
* 注意: 会保留换行符
*/
示例:逐行读取文件
cpp
#include <stdio.h>
#include <string.h>
int read_file_line_by_line(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (!fp) return -1;
char buffer[256];
int line_num = 0;
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
line_num++;
// 去掉换行符
buffer[strcspn(buffer, "\n")] = '\0';
printf("Line %d: %s\n", line_num, buffer);
}
fclose(fp);
return 0;
}
七、注意事项
-
错误处理:所有文件操作函数都可能失败,必须检查返回值
-
资源释放:fopen后必须对应调用fclose
-
缓冲区:标准I/O有缓冲区,fflush()可强制刷新
-
文件位置:读写操作会改变文件位置指针
-
二进制 vs 文本:Windows和Linux对文本文件处理不同(换行符)
八、常用命令
# 查看文件类型
ll # 显示文件类型标识
file filename # 查看文件详细信息
# 查看设备文件
ll /dev # 查看设备目录
# 编译运行
gcc -o program program.c # 编译
./program arg1 arg2 # 运行