在编程中,文件和目录操作是常见的任务。本文将详细讲解常用的文件操作函数和目录操作函数,包括其功能、参数、使用方法,并通过示例代码展示如何用这些函数实现常见的操作。
fopen()
函数功能:打开或创建文件。
参数:
const char *pathname
:文件名。
const char *mode
:文件操作模式。常见的模式有:
"r"
:只读模式,文件必须存在。
"w"
:只写模式,文件不存在则创建,存在则清空。
"a"
:追加模式,文件不存在则创建,存在则从末尾开始写入。
返回值:
成功返回一个 FILE *
类型的文件指针。
失败返回 NULL
,errno
会被设置。
示例代码:
#include
int main() {
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("fopen failed");
return -1;
}
fclose(fp);
return 0;
}
解释:
fopen("example.txt", "r")
:尝试以只读模式打开名为 "example.txt"
的文件。
如果文件不存在或无法打开,fopen
将返回 NULL
,程序通过 perror
输出错误信息。
最后调用 fclose(fp)
关闭文件。
fclose()
函数功能:关闭文件指针。
参数:
FILE *fp
:要关闭的文件指针。
返回值:
成功返回 0
。
失败返回 EOF
。
示例代码:
fclose(fp); // 关闭文件
解释:
fclose(fp)
:关闭文件指针 fp
,释放与文件相关的系统资源。
fgetc()
函数功能:从文件指针中读取一个字符。
参数:
FILE *fp
:文件指针。
返回值:
成功返回读取的字符。
失败或到达文件末尾返回 EOF
。
示例代码:
char c = fgetc(fp);
if (c == EOF) {
perror("fgetc failed");
return -1;
}
解释:
fgetc(fp)
:从文件指针 fp
中读取一个字符。
如果读取失败或到达文件末尾,返回值为 EOF
,程序通过 perror
输出错误信息。
fputc()
函数功能:向文件指针写入一个字符。
参数:
int c
:要写入的字符。
FILE *fp
:文件指针。
返回值:
成功返回写入的字符。
失败返回 EOF
。
示例代码:
int ret = fputc('A', fp);
if (ret == EOF) {
perror("fputc failed");
return -1;
}
解释:
fputc('A', fp)
:向文件指针 fp
写入字符 'A'
。
如果写入失败,返回值为 EOF
,程序通过 perror
输出错误信息。
fgets()
函数功能:从文件指针中读取一行数据。
参数:
char *str
:存储读取数据的字符串。
int n
:最大读取字符数。
FILE *fp
:文件指针。
返回值:
成功返回读取的字符串。
失败或到达文件末尾返回 NULL
。
示例代码:
char buffer[100];
char *line = fgets(buffer, sizeof(buffer), fp);
if (line == NULL) {
perror("fgets failed");
return -1;
}
解释:
fgets(buffer, sizeof(buffer), fp)
:从文件指针 fp
中读取一行数据到缓冲区 buffer
中。
如果读取失败或到达文件末尾,返回值为 NULL
,程序通过 perror
输出错误信息。
fputs()
函数功能:向文件指针写入一行数据。
参数:
const char *str
:要写入的字符串。
FILE *fp
:文件指针。
返回值:
成功返回非负值。
失败返回 EOF
。
示例代码:
int ret = fputs("Hello, World!\n", fp);
if (ret == EOF) {
perror("fputs failed");
return -1;
}
解释:
fputs("Hello, World!\n", fp)
:向文件指针 fp
写入字符串 "Hello, World!\n"
。
如果写入失败,返回值为 EOF
,程序通过 perror
输出错误信息。
fscanf()
和 fprintf()
函数功能:格式化输入输出。
fscanf()
从文件指针中读取格式化输入。
fprintf()
向文件指针写入格式化输出。
参数:
FILE *fp
:文件指针。
const char *format
:格式字符串。
返回值:
fscanf()
返回成功读取的输入项数。
fprintf()
返回写入的字符数。
示例代码:
int num;
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("fopen failed");
return -1;
}
fscanf(fp, "%d", &num);
fprintf(stdout, "Read number: %d\n", num);
fclose(fp);
解释:
fscanf(fp, "%d", &num)
:从文件指针 fp
中读取一个整数到变量 num
中。
fprintf(stdout, "Read number: %d\n", num)
:向标准输出写入格式化字符串,显示读取的整数。
rewind()
函数功能:将文件指针重置到文件开头。
参数:
FILE *fp
:文件指针。
示例代码:
rewind(fp); // 文件指针重置到文件开头
解释:
rewind(fp)
:将文件指针 fp
重置到文件开头,方便再次读取文件。
ftell()
函数功能:获取文件指针的当前位置。
参数:
FILE *fp
:文件指针。
返回值:
成功返回当前偏移量。
失败返回 -1
,errno
会被设置。
示例代码:
long offset = ftell(fp);
if (offset == -1) {
perror("ftell failed");
return -1;
}
解释:
ftell(fp)
:获取文件指针 fp
的当前位置,以文件开头为基准的字节数。
如果失败,返回值为 -1
,程序通过 perror
输出错误信息。
fseek()
函数功能:重新定位文件指针。
参数:
FILE *fp
:文件指针。
long offset
:偏移量。
int whence
:参考点(SEEK_SET
、SEEK_CUR
、SEEK_END
)。
返回值:
成功返回 0
。
失败返回非零值。
示例代码:
if (fseek(fp, 0, SEEK_END) != 0) {
perror("fseek failed");
return -1;
}
解释:
fseek(fp, 0, SEEK_END)
:将文件指针 fp
定位到文件末尾。
SEEK_END
表示参考点为文件末尾,offset
为 0
表示定位到文件末尾。
fdopen()
和 fileno()
函数功能:
fdopen()
:将文件描述符转换为文件指针。
fileno()
:将文件指针转换为文件描述符。
参数:
fdopen()
:
int fd
:文件描述符。
const char *mode
:打开模式。
fileno()
:
FILE *stream
:文件指针。
返回值:
fdopen()
返回文件指针。
fileno()
返回文件描述符。
示例代码:
#include
#include
int fd = open("example.txt", O_RDWR);
FILE *fp = fdopen(fd, "r+");
if (fp == NULL) {
perror("fdopen failed");
return -1;
}
int fdFromFP = fileno(fp);
解释:
fdopen(fd, "r+")
:将文件描述符 fd
转换为文件指针 fp
,打开模式为读写。
fileno(fp)
:将文件指针 fp
转换为文件描述符 fdFromFP
。
rename()
函数功能:重命名或移动文件。
参数:
const char *oldname
:旧文件名。
const char *newname
:新文件名。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
if (rename("oldfile.txt", "newfile.txt") != 0) {
perror("rename failed");
return -1;
}
解释:
rename("oldfile.txt", "newfile.txt")
:将文件 "oldfile.txt"
重命名为 "newfile.txt"
。
如果失败,返回值为 -1
,程序通过 perror
输出错误信息。
remove()
函数功能:删除文件。
参数:
const char *filename
:文件名。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
if (remove("file.txt") != 0) {
perror("remove failed");
return -1;
}
解释:
remove("file.txt")
:删除文件 "file.txt"
。
如果失败,返回值为 -1
,程序通过 perror
输出错误信息。
stat()
、fstat()
和 lstat()
函数功能:获取文件状态信息。
参数:
const char *pathname
:文件名。
struct stat *buf
:存储文件状态信息的结构体指针。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
#include
struct stat buf;
if (stat("example.txt", &buf) == 0) {
printf("File size: %ld bytes\n", buf.st_size);
} else {
perror("stat failed");
return -1;
}
解释:
stat("example.txt", &buf)
:获取文件 "example.txt"
的状态信息,并存储在结构体 buf
中。
buf.st_size
表示文件的大小(以字节为单位)。
flock()
和 fcntl()
函数功能:
flock()
:对文件进行加锁。
fcntl()
:对文件描述符进行操作(如加锁)。
参数:
int fd
:文件描述符。
int cmd
:操作命令。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
#include
#include
int fd = open("example.txt", O_RDWR);
if (fd < 0) {
perror("open failed");
return -1;
}
if (flock(fd, LOCK_EX) == 0) {
// 文件已加锁,可以进行操作
flock(fd, LOCK_UN); // 解锁
} else {
perror("flock failed");
return -1;
}
close(fd);
解释:
flock(fd, LOCK_EX)
:对文件描述符 fd
进行独占锁操作。
LOCK_EX
表示独占锁。
flock(fd, LOCK_UN)
:解锁文件。
opendir()
函数功能:打开目录。
参数:
const char *pathname
:目录名。
返回值:
成功返回 DIR *
指针。
失败返回 NULL
,errno
会被设置。
示例代码:
DIR *dir = opendir("/");
if (dir == NULL) {
perror("opendir failed");
return -1;
}
解释:
opendir("/")
:打开目录 /
。
如果失败,返回值为 NULL
,程序通过 perror
输出错误信息。
readdir()
函数功能:读取目录项。
参数:
DIR *dirp
:目录指针。
返回值:
成功返回 struct dirent *
指针。
失败或到达目录末尾返回 NULL
。
示例代码:
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("Found entry: %s\n", entry->d_name);
}
解释:
readdir(dir)
:读取目录 dir
中的条目,直到到达目录末尾。
entry->d_name
表示目录条目的名称。
closedir()
函数功能:关闭目录。
参数:
DIR *dirp
:目录指针。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
closedir(dir); // 关闭目录
解释:
closedir(dir)
:关闭目录指针 dir
,释放相关资源。
chdir()
函数功能:改变当前工作目录。
参数:
const char *path
:新的工作目录。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
if (chdir("/home/user/documents") != 0) {
perror("chdir failed");
return -1;
}
解释:
chdir("/home/user/documents")
:将当前工作目录更改为 /home/user/documents
。
如果失败,返回值为 -1
,程序通过 perror
输出错误信息。
getcwd()
函数功能:获取当前工作目录。
参数:
char *buf
:存储路径的缓冲区。
size_t size
:缓冲区大小。
返回值:
成功返回路径字符串。
失败返回 NULL
。
示例代码:
char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) == NULL) {
perror("getcwd failed");
return -1;
}
printf("Current working directory: %s\n", cwd);
解释:
getcwd(cwd, sizeof(cwd))
:获取当前工作目录,并存储在缓冲区 cwd
中。
如果失败,返回值为 NULL
,程序通过 perror
输出错误信息。
mkdir()
函数功能:创建目录。
参数:
const char *pathname
:目录名。
mode_t mode
:权限模式。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
if (mkdir("new_directory", 0755) != 0) {
perror("mkdir failed");
return -1;
}
解释:
mkdir("new_directory", 0755)
:以权限 0755
创建名为 "new_directory"
的目录。
如果失败,返回值为 -1
,程序通过 perror
输出错误信息。
rmdir()
函数功能:删除空目录。
参数:
const char *pathname
:目录名。
返回值:
成功返回 0
。
失败返回 -1
,errno
会被设置。
示例代码:
if (rmdir("empty_directory") != 0) {
perror("rmdir failed");
return -1;
}
解释:
rmdir("empty_directory")
:删除名为 "empty_directory"
的空目录。
如果失败,返回值为 -1
,程序通过 perror
输出错误信息。
以下是将使用 fread
和 fwrite
、fgetc
和 fputc
、fgets
和 fputs
、read
和 write
函数实现 cp
和 cat
操作的代码整合到博客中的内容:
fread
和 fwrite
实现 cp
和 cat
#include
void do_copy(FILE *src, FILE *dest) {
char buffer[1024];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), src)) > 0) {
fwrite(buffer, 1, bytes_read, dest);
}
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
FILE *src = fopen(argv[1], "rb");
if (!src) {
perror("Failed to open source file");
return 1;
}
FILE *dest = fopen(argv[2], "wb");
if (!dest) {
perror("Failed to open destination file");
fclose(src);
return 1;
}
do_copy(src, dest);
fclose(src);
fclose(dest);
return 0;
}
#include
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s [resume_offset]\n", argv[0]);
return 1;
}
FILE *src = fopen(argv[1], "rb");
if (!src) {
perror("Failed to open source file");
return 1;
}
FILE *dest = fopen(argv[2], "r+b");
if (!dest) {
dest = fopen(argv[2], "w+b");
if (!dest) {
perror("Failed to open destination file");
fclose(src);
return 1;
}
}
if (argc >= 4) {
long offset = strtol(argv[3], NULL, 10);
fseek(dest, offset, SEEK_SET);
}
char buffer[1024];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), src)) > 0) {
fwrite(buffer, 1, bytes_read, dest);
}
fclose(src);
fclose(dest);
return 0;
}
fgetc
和 fputc
实现 cp
和 cat
#include
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
FILE *src = fopen(argv[1], "r");
if (!src) {
perror("Failed to open source file");
return 1;
}
FILE *dest = fopen(argv[2], "w");
if (!dest) {
perror("Failed to open destination file");
fclose(src);
return 1;
}
int c;
while ((c = fgetc(src)) != EOF) {
fputc(c, dest);
}
fclose(src);
fclose(dest);
return 0;
}
fgets
和 fputs
实现 cp
和 cat
#include
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
FILE *src = fopen(argv[1], "r");
if (!src) {
perror("Failed to open source file");
return 1;
}
FILE *dest = fopen(argv[2], "w");
if (!dest) {
perror("Failed to open destination file");
fclose(src);
return 1;
}
char buffer[1024];
while (fgets(buffer, sizeof(buffer), src)) {
fputs(buffer, dest);
}
fclose(src);
fclose(dest);
return 0;
}
read
和 write
实现 cp
和 cat
#include
#include
#include
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
int src_fd = open(argv[1], O_RDONLY);
if (src_fd == -1) {
perror("Failed to open source file");
return 1;
}
int dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (dest_fd == -1) {
perror("Failed to open destination file");
close(src_fd);
return 1;
}
char buffer[1024];
ssize_t bytes_read;
while ((bytes_read = read(src_fd, buffer, sizeof(buffer))) > 0) {
write(dest_fd, buffer, bytes_read);
}
close(src_fd);
close(dest_fd);
return 0;
}
#include
#include
#include
#include
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s [resume_offset]\n", argv[0]);
return 1;
}
int src_fd = open(argv[1], O_RDONLY);
if (src_fd == -1) {
perror("Failed to open source file");
return 1;
}
int dest_fd = open(argv[2], O_WRONLY | O_CREAT, 0666);
if (dest_fd == -1) {
perror("Failed to open destination file");
close(src_fd);
return 1;
}
off_t offset = 0;
if (argc >= 4) {
offset = strtol(argv[3], NULL, 10);
if (lseek(dest_fd, offset, SEEK_SET) == -1) {
perror("Failed to seek destination file");
close(src_fd);
close(dest_fd);
return 1;
}
}
char buffer[1024];
ssize_t bytes_read;
while ((bytes_read = read(src_fd, buffer, sizeof(buffer))) > 0) {
if (write(dest_fd, buffer, bytes_read) != bytes_read) {
perror("Failed to write to destination file");
close(src_fd);
close(dest_fd);
return 1;
}
}
close(src_fd);
close(dest_fd);
return 0;
}
以上代码分别使用了不同的文件操作函数实现 cp
和 cat
操作,每种方法都有其适用场景和特点。你可以根据具体需求选择合适的函数组合。