Linux、标准c库对文件操作的区别
1.来源
从来源的角度看,两者能很好的区分开,这也是两者最显而易见的区别:
- open是UNIX系统调用函数 (包括LINUX等) ,返回的是文件描述符 (File Descriptor),它是文件在文件描述符表里的索引。.·
- fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
2.移植性
- 这一点从上面的来源就可以推断出来,‘fopen’是C标准函数,因此拥有良好的移植性,而‘open’是UNIX系统调用,移植性有限。如windows下只能运行’fopen‘,但无法运行‘open’,若想要在windows下运行‘open’,则只能在windows下相似的功能使用API函数 ‘CreateFile’。
3.适用范围
- open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件 (Regular File)。(一些特定情况下只能用open)
- fopen是用来操纵普通正规文件 (Regular File) 的。
- 两者都能操纵普通正规文件,但通常推荐fopen
4.文件IO层次
- 如果从文件I0的角度来看,前者属于低级I0函数,后者属于高级I0函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。
5.缓冲
- 1.缓冲文件系统缓冲文件系统的特点是:在内存开辟一个"缓冲区”,为程序中的每一个文件使用,当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存"缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件"缓冲区”的大小随机器 而定。fopen,fclose,fread,fwrite,fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等
- 2.非缓冲文件系统缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open,close,read,write, getc,getchar, putc,putchar等。
- 一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read,write等配合使用,后者与fread,fwrite等配合使用。
- 使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用AP:read,wite);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换,表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快;如果随机访问文件则相反。
标准c库对文件操作
1.fopen函数
可以在Linux环境下用fopen函数创建或打开一个已有的文件,其返回值是FILE类型的文件名,函数原型如下:
FILE *fopen(const char *filename, const char *mode);
const char *filename | 文件名 |
,const char *mode | 打开文件的权限(方式) |
文件的打开方式有很多种,下面是对常用文件打开方式的汇总
方式 | 解释 |
r | 打开一个已有的文本文件,允许读取文件,文件必须存在 |
r+ | 打开一个已有的文本文件,允许读写文件,文件必须存在 |
w | 以写的方式打开文件。如果文件不存在 , 就创建文件 ; 如果文件存在 , 覆盖原有数据重新写入数据 ; 写出时 , 将该文件原有数据覆盖 , 即文件长度清 0 , 删除文件内容 , 重新写入文件内容 |
w+ | 以读写的方式打开已有的文本文件。如果文件不存在 , 就创建文件 ; 如果文件存在 , 覆盖原有数据重新写入数据 ; 写出时 , 将该文件原有数据覆盖 , 即文件长度清 0 , 删除文件内容 , 重新写入文件内容 |
a | 以追加方式打开写文件。如果文件不存在 , 则 创建文件 ;如果文件存在 , 则新写入的数据会被 追加到文件末尾 , 文件原来的数据会被保留 |
a+ | 以追加方式打开读写文件。如果文件不存在 , 则 创建文件 ;如果文件存在 , 则新写入的数据会被 追加到文件末尾 , 文件原来的数据会被保留 |
2.fclose函数
与Linux对文件操作一样,打开文件对文件进行一系列操作后,需关闭文件,则调用flose,函数原型如下:
int fclose( FILE *fp );
参数是打开文件的返回值,与文件描述符类似
如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。
3.fwrite函数
函数原型如下:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
void *ptr | 缓冲区(内容存放的地方) |
size_t size | 写入字节的大小 |
size_t nmemb | 写入字节的个数 |
FILE *stream | 内容输入位置(将内容传到指定位置) |
4.fread函数
函数原型如下:
size_t fread(void *ptr, size_t size, sizet nmemb, FILE *stream);
void *ptr | 缓冲区(读取内容后内容存放的地方) |
size_t size | 读取字节的大小 |
sizet nmemb | 读取字节的个数 |
FILE *stream | 一开始存放内容的位置(即将读取) |
代码展示
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char *buf = "Hello word";
char readBuf[128] = {0};
fp = fopen("Luo.text","w+");//打开Luo.text,若不存在则创建一个
fwrite(buf,sizeof(char),strlen(buf),fp);//buf是字符串,所以只第二个参数是字符型字节大小,第三个参数是字符串长度,将buf中的内容写到fp
// fwrite(buf,sizeof(char)*strlen(buf),1),fp);//也可以计算总的长度后,只计算1次
fseek(fp,0,SEEK_SET);//光标移动方便读取
fread(readBuf,sizeof(char),strlen(buf),fp);//将fp中的内容读取到readBuf中
// fread(readBuf,sizeof(char)*strlen(buf),1),fp);//与上面类似
printf("read context is %s\n",readBuf);
return 0;
}