Linux 文件操作:系统调用与标准库函数接口汇总及代码示例
1. 文件操作的系统调用和库函数各个接口
1.1 C 语言文件操作常用接口
| 函数名 | 功能 | 头文件 | 参数说明 |
|---|
fopen | 打开文件 | stdio.h | FILE* fopen(const char* filename, const char* mode) |
fclose | 关闭文件 | stdio.h | int fclose(FILE* stream) |
fputc | 写入一个字符 | stdio.h | int fputc(int char, FILE* stream) |
fgetc | 读取一个字符 | stdio.h | int fgetc(FILE* stream) |
fputs | 写入一个字符串 | stdio.h | int fputs(const char* str, FILE* stream) |
fgets | 读取一个字符串 | stdio.h | char* fgets(char* str, int n, FILE* stream) |
fprintf | 格式化写入数据 | stdio.h | int fprintf(FILE* stream, const char* format, ...) |
fscanf | 格式化读取数据 | stdio.h | int fscanf(FILE* stream, const char* format, ...) |
fwrite | 向二进制文件写入数据 | stdio.h | size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) |
fread | 从二进制文件读取数据 | stdio.h | size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) |
fseek | 设置文件指针的位置 | stdio.h | int fseek(FILE* stream, long int offset, int whence) |
ftell | 计算当前文件指针相对于起始位置的偏移量 | stdio.h | long int ftell(FILE* stream) |
rewind | 设置文件指针到文件的起始位置 | stdio.h | void rewind(FILE* stream) |
ferror | 判断文件操作过程中是否发生错误 | stdio.h | int ferror(FILE* stream) |
feof | 判断文件指针是否读取到文件末尾 | stdio.h | int feof(FILE* stream) |
1.2 系统调用和库函数汇总
1.2.1 系统调用
| 系统调用 | 函数功能 | 头文件 | 参数模板 | 返回值 |
|---|
| open() | 打开或创建文件 | <fcntl.h> | int open(const char *pathname, int flags, mode_t mode); | 文件描述符 (成功)/-1(失败) |
| creat() | 创建新文件 | <fcntl.h> | int creat(const char *pathname, mode_t mode); | 文件描述符 (成功)/-1(失败) |
| close() | 关闭文件描述符 | <unistd.h> | int close(int fd); | 0(成功)/-1(失败) |
| read() | 从文件描述符读取数据 | <unistd.h> | ssize_t read(int fd, void *buf, size_t count); | 读取字节数/-1(失败) |
| write() | 向文件描述符写入数据 | <unistd.h> | ssize_t write(int fd, const void *buf, size_t count); | 写入字节数/-1(失败) |
| lseek() | 移动文件读写指针 | <unistd.h> | off_t lseek(int fd, off_t offset, int whence); | 新偏移量/-1(失败) |
| pread() | 从指定偏移处读取 | <unistd.h> | ssize_t pread(int fd, void *buf, size_t count, off_t offset); | 读取字节数/-1(失败) |
| pwrite() | 向指定偏移处写入 | <unistd.h> | ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); | 写入字节数/-1(失败) |
| fsync() | 将文件数据同步到磁盘 | <unistd.h> | int fsync(int fd); | 0(成功)/-1(失败) |
| fdatasync() | 同步文件数据(不包括元数据) | <unistd.h> | int fdatasync(int fd); | 0(成功)/-1(失败) |
| ftruncate() | 截断/扩展文件大小 | <unistd.h> | int ftruncate(int fd, off_t length); | 0(成功)/-1(失败) |
| dup() | 复制文件描述符 | <unistd.h> | int dup(int oldfd); | 新文件描述符/-1(失败) |
| dup2() | 复制文件描述符到指定值 | <unistd.h> | |
1.2.2 C 语言标准库文件 IO 函数
| 库函数 | 函数功能 | 头文件 | 参数模板 | 返回值 |
|---|
| fopen() | 打开文件流 | <stdio.h> | FILE *fopen(const char *path, const char *mode); | 文件指针/NULL |
| freopen() | 重新打开文件流 | <stdio.h> | FILE *freopen(const char *path, const char *mode, FILE *stream); | 文件指针/NULL |
| fclose() | 关闭文件流 | <stdio.h> | int fclose(FILE *stream); | 0(成功)/EOF |
| fread() | 从文件流读取数据 | <stdio.h> | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); | 读取元素数 |
| fwrite() | 向文件流写入数据 | <stdio.h> | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); | 写入元素数 |
| fgetc() | 从文件流读取字符 | <stdio.h> | int fgetc(FILE *stream); | 字符/EOF |
| getc() | 从文件流读取字符 | <stdio.h> | int getc(FILE *stream); | 字符/EOF |
| getchar() | 从标准输入读取字符 | <stdio.h> | int getchar(void); | 字符/EOF |
| fputc() | 向文件流写入字符 | <stdio.h> | int fputc(int c, FILE *stream); | 字符/EOF |
| putc() | 向文件流写入字符 | <stdio.h> | int putc(int c, FILE *stream); | 字符/EOF |
| putchar() | 向标准输出写入字符 | <stdio.h> | int putchar(int c); | 字符/EOF |
| fgets() | 从文件流读取字符串 | <stdio.h> | char *fgets(char *s, int size, FILE *stream); | 字符串指针/NULL |
| fputs() | 向文件流写入字符串 | <stdio.h> | int fputs(const char *s, FILE *stream); | 非负数/EOF |
| fseek() |
2. 文件 IO 部分代码演示
2.1 文件操作 1:打开文件方式
Makefile
myfile:myfile.c
gcc -o $@ $^
.PHONY:clean
clean: rm -f myfile
myfile.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
umask(0);
int fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);
if(fd < 0){
perror("open");
return 1;
}
const char* message = "ccc";
write(fd, message, strlen(message));
close(fd);
return 0;
}
2.2 文件操作 2:重定向
Makefile
myfile:myfile.c
gcc -o $@ $^
.PHONY:clean
clean: rm -f myfile
myfile.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
FILE *fp = fopen("log.txt","w");
fprintf(stdout,"hello stdout\n");
close(1);
int fda = open("loga.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);
int fdb = open("logb.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);
int fdc = open("logc.txt",O_CREAT | O_WRONLY | O_TRUNC,0666);
fprintf(stdout,"fda : %d\n",fda);
fprintf(stdout,"fdb : %d\n",fdb);
(,,fdc);
close(fda);
close(fdb);
close(fdc);
;
}
loga.txt
fda :1 fdb :4 fdc :5
2.3 文件操作 3:理解缓冲区
Print.c
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
int main(){
printf("hell world");
sleep(40);
return 0;
}
2.4 文件操作 4:实现 stdio
Makefile
testlibc:main.c my_stdio.c
gcc -o $@ $^
.PHONY:clean
clean: rm -f testlibc
main.c
#include"my_stdio.h"
#include<string.h>
#include<unistd.h>
int main(){
My_FILE *fp = Myfopen("log.txt","a");
if(!fp)
return 1;
int cnt = 10;
const char* msg = "hello world ";
while(cnt--){
Myfwrite(msg,1,strlen(msg),fp);
Myfflush(fp);
sleep(2);
}
Myfclose(fp);
return 0;
}
my_stdio.h
#pragma once
typedef struct{
int fd;
int flags;
int mode;
char outbuffer[1024];
int cap;
int size;
} My_FILE;
#define NONE_CACHE 1
#define LINE_CACHE 2
#define FULL_CACHE 4
My_FILE *Myfopen(const char* pathname,const char* mode);
int Myfwrite(const char* message,int size,int num,My_FILE *fp);
void Myfflush(My_FILE *fp);
void Myfclose(My_FILE *fp);
my_stdio.c
#include"my_stdio.h"
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
static mode_t global_mode = 0666;
My_FILE *Myfopen(const char* pathname,const char* mode){
if(pathname == NULL || mode == NULL)
return NULL;
umask(0);
int fd = 0;
int flags = 0;
if(strcmp(mode,"w")==0){
flags = O_CREAT | O_WRONLY | O_TRUNC;
fd = open(pathname,flags,global_mode);
}
if(strcmp(mode,"r")==0){
flags = O_RDONLY;
fd = open(pathname,flags);
}
if(strcmp(mode,"a")==0){
flags = O_CREAT | O_WRONLY | O_APPEND;
fd = open(pathname,flags,global_mode);
}
(fd < )
;
My_FILE* fp = (My_FILE*)((My_FILE));
(!fp)
;
fp->fd = fd;
fp->flags = flags;
fp->mode = LINE_CACHE;
fp->cap = ;
fp->size = ;
(fp->outbuffer,,(fp->outbuffer));
fp;
}
{
(message == || fp == )
;
total = size * num;
(total + fp->size > fp->cap )
;
(fp->outbuffer + fp->size,message,total);
fp->size += total;
fp->outbuffer[fp->size]=;
(fp->outbuffer[fp->size ]== && (fp->mode & LINE_CACHE))
Myfflush(fp);
num;
}
{
(!fp)
;
(fp->size >)
{
write(fp->fd,fp->outbuffer,fp->size);
fp->size = ;
fsync(fp->fd);
}
}
{
(!fp)
;
Myfflush(fp);
close(fp->fd);
}