C文件的接口
FILE * fopen(const char * path,const char* mode)
- 打开文件出错则返回空
- FILE: 返回值是文件流指针
- path: 需要打开哪一个文件,可以带路径,如果不带路径,则在当前的目录下寻找
- mode:
- r:以读方式打开,如果当前打开的文件不存在则报错
- r+:以读写方式打开,如果当前打开的文件不存在,则报错
- w:以写方式打开,如果文件不存在则创建文件,如果文件存在,则将当前文件截断,截断是指清空,文件流指针指向文件头部
- w+:以读写方式打开,如果文件不存在则创建,如果文件存在,则将当前文件截断,文件流指针指向文件头部
- a:以追加方式打开,如果文件不存在则创建
- a+:以追加方式打开,如果文件不存在则创建当前的a+是支持读的
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
- ptr:将fread读到的内容保存在ptr里
- size: 块的大小 ,比如是五个字节读取的,如果不够五个字节则不会读
- nmemb:块的个数
- size*nmemb==总的字节数量(如果是7个字节,size为3,nmemb为2,则返回值为2,如果size为2,nmemb为4,返回为3)
- stream: 文件流指针,从哪里读
- 返回值:返回成功读到的块的个数 如果是8个字节,块的大小是5个字节,则返回值为1(5个字节)
- 常用的用法:将快的大小指定为1,快的个数就是ptr的内存空间大小
size_t fwrite(const void* ptr, size_t size, size_t nmemb,FILE* stream)
- ptr:写什么数据,写的数据放到ptr当中
- size:写数据的时候块的大小
- nmemb: 块的个数
- stream: 写到哪里去,文件流指针
- 返回值:返回成功写入的块的个数
常用的用法:将size指定为1,然后返回值计算成功写入的字节数
int fseek(FILE* stream,long offet,int whence)
- stream:文件流指针
- offet:偏移量,针对第三个参数whence的
- 返回值:成功返回0,否则,将返回-1并设置errno以指示错误。
- whence:需要将文件流指针定位到那个位置
whence的三个取值
SEEK_SET:文件头
SEEK_END:文件尾
SEEK_CUR.:当前位置
int fclose(FILE* stream)
函数 fclose 将名为 stream 的流与它底层关联的文件或功能集合断开。如果流曾用作输出,任何缓冲的数据都将首先被写入,使用 fflush(3) 。
- 返回值:成功执行返回 0,否则返回 EOF 并设置全局变量 errno 来指示错误发生。
- stream:文件流指针
看段代码吧
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
FILE *fp=fopen("tmp.txt","w+");
if(!fp)
{
perror("fopen");
return 0;
}
//打开成功
char lp[1024]={0};
int ret=fwrite("lhy mwj",1,7,fp);
if(ret==7)
{
printf("write size:%d\n",ret);
}
else
{
printf("write size :%d\n",ret);
}
//读文件
fseek(fp,0,SEEK_SET);
ret=fread(lp,2,sizeof(lp)-1,fp);
if(ret==7)
{
printf("fread size:%d\n",ret);
}
else
{
printf("fread size:%d\n",ret);
}
fclose(fp);
return 0;
}
文件存储内容为lhy mwj 一共7个字节,设置的块大小为2个字节,所以返回块的个数为3,不够两个字节的不读
系统文件I/O
int open(const char* pathname,int flags,mode_t mode)
- pathname:要打开的文件的路径+文件名称
- flags:以何种方式打开
- mode: 对新创建的文件,设置文件权限
- 返回值:打开成功则返回文件描述符,错误则返回-1
ssize_t write(int fd,const void* buf,size_t count)
write向文件描述符fd所引用的文件中写入从buf开始的缓冲区中count字节的数据
- fd:文件描述符
- buf:写什么数据
- count:写入数据的大小
- 返回值:成功时返回所写入的字节数(若为零则表示没有写入数据). 错误时返回-1,并置errno为相应值.若count为零,对于普通文件无任何影响,但对特殊文件 将产生不可预料的后果.
ssize_t read(int fd,char *buf,size_count)
read() 从文件描述符 fd 中读取 count 字节的数据并放入从 buf 开始的缓冲区中.
- fd:文件描述符
- buf: 数据存储的空间,独到的数据存到哪里去
- count: 最大读多少,一般是buf的空间-1
- 返回值: 成功时返回读取到的字节数(为零表示读到文件描述符), 此返回值受文件剩余字节数限制.当返回值小于指定的字节数时并不意味着错误;这可能是因为当前可读取的字节数小于指定的字节数(比如已经接近文件结尾,或者正在从管道或者终端读取数据,或者read()被信号中断). 发生错误时返回-1,并置 errno 为相应值.在这种情况下无法得知文件偏移位置是否有变化.
off_t lseek(int fd,off_offset,int whence)
- fd: 文件描述符
- offset:偏移量
- whence:偏移到哪里去
- 返回值:成功完成后,Lseek()返回从文件开始以字节为单位测量的偏移位置。在出现错误时,返回值(off_t) -1,并设置errno来指示错误。
int close(int fd)
close 关闭 一个 文件描述符 , 使它不在 指向任何文件和可以在新的文件操作中被再次使用. 任何与此文件相关联的以及程序所拥有的锁 , 都会被删除 (忽略那些持有锁的文件描述符)
- fd:文件描述符
- FILE *fd=fopen();
查看操作系统为进程所分配的文件描述符信息
ll /proc/[pid]/fd
程序最多打开的文件的数量是1021因为已经有三个文件在进程创建的时候被打开 stdin stdout stderr 。所以程序在开发阶段,除了有内存泄露还有文件描述符泄露
重定向int dup2(int oldfd,int newfd)
- dup2()使newfd是oldfd的副本,如果需要首先关闭newfd,如果oldfd不是一个有效的的文件描述符,则调用失败,newfd不会关闭,如果oldfd是一个有效的文件描述符,并且newfd和oldfd的值相同,那么dup2()什么事都不做,返回newfd
- 返回值:如果成功则返回系统调用的新的描述符,失败返回-1,并设置erron
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
//打开文件
//int open(const char * pathname,int flags,mode_t mode)
//pathname:要打开的文件路径
//flags:当做位图来处理的 以何种方式打开 O_RDONLY,O_WRONLY,O_RDWR这三个参数任选其一
//可以附加的参数O_CREAT:如果打开的文件不存在则创建文件
//O_TRUNC:打开文件之后截断文件
//O_APPEND:以追加方式打开 附加的组合|来使用
// close(0);//关闭了标准输入
// 打开
int fd=open("./tmp.txt",O_RDWR | O_CREAT|O_APPEND, 0664);
if(fd<0)
{
perror("open");
return 0;
}
printf("fd:[%d]\n",fd);
//写
int ret=write(fd,"lhy",3);
if(ret<0)
{
perror("write");
return 0;
}
//偏移到文件头部
lseek(fd,1,SEEK_SET);//使文件流指针从写入的最末尾偏移到文件头部再进行读
//读
char buf[1024]={0};
ret=read(fd,buf,sizeof(buf)-1);//最多读1023个字节
if(ret<0)
{
printf("read error");
return 0;
}
else if(ret==0)
{
printf("read size [%d]\n",ret);
}
printf("%s\n",buf);
close(fd);//关闭文件描述符
return 0;
}