目录
1. feof / ferror
feof () 函数判断 : int feof(FILE *stream);
功能:判断当前参数stream的文件流指针是否到达文件结尾,如果到达文件结尾则返回真,否则返回假
注意:该操作一定要在一次IO操作之后判断。
参数:stream 要判断结尾的文件流对象
返回值:成功到达结尾是 真 , 否则 是假
ferror : 检测一个流是否出错
if (feof(fp)) {
printf("到达文件末尾!\n");
} else {
printf("未到达文件末尾!\n");
}
if (ferror(fp)) {
printf("出错!\n");
clearerr(fp);
} else {
printf("未出错!\n");
}
2. fseek
int fseek(FILE *stream, long offset, int whence);
功能:将stream流文件中的文件指针从whence位置开始,偏移offset字节的长度。
参数:stream 要移动文件指针的目标文件流对象。
注意:不支持设备文件,一般用于普通文件。
offset 要在文件内偏移的距离,单位字节。
如果值为整数,则向文件末尾偏移
如果值为负数,则向文件开头偏移
whence 偏移的起始位置,由系统定义的三个宏开始。
SEEK_SET 文件的开头位置
SEEK_CUR 文件的当前位置
SEEK_END 文件的末尾位置
返回值:
成功: 返回 0
失败: -1;
如果从文件的指定位置向后偏移过程中已经超过了文件的当前末尾位置,则会自动以'\0'来填充文件内容,从而形成一种被称为"空洞文件" 的特殊文件。
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("./01fopen.c","r");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
int ret = fseek(fp,10,SEEK_SET);
if(-1 == ret)
{
printf("fseek error\n");
return 1;
}
char buf[512]={0};
fgets(buf,sizeof(buf),fp);
printf("buf is %s\n",buf);
fclose(fp);
return 0;
}
3. ftell
long ftell(FILE *stream);rewind(fp);
功能:获取当前文件流指针的具体位置,一般以文件开头到当前指针的字节数为返回值。
参数:stream 要返回指针距离的文件流对象
返回值:成功 获取到的距离长度,单位是字节;失败 -1;
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("./2.png","r");
if(NULL == fp)
{
return 1;
}
fseek(fp,0,SEEK_END);
long size = ftell(fp);
fclose(fp);
printf("size is %ld\n",size);
return 0;
}
4. 缓冲
(1)行缓冲
1k, terminal,主要用于人机交互stdout
缓存区满或者遇到\n刷新 1024,行缓存多是关于终端的一些操作
1.遇到\n刷新
2.缓存区满刷新(1k = 1024)
3.程序结束刷新
4.fflush刷新 fflush(stdout);
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
/* 1. 如果在hello后面加上 '\n' ,就会在屏幕上显示
printf("hello");
while(1)
sleep(1);
*/
/* 2. i 为超过1024,则在屏幕上显示前1024个a
int i=0;
for(i=0;i<1025;i++)
{
//printf("a");
fputc('a',stdout);// stdin stdout stderr
}
while(1)
sleep(1);
*/
/*3. 程序结束
printf("hello");
*/
/* 4. fflush 刷新
printf("hello");
fflush(stdout);
while(1)
sleep(1);
return 0;
}
(2)全缓冲
4k,主要用于文件的读写
缓存区满刷新缓存区 4096,对普通文件进行标准IO操作,建立的缓存一般为全缓存
刷新条件:
1.缓存区满刷新
2.程序结束刷新
3.fflush来刷新 fflush(fp);
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("1.txt","w");
if(NULL == fp)
{
return 1;
}
/* 1
char buf[]="hello";
fputs(buf,fp);
while(1)
sleep(1);
*/
/*2
int i=0;
for(i = 0 ;i < 4097;i++)
{
fputc('a',fp);
}
while(1)
sleep(1);
return 0;
*/
/*3
char buf[]="hello";
fputs(buf,fp);
return 0;
*/
char buf[]="hello";
fputs(buf,fp);
fflush(fp);
while(1)
sleep(1);
return 0;
}
(3)无缓冲
0 k 主要用于出错处理信息的输出 stderr ,不对数据缓存直接刷新
printf( ); => stdout
fprintf(strerr,"fopen error %s",filename);
界面交互 出错处理:使用gdb查看,FILE结构体,或使用写入数据测试缓冲区。
缓冲区的大小是可以设置
5. 文件io
操作系统为了方便用户使用系统功能而对外提供的一组系统函数。称之为 系统调用 其中有个 文件IO,一般都是对设备文件操作,当然也可以对普通文件进行操作。
一个基于Linux内核的没有缓存的IO机制。
特性:
1.没有缓存区
2.操作对象不在是流,而是文件描述符 FILE* int 0-1023
3.文件描述符
很小的非负的整数 int 0~1023
内核每打开一个文件就会获得一个文件 描述符
每个程序在启动的时候操作系统默认为其打开 三个描述符与流对象匹配:
0 ==> STDIN_FILENO ==> stdin
1 ==>STDOUT_FILENO == >stdout
2 ==>STDERR_FILENO ==> stderr
注:因为0,1,2被这三个描述符占了,所以我们写的文件一般从3开始。
6. 操作函数
6.1 open
int open(const char *pathname, int flags,int mode);
功能:获得一个文件描述符
参数:
pathname : 文件名
flags:
O_RDONLY (只读)
O_WRONLY(只写) // 三选一
O_RDWR (读写)
O_CREAT, 创建文件
O_EXCL 需要和O_CREAT同时使用,表示新建的文件不能存在,成功,否则open就会失败
O_NOCTTY 不是终端设备
O_TRUNC 文件内容清空(如果写上这个标志位,就要指定模式,对普通文件传0666)
O_APPEND 追加
O_ASYNC 异步io,什么时候io不确定,
O_NONBLOCK 非阻塞
返回值:成功返回文件描述符,失败返回-1
fopen open
w O_WRONLY | O_CREAT | O_TRUNC
w+ O_RDWR | O_CREAT | O_TRUNC
r O_RDONLY
r+ O_RDWR
a O_WRONLY | O_CREAT | O_APPEND
a+ O_RDWR | O_CREAT | O_APPEND
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_WRONLY| O_CREAT|O_TRUNC,0666);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
printf("fd is %d\n",fd);
return 0;
}
6.2 write
ssize_t write(int fd, const void *buf, size_t count);
功能 : 通过文件描述符向文件中写一串数据
参数:
fd : 文件描述符
buf : 要写入文件的字符串的首地址
count : 要写入字符的个数(实际有效长度,字符一般用strlen)
返回值 : 成功返回实际写入的个数,失败返回 -1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_WRONLY| O_CREAT|O_TRUNC,0666);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
printf("fd is %d\n",fd);
char buf[512]="hello";
int ret = write(fd,buf,strlen(buf));
if(-1 == ret)
{
fprintf(stderr,"write error\n");
return 1;
}
close(fd);
return 0;
}
6.3 read
ssize_t read(int fd, void *buf, size_t count);
功能 : 通过文件描述符读取文件中的数据
参数:
fd : 文件描述符
buf : 存放数据空间的首地址
count : 要读到数据的个数
返回值:成功返回读到数据的个数,失败返回-1,读到文件结尾返回0
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_RDONLY);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
printf("fd is %d\n",fd);
char buf[512]={0};
while(1)
{
int ret = read(fd,buf,sizeof(buf));
if(ret<=0) // 表示读完或者错误
{
break;
}
printf("%s\n",buf);
}
close(fd);
return 0;
}
6.4 lseek
off_t lseek(int fd, off_t offset, int whence);
功能:定位光标的位置
参数:
fd : 文件描述符
offset : 偏移量
正 : 向后偏移
负 : 向前偏移
零 : 不偏移
whence:
SEEK_SET
SEEK_CUR
SEEK_END
返回值 :成功返回偏移量,失败返回-1
注意:
1、不支持O_APPEND的追加模式,无法生成空洞文件。
2、lseek函数执行失败,文件指针还在偏移前的位置。
3、lseek函数在设备文件上偏移无效。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd = open("1.txt",O_RDWR);
if(-1 == fd)
{
fprintf(stderr,"open error\n");
return 1;
}
off_t off = lseek(fd,15,SEEK_SET);
printf("off %ld\n",off);
char buf[]="hello";
write(fd,buf,strlen(buf));
printf("fd is %d\n",fd);
close(fd);
return 0;
}
7. 练习
用read 和 write 写出 复制文件的功能
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if(argc < 3)
{
fprintf(stderr,"usage:./a.out srcfile dstfile\n");
return 1;
}
int src_fd = open(argv[1],O_RDONLY);
int dst_fd = open(argv[2],O_WRONLY| O_CREAT|O_TRUNC,0666);
if(-1 == src_fd ||-1 == dst_fd)
{
fprintf(stderr,"open error\n");
return 1;
}
while(1)
{
char buf[512]={0};
int rd_ret = read(src_fd,buf,sizeof(buf));
if(rd_ret<=0)
{
break;
}
write(dst_fd,buf,rd_ret);
}
close(dst_fd);
close(src_fd);
return 0;
}