feof 检测文件是否到达结尾
feof() 函数判断int feof(FILE *stream);
功能:判断当前参数stream的文件流指针是否到达文件结尾。如果到达文件结尾则返回真,否则返回假。
注意:该操作一定要在一次IO操作之后判断。
参数:stream 要判断结尾的文件流对象
返回值:成功到达结尾是 真 否则 是假
ferror 检测一个流是否出错
一、标准IO之文件定位
fseek() ftell() rewind()
int fseek(FILE *stream, long offset, int whence);
功能:将stream流文件中的文件指针从whence位置开始偏移offset字节的长度。
参数:stream 要移动文件指针的目标文件流对象。
注意:不支持设备文件,一般用于普通文件。
offset 要在文件内偏移的距离,单位字节。
如果值为整数,则向文件末尾偏移
如果值为负数,则向文件开头偏移
whence 偏移的起始位置,由系统定义的三个宏开始。
SEEK_SET 文件的开头位置 SEEK_CUR 文件的当前位置 SEEK_END 文件的末尾位置
返回值: 成功: 返回 0 失败: -1;
如果从文件的指定位置向后偏移过程中已经超过了文件的当前末尾位置,则会自动以'\0'来填充文件内容,从而形成一种被称为"空洞文件" 的特殊文件。
fseek()
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("1.txt","w+");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
char buf[128]="hello world";
fputs(buf,fp);
fseek(fp,0,SEEK_SET);
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),fp);
printf("buf is %s\n",buf);
fclose(fp);
return 0;
}
ftell()
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("/home/linux/1.png","r");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
fseek(fp,0,SEEK_END);
long size = ftell(fp);
printf("size is %ld\n",size);
fclose(fp);
return 0;
}
rewind() 回到开头(复位)
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("1.txt","r");
if(NULL == fp)
{
printf("fopen error");
return 1;
}
char buf[1024]={0};
fgets(buf,sizeof(buf),fp);
printf("1 buf is %s\n",buf);
rewind(fp);
fgets(buf,sizeof(buf),fp);
printf("2 buf is %s\n",buf);
fclose(fp);
return 0;
}
二、缓冲区
1.行缓冲
行缓冲,1k, terminal,主要用于人机交互stdout
缓存区满或者遇到\n刷新 1024
行缓存多是关于终端的一些操作
1.遇到\n刷新
2.缓存区满刷新
3.程序结束刷新
4.fflush刷新 fflush(stdout);
2.全缓冲
全缓冲,4k,主要用于文件的读写
缓存区满刷新缓存区 4096
对普通文件进行标准IO操作,建立
的缓存一般为全缓存
刷新条件:
1.缓存区满刷新
2.程序结束刷新
3.fflush来刷新 fflush(fp);
3.无缓冲
无缓冲,0k 主要用于出错处理信息的输出 stderr
不对数据缓存直接刷新
三、文件IO
操作系统为了方便用户使用系统功能而对外提供的一组系统函数。称之为 系统调用,其中有个文件件IO
一般都是对设备文件操作,当然也可以对普通文件进行操作。
一个基于Linux内核的没有缓存的IO机制
特性:
.1 没有缓存区
.2 操作对象不在是流,而是文件描述符
.3文件描述符
很小的非负的整数 int 0-1023
内核每打开一个文件就会获得一个文件 描述符
unistd.h ===>POSIX 标准库
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
1.open
open("1.c",O_WRONLY|O_CREAT,0666 );
int open(const char *pathname, int flags,int mode);
O_RDONLY O_WRONLY O_RDWR O_CREAT O_TRUNC
只读 只写 读写 创建 清空
返回值: 成功返回文件描述符 失败返回-1
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd= open("1.txt",O_WRONLY | O_CREAT|O_TRUNC,0666);//truncate
if(-1 == fd)
{
printf("open error\n");
return 1;
}
printf("fd is %d\n",fd);
return 0;
}
2.read
功能:通过文件描述符读取文件中的数据
参数:fd:文件描述符 buf:存放数据空间的首地址 count:要读到数据的个数
返回值: 成功返回读到数据的个数 失败返回-1 读到文件结尾返回0
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd= open("1.txt",O_RDONLY);//truncate
if(-1 == fd)
{
printf("open error\n");
return 1;
}
printf("fd is %d\n",fd);
char buf[512]={0};
int rd_ret = read(fd,buf,sizeof(buf));
if(rd_ret<=0)
{
printf("read eof or error\n");
return 1;
}
printf("ret %d,%s\n",rd_ret,buf);
close(fd);
return 0;
}
3.write
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.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);//truncate
if(-1 == fd)
{
printf("open error\n");
return 1;
}
printf("fd is %d\n",fd);
char buf[128]="hello,world";
int wr_ret = write(fd,buf,strlen(buf));
if(-1 == wr_ret)
{
printf("write error\n");
return 1;
}
close(fd);
return 0;
}
功能:通过文件描述符向文件中写一串数据
参数: fd:文件描述符 buf:要写入文件的字符串的首地址 count:要写入字符的个数
返回值: 成功返回实际写入的个数, 失败返回-1
4.close
5.lseek
功能:定位光标的位置
参数:fd:文件描述符 offset:偏移量 正:向后偏移 负:向前偏移 零:不偏移
whence:
SEEK_SET
SEEK_CUR
SEEK_END
返回值: 成功返回偏移量 失败返回-1
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd= open("1.txt",O_WRONLY);//truncate
if(-1 == fd)
{
printf("open error\n");
return 1;
}
printf("fd is %d\n",fd);
off_t offset = lseek(fd,6, SEEK_SET);
printf("offset %ld\n",offset);
write(fd,"china",5);
close(fd);
return 0;
}
-
四、文件IO和标准IO的区别
- 文件I/O遵循POSIX标准,只能在遵循POSIX标准的类UNIX环境下使用;标准I/O遵循ANSI标准,只要重新编译即可在不同的环境中运行。
- 文件I/O属于系统调用,可移植性差;标准I/O属于C库,可以在不同的操作系统下移植。
- 标准I/O函数接口在对文件进行操作时,首先操作缓存区,等待缓存区满足一定的条件时,然后再去执行系统调用,真正实现对文件的操作。而文件I/O不操作任何缓存区,直接执行系统调用。
- 使用标准I/O可以减少系统调用的次数,提高系统效率。
- 文件I/O主要针对文件操作,读写硬盘等;标准I/O主要是打印输出到屏幕等,因为它们设备不同,文件I/O针对的是文件,标准I/O是对控制台,操作的是字符流。