标准IO是指在C库中提供的一组专门用于输入输出的函数
不仅在UNIX系统,在很多操作系统上都实现了标准I/O库
标准I/O库由ANSI C标准说明
标准I/O通过缓冲机制减少系统调用,实现更高效率
标准I/O在系统调用函数基础上构造的,它便于用户使用
标准IO默认打开了三个流:stdin、stdout、stderr
定义:所有的I/O操作仅是简单的从程序移进或者移出,
这种字节流,就称为流
每个被使用的文件都在内存中开辟一个区域,用来存放文件
的有关信息,这些信息是保存在一个结构体类型的变量中,
该结构体类型是由系统定义的,取名为FILE。
标准I/O库的所有操作都是围绕流(stream)来进行的,
在标准I/O中,流用FILE *来描述。
使用vi -t FILE
vi -t FILE —> ctrl+](追朔源码定义)–>struct _IO_FILE
ctrl+t:回退上一次定义
刷新缓存区的条件:
1)程序正常退出
2)缓存区满刷新
3)fflush强制刷新
fflush( FILE* 流指针);
刷新缓存区的条件:
1)\n刷新
2)程序正常退出
3)缓存区满刷新
4)fflush强制刷新
练习:测试标准输出缓存区的大小
/**
** Created by 24122 on 2022/4/28.
**/
#include
#include
#include
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < 256; i++){
if (i < 10)
{
printf("000%d", i);
}
else if (i >= 10 && i < 100)
{
printf("00%d", i);
}
else if (i >= 100)
{
printf("0%d", i);
}
}
while (1);
/*标准输入(stdin) 标准输出(stdout) 标准出错(stderr)
int len;
printf("hello world!\n");
len = stdout->_IO_buf_end-stdout->_IO_buf_base;
printf("len:%d\n", len);
*/
return 0;
}
FILE *fopen(const char *path, const char *mode);
功能:打开文件
参数:path:文件路径
mode:打开文件的方式
r:只读,文件不存在,会报错
r+:可读可写,文件不存在,会报错
w:只写,文件不存在创建,文件存在清空
w+:可读可写,文件不存在创建,文件存在清空
a:追加(可写),文件不存在创建,存在追加
a+:可读可写,文件不存在创建,存在追加
注:以"a"开头的附加模式下打开后续对该流操作总会写入文件末尾。
返回值:成功:返回文件流指针
失败:NULL
关闭文件:
int fclose(FILE *fp);
/**
** Created by 24122 on 2022/4/28.
**/
练习:使用读写并且不存在创建存在清空权限,打开一个文件,然后关闭这个文件。
#include
#include
#include
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("E:\\Code\\IOProcess\\1\\test.txt","w+");
if(fp == NULL)
{
printf("fopen err\n");
return -1;
}
fclose(fp);
return 0;
}
FILE *freopen(const char *pathname, const char mode, FILE fp)
功能:将指定的文件流指针重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同上)
fp:文件流指针
返回值:成功:返回文件流指针
失败:NULL
练习:打开一个文件并将标准输出重定向到这个文件,使用printf("hello world\n");来验证
/**
** Created by 24122 on 2022/4/28.
**/
#include
int main(int argc, char *argv[])
{
freopen("E:\\Code\\IOProcess\\1\\test.txt","w",stdout);
printf("hello world!\n");
return 0;
}
补充:
void perror(const char *s);
功能:当你调用“某些”函数出错时,会将参数 s 所指的字符串和错误的原因输出到标准设备。
char *strerror(int errnum);
功能:根据错误号返回错误原因字符串
参数:errnum:errno号
int fprintf(FILE *stream, const char *format, ...);
功能:向指定的流中输出数据
参数:
stream:指定的文件流
const char *format, ...:向流输入的内容
返回值:
成功返回向文件流输入内容的字符个数
失败返回0
练习1:指定一个文件,向这个文件输入hello world.
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("./test.txt","w");
if(fp == NULL)
{
perror("fopen err");
return -1;
}
fprintf(fp,"hello world\n");
fclose(fp);
return 0;
}
练习2:测试一个进程最多可以打开多少个文件?
#include
#include
#include
int main(int argc, char *argv[])
{
FILE *fp;
int num = 0;
while (1)
{
fp = fopen("./test.txt","r");
if(fp == NULL)
{
break;
}
num++;
}
printf("num:%d",num);
//printf("%p\n", fp);
//fclose(fp);
return 0;
}
int fgetc(FILE *stream);
功能:每次一个字符的读
参数:stream:文件流指针
返回值:成功:读到字符的ASCII
失败或文件结尾:EOF(-1)
int fputc(int c, FILE *stream);
功能:向指定的文件中写一个字符
参数:c 要写的字符
stream 要写到的流
返回值:成功:写入的字符;
失败:EOF
练习:用fgetc和fputc实现cat的功能,从命令行输入文件名.
#include
#include
#include
int main(int argc, char *argv[])
{
FILE *fp1,*fp2;
//读取的文件
fp1 = fopen(argv[1],"r");
if(fp1 ==NULL)
{
perror("fopen err!\n");
return -1;
}
fp2 = fopen(argv[2], "w");
//实现cp
/* if(fp2 ==NULL)
{
perror("fopen2 err!\n");
return -1;
}*/
char temp;
while ((temp= fgetc(fp1))!=EOF)
{
//fputc(temp, fp2);//实现cp
fputc(temp, stdout);//实现cat
}
fclose(fp1);
//fclose(fp2);
return 0;
}
char *fgets(char *s, int size, FILE *stream);
功能:从指定的流中读取最多size-1个字符,第size个字符是’\0’
存放在s所指的空间
参数:s 读到数据的存放位置
size 一次期望读到的数据,若遇到’\n’会直接返回
stream 流
返回值:成功返回s的地址
失败或读到文件结尾:NULL
int fputs(const char *s, FILE *stream);
功能:向指定的文件流中写入一串字符
参数:s:要写入的字符内容
stream 流
返回值: 成功 实际写入的数据的个数
失败 EOF
注意:
fgets最多可以读size - 1个,最后一个字符必须是’\0’字符
fgets函数是每次读一行的函数,遇到’\n’字符返回
//练习1:用fgets实现wc –l的功能,文件名从命令行输入
#include
#include
#include
int main(int argc, char *argv[])
{
int line =0;
char buf[32];
FILE *fp = fopen(argv[1],"r");
if(fp ==NULL)
{
perror("fopen error!\n");
return -1;
}
while (fgets(buf,sizeof (buf)-1,fp) != NULL)
{
if(buf[strlen(buf) - 1 ] == '\n')
{
line++;
}
}
printf("%d %s", line, argv[1]);
fclose(fp);
return 0;
}
//练习2:用fgets和fputs实现cp的功能,两个文件名从命令行输入
#include
#include
#include
int main(int argc, char *argv[])
{
FILE *fp1,*fp2;
char buf[32];
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2],"w");
if(fp1 == NULL ||fp2 ==NULL)
{
perror("fopen error!\n");
return -1;
}
while (fgets(buf,32,fp1) != NULL)
{
fputs(buf, fp2);
}
printf("cp complete!\n");
fclose(fp1);
fclose(fp2);
return 0;
}
练习3:使用fgets从终端输入字符串,将此字符串写入指定文件里,当输入"quit"退出.
#include
#include
int main(int argc,char *argv[])
{
FILE *file1,file2;
char buf[32] = {0};
file1 = fopen(argv[1], "w");
if(file1 ==NULL)
{
perror("fopen err");
return -1;
}
while (1)
{
if(fgets(buf,sizeof (buf),stdin) == NULL)
{
perror("fgets err");
return -1;
}
//printf("%s\n",buf);
if(strcmp(buf,"quit\n")==0)
{
break;
}
/*if(strncmp(buf,"quit\n",4)==0)
{
break;
}*/
fputs(buf,file1);
}
fclose(file1);
return 0;
}
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);//从流里读
功能:从文件流读取多个元素
参数: ptr :用来存放读取元素的地址
size :元素大小 sizeof(数据类型)
nmemb :读取元素的个数
stream :要读取的文件
返回值:成功:读取的元素的个数;读到文件尾: 0
失败: -1
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);//往流里写
功能:按对象写
参数:同上
返回值:成功:写的元素个数
失败 :-1
注意:
两个函数的返回值为:读或写的对象数
对于二进制数据我们更愿意一次读或写整个结构
//练习1:从一个文件中读取数据然后将数据往另外一个文件里去写
#include
#include
int main(int argc,char *argv[])
{
FILE *fp1,*fp2;
char buf ={0};
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2], "w");
if(fp1 == NULL)
{
perror("fopen err");
return -1;
}
if(fread(buf,sizeof (char ),32,fp1) < 0)
{
perror("fread err");
return -1;
}
if(fwrite(buf,sizeof (char ),strlen(buf),fp2) < 0)
{
perror("fwrite err");
return -1;
}
printf("%s\n",buf);
return 0;
}
int fseek(FILE *stream, long offset, int whence);
功能:设定stream流的文件位置
参数: stream 要偏移的流指针
offset 偏移量
正数:向文件结尾位置移动 负数:向文件开始位置
whence 相对位置
SEEK_SET 开始位置
SEEK_CUR 当前位置
SEEK_END 结尾位置
返回值:成功:0 失败:-1
long ftell(FILE *stream);
功能:取得当前的文件位置
参数:要检测的流
返回值:当前的文件位置,出错则为-1L
void rewind(FILE *stream);
功能:设定流的文件位置指示为文件开始
注意:rewind(fp)的功能和fseek(fp, 0, SEEK_SET)的功能相同
//练习:将指定文件的光标向后移动10个字节单位,并且写入一个字符
#include
int main(int argc,char *argv[])
{
FILE *fp;
fp = fopen(argv[1], "w");
if(fp ==NULL)
{
perror("fopen err");
return -1;
}
fseek(fp, 10, SEEK_SET);
fputc('a', fp);
fclose(fp);
return 0;
}