一、open和fopen区别 概念
二、标准C库 man 手册
三、标准C库 API 代码实现
四、标准C库 写入结构体到文件
五、标准C库 fputc()、fputs()函数 API
六、标准C库 fgetc()、feof() 和 ferror()函数 API
一、open和fopen区别 概念
1. 来源
从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别:
open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
PS:从来源来看,两者是有千丝万缕的联系的,毕竟C语言的库函数还是需要调用系统API实现的。
2. 移植性
这一点从上面的来源就可以推断出来,
fopen是C标准函数,因此拥有良好的移植性;而open是UNIX系统调用,移植性有限。如windows下相似的功能使用API函数CreateFile。
3. 适用范围
open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。fopen是用来操纵普通正规文件(Regular File)的。
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的区别
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等配合使用。
后者是在前者的基础上扩充而来的,在大多数情况下,用后者。
二、man 手册
参数定义
*path 文件
*mode 文件权限
FILE *fp 返回值(返回的是文件流)
*ptr buf
size_t size 类型大小
size_t nmemb 个数
stream 文件FILE索引(哪个文件)
EOF作用:
EOF 本来表示文件末尾,意味着读取结束,但是很多函数在读取出错时也返回 EOF ,
那么当返回 EOF 时,到底是文件读取完毕了还是读取出错了?
我们可以借助 stdio.h 中的两个函数来判断,分别是 feof() 和 ferror() 。
- fopen
SYNOPSIS
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
- fwrite / fread
SYNOPSIS
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
- fseek
SYNOPSIS
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
- fclose
SYNOPSIS
#include <stdio.h>
int fclose(FILE *stream);
三、标准C库 API 代码实现
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char *str = "ga li nian gao !";
char readBuf[128] = {0};
// FILE *fopen(const char *pathname, const char *mode);
fp = fopen("./tan.txt","w+");
// size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
//ptr buf
//size sizeof 类型大小
//nmemb 个数
//stream 哪个文件
fwrite(str,sizeof(char),strlen(str),fp);
// int fseek(FILE *stream, long offset, int whence);
fseek(fp,0,SEEK_SET);
// size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
fread(readBuf,sizeof(char),strlen(str),fp);
printf("read data: %s\n",readBuf);
// int fclose(FILE *stream);
fclose(fp);
return 0;
}

read / write 的返回值
size_t fwrite 和 size_t fwrite 返回值与第三个参数(size_t nmemb)有关
int nwrite = fwrite(str,sizeof(char),strlen(str),fp);
int nread = fread(readBuf,sizeof(char),strlen(str),fp);
int nwrite = fwrite(str,sizeof(char)*strlen(str),1,fp);
int nread = fread(readBuf,sizeof(char)*strlen(str),1,fp);

int nwrite = fwrite(str,sizeof(char)*strlen(str),1,fp);
int nread = fread(readBuf,sizeof(char)*strlen(str),100,fp);
int nwrite = fwrite(str,sizeof(char)*strlen(str),100,fp);
int nread = fread(readBuf,sizeof(char)*strlen(str),1,fp);

四、标准C库 写入结构体到文件
Linux查找文件内容(grep)
- grep是Linux命令行下常用于查找过滤文本文件内容的命令。最简单的用法是:
- 如果想忽略大小写,可以用-i参数:
- 如果想搜索目录里所有文件,包括子目录的话,并且在结果中显示行号,可以用以下命令:
grep 查找内容 文件
grep -i 查找内容 文件
grep -nr 查找内容 *

基于前面的代码写入一个结构体到文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
int a;
char c;
};
int main()
{
FILE *fp;
struct Test data1 = {100,'a'};
struct Test data2;
fp = fopen("./file4","w+");
int n_write = fwrite(&data1,sizeof(struct Test),1,fp);
fseek(fp,0,SEEK_SET);
int n_read = fread(&data2,sizeof(struct Test),1,fp);
printf("fread %d,%c\n",data2.a,data2.c);
fclose(fp);
return 0;
}

五、标准C库 fputc()、fputs()函数 API

SYNOPSIS
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
写入字符到文件 代码实现
#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("./test.txt","w+");
//int fputc(int c, FILE *stream);
fputc('a',fp);
fclose(fp);
return 0;
}
写入字符串到文件 代码实现

- fputc()函数实现
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int i;
char *str = "ga li nian gao !";
int length = strlen(str);//先计算出大小,不然后面偏移会影响输出
fp = fopen("./test.txt","w+");
//int fputc(int c, FILE *stream);
for(i=0;i<length;i++){
fputc(*str,fp);
str++;
}
fclose(fp);
return 0;
}
- fputs()函数实现
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char *str = "ga li nian gao !";
fp = fopen("./test.txt","w+");
//int fputs(const char *s, FILE *stream);
fputs(str,fp);
fclose(fp);
return 0;
}
fputs("ga li nian gao !\n",fp);
六、标准C库 fgetc()、feof() 和 ferror()函数 API



SYNOPSIS
#include <stdio.h>
int feof(FILE *stream);
int ferror(FILE *stream);
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
feof()、fgetc()调用
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char c;
fp = fopen("./test.txt","r");
// int feof(FILE *stream);
while(!feof(fp)){// nonezero if reach end of file
// int fgetc(FILE *stream);
c = fgetc(fp);
printf("%c",c);
}
fclose(fp);
return 0;
}
fgetc()、 ferror()调用
#include<stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char c;
if( (fp=fopen("./file1","r+")) == NULL ){
printf("打开文件失败!\n");
exit(0);
}
//int fgetc(FILE *stream);
//每次读取一个字节,直到读取完毕
while( (c=fgetc(fp)) != EOF){
putchar(c);
}
//读取文件成功返回非零值,否则返回零值
//int ferror ( FILE *fp );
if(ferror(fp)){
printf("读取失败\n");
}else{
printf("读取成功\n");
}
fclose(fp);
return 0;
}

5090

被折叠的 条评论
为什么被折叠?



