Linux文件编程

一、文件编程

1、打开/创建文档 2、编辑文档 3、保存文档 4、关闭文档

应用

打开 open
读写 write/read
光标定位 lseek
关闭 close

打开/创建文件

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>

//API
int open(const char *pathname,int flags);
int open(const char *pathename,int flags,mode_t mode);

int creat(const char *pathname,mode_t mode);


pathname:要打开的文件名(含路径,缺省为当问文字路径)
Flags:
O_RDONLY 只读打开 O_WRONLY只写打开 O_RDWR 可读可写打开

在Linux命令行写touch file1,生成一个文件。
在Linux命令行写man 2 open,打开需要包含的头文件。

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>

int main()
{	
	int fd;
	
	fd = open('./file1',O_RDWR );

	printf("fd = %d\n",fd);

	return 0;
}

成功返回3,失败返回-1。

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>

int main()
{	
	int fd;
	
	fd = open('./file1',O_RDWR);
	if(fd == -1){
		printf("open file1 failed\n ");
		fd = open('./file1',O_RDWR|O_CREAT,0600);//没有file1文件,O_CREAT创建这个文件
		if(fd > 0){
			printf("open file1 succeed\n"); 
		}
	}
	return 0;
}

在Linux命令行中rm file1,删除file1
输出结果open file1 failed,然后open file1 succeed

1、可读 R 4
2、可写 W 2
3、执行 X 1

读/写操作

写入文件

#include <unistd.h>

ssize_t write(int fd,vost void buf,size_t count);

fd是文件,buf是缓冲区,count是多少个字节大小
将fd文件,将buf缓冲区写入fd文件,有多少个,count大小。

在Linux命令行中写vi file1 创造一个文件
在Linux命令行中写cat file1
在Linux命令行中写man 2 open
在Linux命令行中写man strlen

#include <unistd.h>

in close(int fd);
#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR);
	if(fd == -1){
		printf("open file1 failed\n ");
		fd = open('./file1',O_RDWR|O_CREAT);//没有file1文件,O_CREAT创建这个文件
		if(fd > 0){
			printf("open file1 succeed\n"); 
		}
	}
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	write("fd,buf,strlen(buf)");
	close(fd);
	return 0;
}

fd文件成功输出大于0,失败输出-1。
在file文件写入sudu。

读取文件

man 2 read
man creat//查看creat的库

#include <unistd.h>

ssize_t read(int fd,void *buf,size_t count);

将fd文件读取多少个count数量放到buf去读
错误放回-1。

man malloc.

#include <stdilb.h>

void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t nmeb,size_t size);
void *raalloc(void *ptr,size_t size);
#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR);
	if(fd == -1){
		printf("open file1 failed\n ");
		fd = open('./file1',O_RDWR|O_CREAT);//没有file1文件,O_CREAT创建这个文件
		if(fd > 0){
			printf("open file1 succeed\n"); 
		}
	}
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	int n_write = write("fd,buf,strlen(buf)");
	if(n_write != -1){
		printf("write %d byte to file1\n",n_write);
	}
	char *readBuf;
	readBuf= (char *)malloc(sizeof(char *)n_write + 1);//强制(char *)

	//ssize_t read(int fd,void *buf,size_t count);
	int n_read = read(fd,readBuf,n_write);
	printf("read %d ,context: %s\n",n_read,readBuf);
	close(fd);
	return 0;
}

在Linux命令行输入rm file1 //删除file1文件
输出结果时
open file1 failed
open suscess:fd = 3
write 4 byte to file1
read 0 ,context :
为什么会错误呢,因为读文件是从光标开始,而刚开始写入的时候光标在后面,所以读文件为0。
解决方法

  1. 先关闭文件,在打开文件。
  2. 将光标移到最前面。
    下面是第一种方法:先关闭文件,在打开文件。
