此文章为本人学习笔记,若有错误求指正,自学推荐书籍《Linux/UNIX系统编程手册》,需要该书籍pdf文档可无偿分享。
文件概述
在UNIX/Linux系统中,一切皆为文件。这不仅包括普通文件和文件夹,还包括设备、进程、网络连接等。所有文件在系统中都是通过文件描述符来标识和操作的。
文件分类
- 文本文件:可以直接阅读和编辑的文件,如源代码文件(.c、.cpp)、文本文件(.txt)、HTML文件(.html)等。这些文件包含字符数据,并且通常使用换行符和文件结束标识符来组织内容。
- 二进制文件:包含非文本数据的文件,如可执行文件、目标文件、图片、音频、视频等。这些文件以二进制形式存储数据,更加紧凑,但不易于人类阅读。
示例比较
数据:65536
- 字符串方式:"65536\0"(文本文件,占用6 bytes)
- 整型方式:65536(整数,二进制文件,占用4 bytes)
文件描述符
文件描述符是一个非负整数,用于标识已打开的文件。在每个进程的上下文中,文件描述符是唯一的。文件描述符表维护着所有打开文件的状态和相关信息。
查看文件类型
使用file命令可以查看文件的类型。例如:
file example.txt
低级文件操作
低级文件操作直接使用系统调用,提供对文件的基本操作功能。这些操作依赖文件描述符。
主要函数
- open:打开文件
- close:关闭文件
- read:读取文件内容
- write:写入文件内容
示例代码
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[100];
ssize_t bytesRead = read(fd, buffer, sizeof(buffer));
if (bytesRead == -1) {
perror("read");
close(fd);
return 1;
}
// 打印读取的数据
write(STDOUT_FILENO, buffer, bytesRead);
close(fd);
return 0;
}
文件模式
open函数的常用文件模式包括
- O_RDONLY:只读模式
- O_WRONLY:只写模式
- O_RDWR:读写模式
- O_CREAT:如果文件不存在则创建文件
- O_TRUNC:如果文件存在则将文件长度截断为0
- O_APPEND:每次写入时都会追加到文件末尾
高级文件操作
高级文件操作使用标准I/O库(<stdio.h>),提供了更高层次的抽象,使文件操作更加方便和直观。
主要函数
- fopen:打开文件
- fclose:关闭文件
- fread:从文件读取数据
- fwrite:向文件写入数据
- fseek:移动文件指针
- ftell:获取文件指针当前位置
- fflush:刷新文件缓冲区
示例代码
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("fopen");
return 1;
}
char buffer[100];
size_t bytesRead = fread(buffer, 1, sizeof(buffer), file);
if (bytesRead < sizeof(buffer) && ferror(file)) {
perror("fread");
fclose(file);
return 1;
}
// 打印读取的数据
fwrite(buffer, 1, bytesRead, stdout);
fclose(file);
return 0;
}
文件访问模式
fopen函数的常用文件访问模式包括:
- "r":只读模式
- "w":写模式(如果文件存在则截断文件)
- "a":追加模式(数据写入文件末尾)
- "r+":读写模式(文件必须存在)
- "w+":读写模式(如果文件存在则截断文件)
- "a+":读写模式(数据追加到文件末尾)
文件指针操作
在文件操作中,文件指针用于标识当前读取或写入的位置。以下是一些常用的文件指针操作函数:
lseek函数
用于在文件中移动文件指针位置。
#include <fcntl.h>
#include <unistd.h>
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
// 移动文件指针到文件末尾
off_t fileSize = lseek(fd, 0, SEEK_END);
if (fileSize == -1) {
perror("lseek");
close(fd);
return 1;
}
printf("文件大小: %ld bytes\n", fileSize);
close(fd);
fseek和ftell函数
用于在高级文件操作中移动和获取文件指针位置。
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("fopen");
return 1;
}
// 移动文件指针到文件末尾
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
if (fileSize == -1) {
perror("ftell");
fclose(file);
return 1;
}
printf("文件大小: %ld bytes\n", fileSize);
fclose(file);
return 0;
}
常见错误处理
文件操作中常见的错误包括文件无法打开、读写错误等。可以使用perror函数或strerror函数来输出错误信息。
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("fopen");
fprintf(stderr, "Error opening file: %s\n", strerror(errno));
return 1;
}
// 进行文件操作
fclose(file);
return 0;
}
总结
文件操作是C语言编程中的基础知识,通过掌握低级和高级文件操作函数,可以灵活地处理各种类型的文件。对于复杂的文件操作,可以结合使用文件指针操作函数,如lseek
、fseek
和ftell
。同时,注意处理文件操作中的错误,确保程序的健壮性。