基于缓冲区:
- 数据在读取或写入时首先存储在内存缓冲区中,而不是直接访问磁盘。
- 读取和写入操作可以在内存中进行,减少了对磁盘的频繁访问,提高了读写效率。
- 缓冲区可以减少磁盘I/O操作的次数,从而提高性能和响应速度。
基于非缓冲区:
- 数据直接从磁盘读取或写入,没有经过内存缓冲区。
- 每次读取或写入都需要直接访问磁盘,可能导致频繁的磁盘I/O操作,影响性能。
- 适用于对实时性要求高的场景,如实时数据处理等。
综上所述,基于缓冲区的文件访问通常比基于非缓冲区的文件访问具有更好的性能和效率。
基于缓冲区的文件操作
打开文件:首先打开要操作的文件,获取文件描述符或文件指针。
创建缓冲区:为读取或写入文件数据创建一个缓冲区,通常是一个内存块。
读取文件:
- 从文件中读取数据到缓冲区中,而不是直接从磁盘读取。
- 可以使用标准库函数如fread()或fgets()来读取文件数据到缓冲区。
处理数据:对缓冲区中的数据进行处理,如解析、修改等操作。
写入文件:
- 将处理后的数据从缓冲区写入文件,而不是直接写入磁盘。
- 可以使用标准库函数如fwrite()或fprintf()将数据写入文件。
刷新缓冲区:在完成数据写入后,需要刷新缓冲区以确保数据被写入文件而不是仅停留在缓冲区中。可以使用fflush()函数来刷新缓冲区。
关闭文件:最后关闭文件,释放资源并关闭文件描述符或文件指针。
基于非缓冲区的文件操作:
打开文件(open):首先打开要操作的文件,获取文件描述符或文件指针。
直接读取文件(read):
-
- 从磁盘直接读取文件数据,而不是先存储到内存缓冲区。
- 读取的数据可以直接处理,而无需在内存中缓存。
处理数据:对直接读取的数据进行处理,如解析、修改等操作。
直接写入文件(write):
-
- 将处理后的数据直接写入文件,而不是先存储到内存缓冲区。
- 数据直接写入磁盘,而非先写入内存。
刷新文件:在完成数据写入后,可能需要调用类似fsync()函数来确保数据被写入磁盘而不是仅停留在缓存中。
关闭文件(close):最后关闭文件,释放资源并关闭文件描述符或文件指针。
基于非缓冲区的文件操作适用于对实时性要求高、数据量较大且无需缓存的场景。这种操作方式可以减少内存的占用,但可能会导致频繁的磁盘I/O操作,影响性能。在实现时需要注意数据的一致性和可靠性,以确保数据正确地写入和读取。
例程
//定义结构体,两个成员,一个账号,一个密码
//1.c先设置账号密码;
//2.c读取1.c写入的结构体
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct STU
{
int account;
char password[10];
};
struct STU data = {123,"123"}; //初始化赋值
int main()
{ char key[10];
for(int i=1;;i<=3;i++)
{
printf("请输入密码:");
scanf("%s",key);
if(strcmp(data.password,key)==0) //strcmp 字符串比较
{
printf("密码输入正确\n");
int fd1 = open("1.txt",O_RDWR | O_CREAT | O_TRUNC,0664); //打开1.txt文件
//函数原型:int open(const char *pathname, int flags, mode_t mode);
//pathname -- 文件的路径
/*
flags:下面的宏定义必须选择一个
O_RDONLY -- 只读
O_WRONLY -- 只写
O_RDWR -- 读写
下面的宏可选:
O_CREAT -- 文件不存在,创建,存在,不起作用
O_TRUNC -- 清空写
O_APPEND -- 追加写
O_EXCL,要和O_CREAT,如果文件不存在,创建文件并打开,存在,直接返回失败;
*/
if(fd1 == -1)
{
perror("open fd1 error");
return -1;
}
write(fd1,&data,sizeof(struct STU));
close(fd1);
break;
}
else if(i != 3)
{
printf("密码输入错误,还有%d 次机会\n",3-i);
}
}
if(i>3)
{
printf("机会已用完\n");
}
return 0;
}
读取结构体里面的内容
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct STU
{
int account;
char password[10];
};
int main()
{
struct STU data1;
int fd2 = open("1.txt",O_RDONLY);
if(fd2 == -1)
{
perror("open fd1 error");
return -1;
}
read(fd2,&data1,sizeof(struct STU));
printf("account = %d\n",data1.account);
printf("password = %s\n",data1.password);
close(fd2);
return 0;
}
//实现一个cp的功能 (非缓冲区的文件操作):
/*******************************************
打开文件 -- open
open(const char *pathname, int flags);
open(const char *pathname, int flags, mode_t mode);
形参:
pathname -- 文件的路径
flags:下面的宏定义必须选择一个
O_RDONLY -- 只读
O_WRONLY -- 只写
O_RDWR -- 读写
下面的宏可选:
O_CREAT -- 文件不存在,创建,存在,不起作用
O_TRUNC -- 清空写
O_APPEND -- 追加写
mode:如果flag里面用了O_CREAT,此时需要提供第三个参数,第三个参数就是文件的权限;
关闭:close
close(int fd);
形参:open的返回值
写 -- write
write(int fd, const void *buf, size_t count);
形参:fd -- open的返回值
buf:要写入的内容的首地址
count:写入的字节数
返回值:成功真正写入的字节数
读 -- read
read(int fd, void *buf, size_t count);
形参:fd -- open的返回值
buf:读取之后要保存的位置的首地址
count:读取的字节数
返回值:成功真正读取到的字节数(读到文件末尾,返回0)
lseek
lseek(int fd, off_t offset,int whence);
形参:fp:open的返回值
offset:偏移量(+往文件末尾方向偏移,-往文件开头偏移)
whence:SEEK_SET 0
SEEK_CUR 1
SEEK_END 2
返回值:先做后面的光标偏移,返回光标偏移之后的位置到文件开头的偏移量;
********************************************/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fcntl.h"
#include "unistd.h"
#include "pthread.h"
int main(int argc, char *argv[])
{
int n = 0;
char buf[1024];
int fd1 = open(argv[1],O_RDONLY,0644);
int fd2 = open(argv[2],O_RDWR | O_CREAT | O_TRUNC,0644);
while(n = read(fd1,buf,1024))
{
write(fd2,buf,n);
}
n = lseek(fd2,0,SEEK_END);
printf("%d\n",n);
close(fd1);
close(fd2);
return 0;
}