#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR);
	if(fd == -1){
		printf("open file1 failed\n ");
		fd = open('./file1',O_RDWR|O_CREAT);//没有file1文件,O_CREAT创建这个文件
		if(fd > 0){
			printf("open file1 succeed\n"); 
		}
	}
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	int n_write = write("fd,buf,strlen(buf)");
	if(n_write != -1){
		printf("write %d byte to file1\n",n_write);
	}

	close(fd);//关闭文件放这里

	char *readBuf;
	readBuf= (char *)malloc(sizeof(char *)n_write + 1);//强制(char *)

	//ssize_t read(int fd,void *buf,size_t count);
	int n_read = read(fd,readBuf,n_write);
	printf("read %d ,context: %s\n",n_read,readBuf);
	close(fd);
	return 0;
}

输出结果
open file1 failed
open suscess:fd = 3
write 4 byte to file1
read 4 ,context :sudu

第二种方法 将光标移到最前面(lseek)
在Linux命令行输入

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd,off_t offset,int whence);

fd 文件,offset偏移值,whence固定点的值。
SEEK_SET指向文件的头,
SEEK_GND指向文件的尾巴
SEEK_END指向当前文件的光标

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR);
	if(fd == -1){
		printf("open file1 failed\n ");
		fd = open('./file1',O_RDWR|O_CREAT);//没有file1文件,O_CREAT创建这个文件
		if(fd > 0){
			printf("open file1 succeed\n"); 
		}
	}
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	int n_write = write("fd,buf,strlen(buf)");
	if(n_write != -1){
		printf("write %d byte to file1\n",n_write);
	}

	// 这个是之前的解决方法  close(fd);//关闭文件放这里

	lseek(fd,-21,SEEK_SET);

	char *readBuf;
	readBuf= (char *)malloc(sizeof(char *)n_write + 1);//强制(char *)

	//ssize_t read(int fd,void *buf,size_t count);
	int n_read = read(fd,readBuf,n_write);
	printf("read %d ,context: %s\n",n_read,readBuf);
	close(fd);
	return 0;
}

lseek(fd,-21,SEEK_SET);//第二个参数负数时往前走,正数往后走。
输出结果时
open file1 failed
open suscess:fd = 3
write 4 byte to file1
read 4 ,context :sudu

lseek错误返回一个-1值,成功返回有多少个字节的buf。

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR);
	
	int filesize = lseek(fd,0,SEEK_END);//计算文件大小
	printf("file size is %d\n",filesize);

	close(fd);
	return 0;
}

输出结果 file size is 4

文件打开补充

在Linux命令行输入man 2 open

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>

//API
int open(const char *pathname,int flags);
int open(const char *pathename,int flags,mode_t mode);

int creat(const char *pathname,mode_t mode);

O_CREAT使用这个,需要说明第三个参数mode,用其说明该新文件的存取许可权限。
O_EXCL如果同时制定了O_CREAT,而文件错在,则出错
O_APPEND每次写时都加到文件的尾端
O_TRUNC属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写,什么意思呢,就是将所有文件内容删除。


