在C语言中,标准I/O库对文件流提供了三种缓冲方式,分别是行缓冲、全缓冲和无缓冲。它们的区别主要在于数据何时从缓冲区写入目标设备或从目标设备读取到缓冲区。
行缓冲(1K):在行缓冲模式下,数据会在遇到换行符(\n
)时刷新;行缓存区(大于1024)满刷新;程序正常结束刷新;调用fflush强制刷新 fflush(stdout)。主要用于人机交互。
#include <stdio.h>
#include <unistd.h>
int main(void){FILE *fb = fopen("1.txt","w");if(NULL == fb){printf("open error!\n");return -1;}//不会打印到终端、行缓冲条件都不满足printf("hello");while(1)sleep(1);//延时1s//'\n'条件可以打印到终端printf("hello\n");while(1)sleep(1);//超过行缓冲的最大值,可打印一行的数据,但是剩下的又会留在行缓冲区中for(int i=0;i<1025;i++)putchar('a');while(1)sleep(1);//程序正常结束printf("hello");//fflush强制刷新printf("hello");fflush(stdout);while(1)sleep(1);
close(fb);
return 0;
}
全缓冲(4k):缓存区(大于4096)满刷新缓存区 主要用于文件的读写;程序正常结束刷新;fflush强制刷新 fflush(fp)。
#include <stdio.h>
#include <unistd.h>
int main(void){FILE *fb = fopen("1.txt","w");if(NULL == fb){printf("open error!\n");return -1;}
//1全缓冲没满char buf[]="hello";fputs(buf,fb);while(1)sleep(1);
//2全缓冲满for(int i=0;i<4097;i++)fputc('a',fb);while(1)sleep(1);
// 程序正常结束fputs("hello",fb);fclose(fb);//强制刷新fputs("hello",fb);fflush(fb);while(1)sleep(1);
close(fb);
return 0;
}
无缓冲(0k):主要用于出错处理信息的输出 stderr ,不对数据缓存直接刷新。用于 界面交互,出错处理。
fprintf(strerr,"fopen error %s",filename);
fputs("error\n",stderr);
1.int fseek(FILE *stream, long offset, int whence)
whence 偏移的起始位置,由系统定义的三个宏开始。
SEEK_SET 文件的开头位置
SEEK_CUR 文件的当前位置
SEEK_END 文件的末尾位置
stream:要移动文件指针的目标文件流对象。注意:不支持设备文件,一般用于普通文件。
offset:要在文件内偏移的距离,单位字节。如果值为整数,则向文件末尾偏移;如果值为负数,则向文件开头偏移。
功能:将stream流文件中的文件指针从whence位置开始。偏移offset字节的长度。 成功: 返回 0、失败: -1。
注意:如果从文件的指定位置向后偏移过程中已经超过了文件的当前末尾位置,则会自动以'\0'来填充文件内容,从而形成一种被称为"空洞文件" 的特殊文件。
2.rewind函数 void rewind(FILE *stream)
功能:rewind相当于调用 fseek(stream, 0, SEEK_SET),它将文件指针移动到文件的开始位置。同时,它还会清除文件流的错误标志(通过 ferror可以检查)和文件结束标志(通过feof可以检查)。用于将文件指针重置到文件的开头,并清除文件流的错误和结束标志
3.ftell函数 long ftell(FILE *stream)
作用:ftell 函数返回当前文件指针的位置(以字节为单位),即开始位置到当前位置的字节数目。
返回值:成功时,ftell返回当前文件指针相对于文件开头的偏移量(字节数)。如果发生错误,ftell返回 -1L,并设置 errno来指示错误类型。
功能:ftell用于获取当前文件指针在文件中的位置,通常用于之后的fseek操作,以便能够恢复到当前的文件位置。用于获取当前文件指针的位置,以字节为单位,方便在后续的文件操作中使用。
#include <stdio.h>
int main(void){FILE *fb = fopen("1.txt","r");if( NULL == fb){printf("open error!\n");return -1;}int ret = fseek(fb,0,SEEK_END); long size = ftell(fb);//统计begin-end字节数rewind(fb);//回到开始位置if(EOF == ret){printf("fseek error!\n");return -1;}char buf[512] = {};fgets(buf,sizeof(buf),fb);//读取一行printf("%s\n",buf);printf("size:%ld\n",size);fclose(fb);return 0;
}
二、文件I\O
系统调用(System Calls)是操作系统为用户程序提供的一组接口,允许用户程序请求操作系统执行一些特定的服务。这些服务通常涉及到底层硬件资源的管理,比如文件操作、内存管理、进程控制、网络通信等。文件I/O系统调用是其中一类,专门用于对文件进行输入输出操作。
· 文件I/O系统调用: 文件I/O系统调用是操作系统提供的一组函数,允许用户程序与文件系统进行交互,包括创建文件、打开文件、读取文件内容、写入文件内容、关闭文件等操作。这些操作通常是通过对文件描述符的操作实现的。 特性:
1 、没有缓存区
2 、操作对象不在是流,而是文件描述符 FILE* int 0-1023
3、文件描述符,很小的非负的整数 int (0-1023)内核每打开一个文件就会获得一个文件 描述符
4、 每个程序在启动的时候操作系统默认为其打开,三个描述符与流对象匹配:
0 ==>STDIN_FILENO === stdin//标准输入
1 ==>STDOUT_FILENO == stdout//标准输出
2 ==>STDERR_FILENO == stderr//标准错误输出
stdin,stdout,stderr,===>FILE*
以下是常见的文件I/O系统调用及其功能:
1.open()函数
打开一个文件或创建一个新文件,并返回一个文件描述符(一个整数,用于标识打开的文件)。成功返回文件描述符,失败返回-1。
int fd = open(const char *pathname, int flags, mode_t mode);
pathname: 文件路径。
flags: 文件打开模式,如只读(O_RDONLY)、只写(O_WRONLY)、读写(O_RDWR)、创建文件(O_CREAT)等。前面3个后面可以加下面参数通过'|'加
O_CREAT,:创建文件
O_EXCL:需要和O_CREAT同时使用,表示新建的文件不能存在,成功,否则open就会失败
O_NOCTTY:不是终端设备
O_TRUNC:文件内容清空
O_APPEND:追加
O_ASYNC:异步io,什么时候io不确定,
O_NONBLOCK:非阻塞
mode: 新文件的权限(仅在使用 O_CREAT时有效)。
2.read()函数 ssize_t read(int fd, void *buf, size_t count);
功能: 从一个已打开的文件中读取数据。 返回值: 读取的字节数;如果读取到文件末尾,则返回0;如果出错,则返回-1。
ssize_t write(int fd, const void *buf, size_t count);
参数:
fd 文件描述符。
buf: 存储读取数据的缓冲区。
count: 读取的字节数。
3. write()函数 ssize_t write(int fd, const void *buf, size_t count);
功能: 向一个已打开的文件中写入数据。返回值: 实际写入的字节数;如果出错,则返回-1。
ssize_t write(int fd, const void *buf, size_t count);
参数:
fd: 文件描述符。
buf: 包含要写入数据的缓冲区。
count: 要写入的字节数。
4. lseek()函数 off_t lseek(int fd, off_t offset, int whence);
off_t lseek(int fd, off_t offset, int whence);
功能: 移动文件指针到文件中的某个位置,常用于在文件中随机访问数据。
off_t lseek(int fd, off_t offset, int whence);
参数:
d: 文件描述符。
offset: 相对于 whence的偏移量。
whence: 基准位置,如文件开始(SEEK_SET)、当前位置(SEEK_CUR)、文件末尾(SEEK_END)。
5.close()函数 int close(int fd);
功能: 关闭一个已打开的文件描述符,释放与该文件相关的资源。 返回值: 成功时返回0;如果出错,则返回-1。
参数:
fd: 文件描述符。
根据这些函数可以实现一个文件数据插入到另一个文件中去
//实现文件插入功能
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
void insertFile(char *str1,char *str2,int seat){int fd = open(str1,O_RDONLY);int fd1 = open(str2,O_RDWR);if(-1 == fd || -1 == fd1){printf("open error\n");return ;}long len = 0;char *p = (char*)malloc(sizeof(char)*1024);len= read(fd1,p,1024);lseek(fd1,SEEK_SET,0);write(fd1,p,seat);while(1){char buf[100]={};long ret = read(fd,buf,sizeof(buf));if(0 >= ret )break;write(fd1,buf,ret);//读压缩包不能多不能少,所以不能要sizeof(buf)} }write(fd1,p+seat,len-seat);free(p);close(fd);close(fd1);
}
int main(int argc,char *argv[]){int n = atoi(argv[3]);insertFile(argv[1],argv[2],n);return 0;
}