一、C的文件接口;
1.fopen(const char* path,const char *mode)
参数:
path:要打开文件的路径
mode:打开的方式
**mode:
文件的几种操纵方式:
返回值:
成功:返回文件流指针
失败:返回NULL
2.size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE*stream)
参数:
ptr:想写入的内容
size:写入时,每一块(虚拟概念)的大小,以字节为单位(通常为1个字节),也可以自行定义。
nmemb:写入的块数目 写入的总字节数=size*nmemb
stream:文件流指针。
返回值:成功写入到文件的块的数目,(不是字节数)
函数验证:
#include<stdio.h>
#include<string.h>
int main()
{
FILE *p=fopen("1.txt","w+");
if(p==NULL)
{
perror("fopen !!");
return 0;
}
const char *strr="hello you ";
ssize_t size=fwrite(strr,1,strlen(strr),p);
return 0;
}
~
~
文件创建成功:
文件写入正确:
最终返回值为10,说明写入了10个“块”,由于一个块的大小为1个字节,所以写入了10个字节
3.size-t fread(void *ptr,size_t size,size_t nmemb,FILE*stream)
参数:
ptr:将读取的内容保存至ptr指向的内存空间之中
size:定义读取时,一个块的大小,以字节为 单位
nmemb:想要读取的块数
stream:文件流指针
返回值:返回成功读入的文件块的个数
#include<stdio.h>
int main()
{
FILE* fp=fopen("1.txt","r");
if(fp==NULL)
{
perror("fopen!! ");
return 0;
}
char buf[1024];
ssize_t size=fread(buf,1,sizeof(buf)-1,fp);
//将buf的接收大小定义为 sizeof(buf)-1,原因如下:
/*
预留"\0"的位置
*/
printf("size--> %d,buf: %s\n",size,buf);
return 0;
}
~
**设置接收大小为sizeof(buf)-1的原因:预留"\0"的空间,从而在后面访问时,能找到 \0结束符,从而不会越界访问。
执行成功,显示读取了10个块(10个字节),以及接收的字符数组的内容。
4.int fseek(FILE*stream,long offest,int whence)
功能:
移动文件流指针的位置
为何要移动文件流指针的位置?
看看下面的程序实例:
#include<stdio.h>
#include<string.h>
int main()
{
/*
*写入文件并
* 读取文件
* */
FILE *fp=fopen("2.txt","w+");
if(fp==NULL)
{
perror("fopen !! ");
return 0;
}
const char *str="HELLO OLLEH ";
ssize_t wsize=fwrite(str,1,strlen(str),fp);
printf("写入的块数: %d \n",wsize);
char buf[1024]={0};
ssize_t rsize=fread(buf,1,sizeof(buf)-1,fp);
printf("读取的块数:%d ,内容: %s \n",rsize,buf);
return 0;
}
~
执行结果:
由此可以明显看到,使用fread函数时,buf字符数组中没有读取到任何内容,为何?
其实是由于文件流指针的位置,写完文件后,其指向最后一个字节后面的一个位置,若再调用fread,则开始读时,后面没有内容,自然为空了。
解决:使用fseek函数
参数:stream:文件流指针
offset:偏移量
whence:将文件流指针移动到什么位置
SEEK_SET:文件头部
SEEK_CUR:当前文件流指针的位置
SEEK_END:文件的末尾
返回值:
成功:0
失败:-1
接下来就可以使用fseek函数,将文件流指针移动至文件头部,再进行读取。
#include<stdio.h>
#include<string.h>
int main()
{
/*
*写入文件并
* 读取文件
* */
FILE *fp=fopen("2.txt","w+");
if(fp==NULL)
{
perror("fopen !! ");
return 0;
}
const char *str="HELLO OLLEH ";
ssize_t wsize=fwrite(str,1,strlen(str),fp);
printf("写入的块数: %d \n",wsize);
//移动文件流指针的位置
fseek(fp,0,SEEK_SET);
char buf[1024]={0};
ssize_t rsize=fread(buf,1,sizeof(buf)-1,fp);
printf("读取的块数:%d ,内容: %s \n",rsize,buf);
return 0;
}
执行成功,成功读取文件内容
5.
ffclose(FILE*fp)
打开文件后,一定要关闭文件,否则会造成文件句柄泄露(内存泄露)
二、
系统调用的文件接口:
1.open
int open(const char *pathname,int flag,mode_t mode)
参数:
pathname:打开文件的路径
flags:打开文件的方式:以下三种方式必选且只选一种 与可选项按位或 | 构成了flags
O_RDONLY 只读
O_WRONLY 只写
O_RDWR:读写
可选项:
O_CREAT: 若文件不存在,则创建,创建时需搭配mode中的选项,以此指明文件的权限
O_APPEND:追加写。
mode:新建文件时,指定文件的权限,传递一个8进制数字
返回值:
成功:返回打开的文件描述符 >=0的数字
失败:返回-1
函数使用:
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd=open("./1.txt",O_RDONLY |O_CREAT,0664 );
printf("%d \n",fd);
return 0;
}
打开成功,返回了一个文件描述符: ” 3“
扩展:
创建一个进程,在代码中可以使用printf、scanf,是由于进程在创建过程中,分别创建了标准输入、输出、标准错误,即:
stdout
stdin
stderr
2.write
ssize_t write(int fd,cosnt void*buf,size_t count)
参数:
fd:文件描述符
buf:将buf指向的内容写到文件中去
count:想要写入的字节数目
返回值:
成功:写入的字节数目
3.read
ssize_t read(int fd,void *buf,size_t count)
参数:
fd:文件描述符
buf:读取内容的存放空间
count:想要读取的字节数
返回值:返回读取的字节数
4.lseek
off_t lseek(int fd,off_offset,whence)
fd:文件描述符
offset:偏移量
whence:将文件流指针移动到什么位置
SEEK_SET:文件头部
SEEK_CUR:当前文件流指针的位置
SEEK_END:文件的末尾
5.clsoe
int close(int fd)
关闭文件描述符
系统函数的综合使用:
#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<string.h> int main() { int fd=open("./1.txt",O_RDONLY |O_CREAT,0664 ); printf("%d \n",fd); const char*str="Linux linux "; ssize_t fsize=fwrite(fd,str,strlen(str)); printf("fsize: %d\n",fsize); //同样使用lseek函数,将文件流指针指向第一个字节,使得读取数据有效 lseek(fd,0,SEEK_SET); char buf[1024]={0}; ssize_t rsize=fread(fd,buf,sizeof(buf)-1); printf("rsize:%d, buf: %s \n",rsize,buf); close(fp); return 0; }
**fopen、open;fread、read的不同
1.fopen返回值是文件流指针: FILE* fp open函数返回文件描述符 int fd
2.fread 需要指明”块“、”块数“ read函数只写明要读取的字节数(以实际文件决定)