```c
#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>

int main()
{	
	int fd;
	
	fd = open('./file1',O_RDWR|O_CREAT,0600);//没有file1文件,O_CREAT创建这个文件
	if(fd == -1){
		printf("file exist\n");//文件存在
	}else{
		printf("file no exist\n");//文件不存在,已创建
	}
	return 0;
}

有文件输出:file exist\n //文件存在,已创建 ,没有文件输出:file no exist // 文件不存在,已创建
在Linux命令行输入ls -l
查看文件权限

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR);
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	int n_write = write("fd,buf,strlen(buf)");
	if(n_write != -1){
		printf("write %d byte to file1\n",n_write);
	}
	close(fd);
	return 0;
}

如果是上面这个代码打开,文件之前的内容会被覆盖,类似于如果file1文件内容有1234,而我输入字符串sudu,则覆盖1234,文件内容为sudu。

加入O_APPEND,会往后面加入内容,不会覆盖原来的内容
例子

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR|O_APPEND);
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	int n_write = write("fd,buf,strlen(buf)");
	if(n_write != -1){
		printf("write %d byte to file1\n",n_write);
	}
	close(fd);
	return 0;
}

假设文件内容为:123412341234,则代码输出结果为:123412341234sudu

O_TRUNC的用法

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "sudu";
	
	fd = open('./file1',O_RDWR|O_TRUNC);
	printf("open suscess:fd = %d\n",fd);

	//ssize_t write(int fd,vost void buf,size_t count);
	int n_write = write("fd,buf,strlen(buf)");
	if(n_write != -1){
		printf("write %d byte to file1\n",n_write);
	}
	close(fd);
	return 0;
}

原来的内容全部删除了,只输入buf文件的内容:sudu

man creat
文件模式
上面图片为文件创建的模式。

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	char *buf = "test";
	
	fd = creat('/home/ccc/file1',S_IRWXU);//第一个参数是文件路径,第二个是权限

	return 0;
}

Linux命令行输入pwd,文件路径
Linux命令行输入 ls file1 -l
输出结果rwx,可读可写可执行

文件描述符

在这里插入图片描述

在这里插入图片描述
Linux环境下

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	
	char readBuf[128];
	int n_read = read(0,readBuf,5);//标准输入,写入readbuf,写5个字节
	int n_write = write(1,readBuf,strlen(readBuf));//标准输出,输出readbuf

	printf("\n");
	return 0;
}

在Linux命令行gcc
输入hello
输出hello

重点:
(1)打开/创建文件
(2)读取文件/写入文件
(3)关闭文件

在这里插入图片描述
6、块设备本身读写非常不灵活,是按块读写的,内存按字节单位操作,可以随即操作,很灵活。

实现Linux cp指令用法

Linux命令行中,cp是复制文件,类似cp demo1.c demo2.c

0 1 2
cp src.c des.c
argv[1] argv[2] argv[3]
1、C语言参数 a.out
2、思路

  1. 打开src.c
  2. 读src到buf
  3. 打开/创建des.c
  4. 将buf写入到des.c
  5. close两个文件
#include <stdio.h>

int main(int argc,char **argv)
{
	printf("total param %d\n",argc);
	printf("NO.1 param %d\n",argv[1]);
	printf("NO.2 param %d\n",argv[2]);
	printf("NO.3 param %d\n",argc[3]);
	return 0;
}

Linux命令行 gcc test.c
Linux命令行./a.out des src //这个意思是argv[0] 、argv[1] 、argv[2]
输出结果是:totol params:3
NO.1 param ./a.out
NO.2 param des
NO.3 param src

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char **argv)
{	
	int fdSrc;
	int fdDes;
	char readBuf[1024];
	
	if(argc != 3){
		printf("param error\n");
		exit(-1);
	}
	
	fdSrc = open(argv[1],O_RDWR);//1、打开src文件
	int n_read = read(fdSrc,readBuf,1024);//2、读Src到readBuf
	
	//ssize_t write(int fd,vost void buf,size_t count);
	fdDes = open(argv[2],O_RDWR|O_CREAT,0600);//3、打开创建Des文件

	int n_write = write(fdDes,readBuf,strlen(readBuf));//4、将src读到的readBuf写入Des内容上

	close(fdDes);//5、关闭文件
	close(fdSrc);
	return 0;
}

Linux命令行 gcc demo.c -o mycp
Linux命令行 ./mycp demo.c new.c
new.c 会有个ctrl+c的字符
解决方法是将readBuf[1024] = {0};
有个问题不一定都是1024个字节
所以要用lseek算出大小

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char **argv)
{	
	int fdSrc;
	int fdDes;
	char *readBuf = NULL;
	
	if(argc != 3){
		printf("param error\n");
		exit(-1);
	}
	
	
	fdSrc = open(argv[1],O_RDWR);//1、打开src文件
	int size = lseek(fdSrc,0,SEEK_END);//算出fdSrc的大小
	lseek(fdSrc,0,SEEK_SET);//光标放到第一位
	readBuf = (char *)malloc(sizeof(char *)size + 8);
	
	int n_read = read(fdSrc,readBuf,size);//2、读Src到readBuf
	
	//ssize_t write(int fd,vost void buf,size_t count);
	fdDes = open(argv[2],O_RDWR|O_CREATO_TRUNC,0600);//3、打开创建Des文件,O_RDWR|O_CREAT,所以加O_TRUNC不让文件覆盖

	int n_write = write(fdDes,readBuf,strlen(readBuf));//4、将src读到的readBuf写入Des内容上

	close(fdDes);//5、关闭文件
	close(fdSrc);
	return 0;
}

上面是做的优化,与上方的代码做出一些比较

配置文件的修改

如 SPEED = 5
LENG = 100
SCORE = 90
LEVEL = 95
在Linux命令行写入vi TEST.config
man strstr

修改 LENG = 5

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char **argv)
{	
	int fdSrc;
	
	char *readBuf = NULL;
	
	if(argc != 2){
		printf("param error\n");
		exit(-1);
	}
	
	
	fdSrc = open(argv[1],O_RDWR);//1、打开src文件
	int size = lseek(fdSrc,0,SEEK_END);//算出fdSrc的大小
	lseek(fdSrc,0,SEEK_SET);//光标放到第一位
	
	readBuf = (char *)malloc(sizeof(char *)size + 8);
	
	int n_read = read(fdSrc,readBuf,size);//2、读Src内容到readBuf

	char *p = strstr(readBuf,"LENG = ");

	if(p == NULL){
		printf("not : found");
		exit(-1);
	}
	p = p + strlen("LENG = ");
	*p = '5';//字符串

	int n_write = write(fdSrc,readBuf,strlen(readBuf));//4、将src读到的readBuf写入Des内容上

	close(fdSrc);//5、关闭文件
	return 0;
}

这些在工作后read和open需要做判断
Linux命令行中输入./a.out TEST.config
输出后TEST.config 出现 SPEED = 5
LENG = 100
SCORE = 90
LEVEL = 95
SPEED = 5
LENG = 5
SCORE = 90
LEVEL = 95
另外出现了一行

要的是覆盖,优化下,两种方法,关闭文件,打开文件,第二种移光标

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char **argv)
{	
	int fdSrc;
	
	char *readBuf = NULL;
	
	if(argc != 2){
		printf("param error\n");
		exit(-1);
	}
	
	
	fdSrc = open(argv[1],O_RDWR);//1、打开src文件
	int size = lseek(fdSrc,0,SEEK_END);//算出fdSrc的大小
	lseek(fdSrc,0,SEEK_SET);//光标放到第一位
	
	readBuf = (char *)malloc(sizeof(char *)size + 8);
	
	int n_read = read(fdSrc,readBuf,size);//2、读Src内容到readBuf

	char *p = strstr(readBuf,"LENG = ");

	if(p == NULL){
		printf("not : found");
		exit(-1);
	}
	p = p + strlen("LENG = ");
	*p = '5';//字符串    一定要是字符
	//上面移动了光标
	lseek(fdSrc,0,SEEK_END);

	int n_write = write(fdSrc,readBuf,strlen(readBuf));//4、将src读到的readBuf写入Des内容上

	close(fdSrc);//5、关闭文件
	return 0;
}

Linux命令行输入./a.out TEST.config
就改成这样 SPEED = 5
LENG = 5
SCORE = 90
LEVEL = 95

文件如何记录一个结构体

假如上面*p = ‘5’,不用字符串,用整形5
SPEED = 5
LENG = ^E;
SCORE = 90
LEVEL = 95
会出现这个问题,用ASCII码可以看得到

写入结构体
Linux命令行写入man 2 write

#include <unistd.h>

ssize_t write(int fd,const coid *buf,size_t count);//fd文件,buf无类型的指针,count数量
#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{	
	int fd;
	
	int data = 100;
	int data2 = 0;
	
	fd = open('./file1',O_RDWR);//1、打开fd文件
	
	int n_write = write(fd,&data,sizeof(int));//4、将data读到内容写入fd文件上

	lseek(fd,0,SEEK_SET);

	int n_read = read(fd,&data2,sizeof(int));//将fd文件内容写入data2
	close(fd);//5、关闭文件
	printf("read %d\n",data);
	return 0;
}

int n_write = write(fd,&data,sizeof(int));//4、将data内容写入fd文件上
int n_read = read(fd,&data2,sizeof(int));//将fd文件内容写入data2

Linux命令行写入./a.out
输出 ^@
要用ASCII码看

结构体

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

struct Test
{
	int a;
	char c;
};

int main()
{	
	int fd;
	
	struct Test data = {100,'a'};
	struct Test data2;
	
	fd = open('./file1',O_RDWR);//1、打开fd文件
	
	int n_write = write(fd,&data,sizeof(struct Test));//4、将data读到内容写入fd文件上

	lseek(fd,0,SEEK_SET);

	int n_read = read(fd,&data2,sizeof(struct Test));//将fd文件内容写入data2
	close(fd);//5、关闭文件
	printf("read %d,%c \n",data2.a,data2.c);
	return 0;
}

输出结果 100,a

写结构体数组

#include <sys/types>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

struct Test
{
	int a;
	char c;
};

int main()
{	
	int fd;
	
	struct Test data[2]= {{100,'a'},{101.'b'}};
	struct Test data2;
	
	fd = open('./file1',O_RDWR);//1、打开fd文件
	
	int n_write = write(fd,&data,sizeof(struct Test)*2);//4、将data读到内容写入fd文件上

	lseek(fd,0,SEEK_SET);

	int n_read = read(fd,&data2,sizeof(struct Test)*2);//将fd文件内容写入data2
	close(fd);//5、关闭文件
	printf("read %d,%c \n",data2[0].a,data2[0].c);
	printf("read %d,%c \n",data2[1].a,data2[1].c);
	return 0;
}

输出结果:100,a
101,b
但是一般都用字符,上面都要用ASCII码看

标准C库打开文件

标准C库网址
https://www.cnblogs.com/NickyYe/p/5497659.html

1. 来源

从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别:

  • open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。
    fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。

PS:从来源来看,两者是有千丝万缕的联系的,毕竟C语言的库函数还是需要调用系统API实现的。

2. 移植性

这一点从上面的来源就可以推断出来,

  1. fopen是C标准函数,因此拥有良好的移植性;
  2. open是UNIX系统调用,移植性有限。
    如windows下相似的功能使用API函数CreateFile

3. 适用范围

  1. open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(RegularFile)。

4. 文件IO层次

如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。

5. 缓冲

  • 缓冲文件系统
  • 缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
  • 非缓冲文件系统
  • 缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open,
    close, read, write, getc, getchar, putc, putchar等。
    一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read, write等配合使用, 后者与fread,fwrite等配合使用。

使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用API:read,write);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快;如果随机访问文件则相反。

这样一总结梳理,相信大家对于两个函数及系列函数有了一个更全面清晰的认识,也应该知道在什么场合下使用什么样的函数更合适,效率更高。

Linux下open与fopen的区别

https://www.cnblogs.com/hnrainll/archive/2011/09/16/2178706.html
int open(const char *path, int access,int mode)
path 要打开的文件路径和名称

access 访问模式,宏定义和含义如下:                        
    O_RDONLY         1    只读打开                         
    O_WRONLY         2    只写打开                         
    O_RDWR           4    读写打开                     
    还可选择以下模式与以上3种基本模式相与:                    
    O_CREAT     0x0100   创建一个文件并打开                
    O_TRUNC     0x0200   打开一个已存在的文件并将文件长度设置为0,其他属性保持         
    O_EXCL      0x0400   未使用                            
    O_APPEND    0x0800   追加打开文件                     
    O_TEXT      0x4000   打开文本文件翻译CR-LF控制字符     
    O_BINARY    0x8000   打开二进制字符,不作CR-LF翻译                                                        
mode 该参数仅在access=O_CREAT方式下使用,其取值如下:      
    S_IFMT      0xF000   文件类型掩码                      
    S_IFDIR     0x4000   目录                              
    S_IFIFO     0x1000   FIFO 专用                         
    S_IFCHR     0x2000   字符专用                          
    S_IFBLK     0x3000   块专用                            
    S_IFREG     0x8000   只为0x0000                        
    S_IREAD     0x0100   可读                              
    S_IWRITE    0x0080   可写                              
    S_IEXEC     0x0040   可执行

FILE *fopen(char *filename, char *mode)
filename 文件名称

mode 打开模式:                                            
    r   只读方式打开一个文本文件                           
    rb  只读方式打开一个二进制文件                         
    w   只写方式打开一个文本文件                           
    wb  只写方式打开一个二进制文件                         
    a   追加方式打开一个文本文件                           
    ab  追加方式打开一个二进制文件                         
    r+  可读可写方式打开一个文本文件                       
    rb+ 可读可写方式打开一个二进制文件                     
    w+  可读可写方式创建一个文本文件                       
    wb+ 可读可写方式生成一个二进制文件                     
    a+  可读可写追加方式打开一个文本文件                   
    ab+ 可读可写方式追加一个二进制文件
  • open和fopen的区别:

前者属于低级IO,后者是高级IO。
前者返回一个文件描述符,后者返回一个文件指针。
前者无缓冲,后者有缓冲。
前者与 read, write 等配合使用, 后者与 fread, fwrite等配合使用。
后者是在前者的基础上扩充而来的,在大多数情况下,用后者。

Linux命令行输入 man fopen

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	char readBuf[128] = {0};
	
	//FILE *fopen(const char *path,const char *mode);//第二个是指针
	fp = fopen("./a.txt","w+");

	//size_t fwrite(const void *ptr,size_t size,size_t nmeb,FILE *stream);
	//ptr 内容 buf
	///size 大小 sizeof
	//nmeb  个数 count
	//stream  文件 
	fwrite(str,sizeof(char)*strlen(str),fp);//将str写入fp文件
	//fwrite(str,sizeof(char)*strlen(str),1,fp);//有个1 是写一次的意思
	
	fseek(fp,0,SEEK_SET);

	//size_t fread(void *ptr,size_t size,size_t nmeb,FILE *stream);
	fread(readBuf,sizeof(char),strlen(str),fp);//readBuf缓冲   读fp文件内
	//fread(readBuf,sizeof(char),sizeo(char)fstrlen(str),1,fp);//readBuf缓冲   读fp文件内   读1次
	printf("read data:%s\n",readBuf);
	return 0;
}

输出结果:read data :sudu
Linux命令行 vi a.text
text 内容:sudu。

补充fopen,fread,fwrite,返回的值

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	char readBuf[128] = {0};
	
	//FILE *fopen(const char *path,const char *mode);//第二个是指针
	fp = fopen("./a.txt","w+");

	//size_t fwrite(const void *ptr,size_t size,size_t nmeb,FILE *stream);
	//ptr 内容 buf
	///size 大小 sizeof
	//nmeb  个数 count
	//stream  文件 
	int n_write = fwrite(str,sizeof(char)*strlen(str),fp);//将str写入fp文件
	//fwrite(str,sizeof(char)*strlen(str),1,fp);//有个1 是写一次的意思
	
	fseek(fp,0,SEEK_SET);

	//size_t fread(void *ptr,size_t size,size_t nmeb,FILE *stream);
	int n_read = fread(readBuf,sizeof(char),strlen(str),fp);//readBuf缓冲   读fp文件内
	//fread(readBuf,sizeof(char),sizeo(char)fstrlen(str),1,fp);//readBuf缓冲   读fp文件内   读1次


	printf("read data:%s\n",readBuf);
	printf("read=%d,write =%d\n",nread,nwrite);

	return 0;
}

输出结果read data :sudu
read=4,write =4

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	char readBuf[128] = {0};
	
	//FILE *fopen(const char *path,const char *mode);//第二个是指针
	fp = fopen("./a.txt","w+");

	//size_t fwrite(const void *ptr,size_t size,size_t nmeb,FILE *stream);
	//ptr 内容 buf
	///size 大小 sizeof
	//nmeb  个数 count
	//stream  文件 
	int n_write = fwrite(str,sizeof(char),100,fp);//将str写入fp文件  有100个写进去
	//fwrite(str,sizeof(char)*strlen(str),1,fp);//有个1 是写一次的意思
	
	fseek(fp,0,SEEK_SET);

	//size_t fread(void *ptr,size_t size,size_t nmeb,FILE *stream);
	int n_read = fread(readBuf,sizeof(char),strlen(str),fp);//readBuf缓冲   读fp文件内  读strlen(str)怎么下
	//fread(readBuf,sizeof(char),sizeo(char)fstrlen(str),1,fp);//readBuf缓冲   读fp文件内   读1次


	printf("read data:%s\n",readBuf);
	printf("read=%d,write =%d\n",nread,nwrite);

	return 0;
}

输出结果read data :sudu
read=4,write =100

下面都是写1次,读1次,很关键

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	char readBuf[128] = {0};
	
	//FILE *fopen(const char *path,const char *mode);//第二个是指针
	fp = fopen("./a.txt","w+");

	//size_t fwrite(const void *ptr,size_t size,size_t nmeb,FILE *stream);
	//ptr 内容 buf
	///size 大小 sizeof
	//nmeb  个数 count
	//stream  文件 
	int n_write = fwrite(str,sizeof(char),1,fp);//将str写入fp文件  有1个写进去 ,所以n_write=1
	//fwrite(str,sizeof(char)*strlen(str),1,fp);//有个1 是写一次的意思
	
	fseek(fp,0,SEEK_SET);

	//size_t fread(void *ptr,size_t size,size_t nmeb,FILE *stream);
	int n_read = fread(readBuf,sizeof(char)*strlen(str),1,fp);//readBuf缓冲 读1次,所以n_read =1
	//int n_read = fread(readBuf,sizeof(char),strlen(str),fp);//readBuf缓冲   读fp文件内  读strlen(str)这么多下
	//fread(readBuf,sizeof(char),sizeo(char)fstrlen(str),1,fp);//readBuf缓冲   读fp文件内   读1次


	printf("read data:%s\n",readBuf);
	printf("read=%d,write =%d\n",nread,nwrite);

	return 0;
}

输出结果read data :sudu
read=1,write =1

读100跟写100不一样
下面是读

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	char readBuf[128] = {0};
	
	//FILE *fopen(const char *path,const char *mode);//第二个是指针
	fp = fopen("./a.txt","w+");

	//size_t fwrite(const void *ptr,size_t size,size_t nmeb,FILE *stream);
	//ptr 内容 buf
	///size 大小 sizeof
	//nmeb  个数 count
	//stream  文件 
	int n_write = fwrite(str,sizeof(char),1,fp);//将str写入fp文件  有1个写进去 ,所以n_write=1
	//fwrite(str,sizeof(char)*strlen(str),1,fp);//有个1 是写一次的意思
	
	fseek(fp,0,SEEK_SET);

	//size_t fread(void *ptr,size_t size,size_t nmeb,FILE *stream);
	int n_read = fread(readBuf,sizeof(char)*strlen(str),100,fp);//readBuf缓冲 读100次,但是n_read =1
	//int n_read = fread(readBuf,sizeof(char),strlen(str),fp);//readBuf缓冲   读fp文件内  读strlen(str)这么多下
	//fread(readBuf,sizeof(char),sizeo(char)fstrlen(str),1,fp);//readBuf缓冲   读fp文件内   读1次


	printf("read data:%s\n",readBuf);
	printf("read=%d,write =%d\n",nread,nwrite);

	return 0;
}

输出结果read data :sudu
read=1,write =1

下面是写

#include <stdio.h>
#include <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	char readBuf[128] = {0};
	
	//FILE *fopen(const char *path,const char *mode);//第二个是指针
	fp = fopen("./a.txt","w+");

	//size_t fwrite(const void *ptr,size_t size,size_t nmeb,FILE *stream);
	//ptr 内容 buf
	///size 大小 sizeof
	//nmeb  个数 count
	//stream  文件 
	int n_write = fwrite(str,sizeof(char),100,fp);//将str写入fp文件  有100个写进去 ,所以n_write=100
	//fwrite(str,sizeof(char)*strlen(str),1,fp);//有个1 是写一次的意思
	
	fseek(fp,0,SEEK_SET);

	//size_t fread(void *ptr,size_t size,size_t nmeb,FILE *stream);
	int n_read = fread(readBuf,sizeof(char)strlen(str),fp);//readBuf缓冲 读100次,但是n_read =1
	//int n_read = fread(readBuf,sizeof(char),strlen(str),fp);//readBuf缓冲   读fp文件内  读strlen(str)这么多下
	//fread(readBuf,sizeof(char),sizeo(char)fstrlen(str),1,fp);//readBuf缓冲   读fp文件内   读1次


	printf("read data:%s\n",readBuf);
	printf("read=%d,write =%d\n",nread,nwrite);
	fclose(fd);

	return 0;
}

输出结果read data :sudu
read=1,write =100
为什么会这样,虽然只有sudu 4个字符,但是空格也是

Linux命令行grep “struct ” //这种是在文件上找哪一个有“struct”文件里面

#include <stdio.h>
#include <string.h>

struct Test
{
	int a;
	char c;
};

int main()
{
	FILE *fp;
	struct Test data = {100,'a'};
	struct Test data2;
	
	fp = fopen("./a.txt","w+");
	
	int n_write = fwrite(&data,sizeof(struct Test),1,fp);//将data写入fp文件  有1个写进去
	
	fseek(fp,0,SEEK_SET);
	
	int n_read = fread(&data2,sizeof(struct Test)1,fp);//readBuf缓冲 读100次,但是n_read =1

	printf("read %d,:%c\n",data2.a,data2.c);
	fclose(fd);

	return 0;
}

输出结果read 200,a

fgetc,fputc,feof

用的会比较少
man fputc

#include <stdio.h>

	int fputc = (int c,FILE *stream);
	int fputs(const char *s,FILE *stream);
	int putc(int c,FILE *stream);
	int putchar(int c);
	int puts(const char *s);

fputc

#include <stdio.h>

int main()
{
	FILE *fp;

	fd = fopen("./test.txt","w+");
	fputc('a',fp);
	fclose(fp);

	return 0;
}

输出结果:test.txt内容有a

#include <stdio.h>
#inlcude <string.h>

int main()
{
	FILE *fp;
	char *str = "sudu";
	int i;
	int len = strlen(str);

	fd = fopen("./test.txt","w+");//w+创建文件可写
	for(i=0;i<len ;i++)
	{
		fputc(*str,fp);
		str++;
	}
	
	
	fclose(fp);

	return 0;
}

输出结果:test.txt内容有sudu

feof

man feof

#include <stdio.h>

	void clearerr(FILE *stream);
	int feof(FILE *stream);
	int ferror(FILE *stream);
	int fileno(FILE *stream);
#include <stdio.h>
#inlcude <string.h>

int main()
{
	FILE *fp;
	int i;
	char c;

	fd = fopen("./test.txt","r");//
	
	while(!feof(fp)){//非0是到达文件最后
			c = fgetc(fp);
			printf("%c",c);
	}
	
	fclose(fp);

	return 0;
}

输出结果:sudu
因为之前文件test.txt里面有sudu内容

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值