标准io的概念
1975 Dennis r IO库,C语言的标准,ANSI c
IO 即input output
I: 键盘是标准输入设备 ====》默认输入就是指键盘 /dev/input
O: 显示器是标准输出设备 ==》默认输出就是指显示器
Linux操作系统当中IO都是对文件的操作
C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
标准IO在UNIX上是对文件IO的封装
文件基本操作
文件操作步骤
1,打开文件 FILE
2,io操作,,读写操作
3,关闭文件
1, fopen
2, 读写操作相关,
fgetc/fputc单个字符
fgets/fputs一次一行
fread/fwrite二进制的操作
3,fclose
fopen函数
FILE *fopen(const char *path, const char *mode);
1.功能:
打开一个文件并建立一个流
2.参数:
path:要打开文件的路径
mode:
r 只读,文件不存在就报错;文件存在则只读打开
r+ 读写,文件不存在报错; 文件存在则读写打开
w 只写,文件不存在则创建,文件存在则清0只写打开
w+ 写读, 文件不存在则创建;文件存在则清0写读打开
a 追加可写,文件不存在则创建 ;文件存在则追加只写打开 ,定位到文件最后增加内容。
a+ 追加读写 ,文件不存在则创建 ;文件存在则追加读写打开
3.返回值:
成功返回建立的文件流指针
失败返回NULL
使用:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("1.txt","w");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
// fputc();
// fclose();
return 0;
}
fputc
int fputc(int c, FILE *stream);
1.功能:
向流中写入一个字符
2.参数:
c:要写入的字符
stream:文件流指针
3.返回值:
成功返回写入的字符ASCII码值
失败返回EOF
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("1.txt","w");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
int ret = fputc('h',fp);
if(-1 == ret)
{
printf("fputc error\n");
return 1;
}
fputc('e',fp);
fputc('l',fp);
fputc('l',fp);
fputc('o',fp);
fclose(fp);
return 0;
}
fgetc
int fgetc(FILE *stream);
1.功能:
从流中读取一个字符
2.参数:
stream:文件流指针
3.返回值:
成功返回读到字符的ASCII码值
读到文件末尾返回EOF
失败返回EOF -1
c= fgetc(stdin);
fputc(c,stdout);
获取键盘上面的输入,显示到屏幕
用法:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("1.txt","r");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
while(1)
{
int c = fgetc(fp);
if(EOF == c)
{
break;
}
printf("%c\n",c);
}
fclose(fp);
return 0;
}
fgets
char *fgets(char *s, int size, FILE *stream);
1.功能:
从stream流对象关联的文件中获取size大小字节的文本数据,并存储到s对应的本地内存(栈区数组,堆区内存)
2.参数:
s 要存储数据的本地内存
size 要获取的数据长度,单位字节。
stream 要获取的目标文件流对象,
可以是stdin ,程序会阻塞等待
如果是普通文件fp 则指向文件第一行数据
3.返回值:
成功 返回指向有效数据的首地址,一般等于s的地址
失败 或者 文件末尾 NULL;
用法:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("/etc/passwd","r");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
char buf[1024]={0};// 1k-4k
while(1)
{
char* s = fgets(buf,sizeof(buf),fp);
if(NULL == s)
{
break;
}
printf("%s\n",buf);
}
fclose(fp);
return 0;
}
fputs
int fputs(const char *s, FILE *stream);
1.功能:
从s所在的本地内存中获取一行数据,并写入stream对应的文件流对象。
2.参数:
s 要写的信息,一般是固定的字符串或者有数据的数组。
stream 要写入的目标文件流对象
3.返回值:
成功 nonnegative number on success
失败 -1;
用法:
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE * fp = fopen("1.txt","w");
if(NULL == fp)
{
printf("fopen error\n");
return 1;
}
char data[]="hello,world";
int ret = fputs(data,fp);
if(EOF == ret)
{
printf("fputs error\n");
return 1;
}
fclose(fp);
return 0;
}
fread和fwrite
fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
1.功能:
从指定的stream流对象中获取nmemeb个大小为size字节的数据块到ptr
所在的本地内存中。
2.参数:
ptr 要存储数据的本地内存一般是数组或者结构体指针
size 单个数据块的元数据大小。最小单元的大小
nmemb 要获取的数据块的个数,拷贝的数据块个数。
stream 要获取数据的源文件流对象,如果是stdin表示从
键盘获取数据,如果是fp文件则表示从普通文件获取。
3.返回值:
成功 小于等于nemeb的整数,表示获取的数据长度
失败 小于0,结尾 0;
fwrite
size_t fwrite(const void *ptr, size_t size,size_t nmemb, FILE *stream);
1.功能:
从ptr所在本地内存中取出nmemb个大小为size的数据块写入到stream流对应的文件流对象中。
2.参数:
ptr 要写的数据块地址,一般是数组或者结构体指针
size 要写的数据块元数据大小,单位是字节
nmemb 要写的数据块的个数
stream 要写的目标文件流对象。如果是stdout则表示数据会
写到终端屏幕显示,如果是fp的普通文件则会写入到文件中。
3.返回值:
成功 小于等于nmemb 的个数。
失败 <0
用法:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char name[50];
int age;
char phone[15];
}PER;
int main(int argc, char *argv[])
{
FILE * src_fp = fopen("/home/linux/1.png","r");
FILE* dst_fp = fopen("2.png","w");
if(NULL == src_fp ||NULL == dst_fp)
{
printf("fopen error\n");
return 1;
}
int size = 160743;// 1024*1024*1024
char *p = (char* )malloc(size);// 32bit 2.9G 64bit 256T +256T
fread(p,size,1,src_fp);
fwrite(p,size,1,dst_fp);
fclose(dst_fp);
fclose(src_fp);
free(p);
return 0;
}
操作判断
ferror ():检测一个流是否出错
clearerr():void clearerr(FILE *stream); 清除一个流出错的标记
feof():检测是否到达文件结尾
feof() 函数判断
nt feof(FILE *stream);
1.功能:
判断当前参数stream的文件流指针是否到达文件结尾。
如果到达文件结尾则返回真,否则返回假
注意:该操作一定要在一次IO操作之后判断。
2.参数:
stream 要判断结尾的文件流对象
3.返回值:
成功到达结尾是 真
否则 是假
用法:
if (feof(fp)) {
printf("到达文件末尾!\n");
} else {
printf("未到达文件末尾!\n");
}
if (ferror(fp)) {
printf("出错!\n");
clearerr(fp);
} else {
printf("未出错!\n");
}
while(fgets(buf,1024,src))
{
}
//EOF
if(feof(src))
{
break;
}
if(ferror(src))
{
clearerr(src);
}
文件定位:
fseek(重点)
int fseek(FILE *stream, long offset, int whence);
1.功能:
将stream流文件中的文件指针从whence位置开始,偏移offset字节的长度。
offset偏移量,whence参考点。
2.参数:
stream 要移动文件指针的目标文件流对象。注意:不支持设备文件,一般用于普通文件。
offset 要在文件内偏移的距离,单位字节。如果值为正数,则向文件末尾偏移,如果值为负数,则向文件开头偏移。
whence 偏移的起始位置,由系统定义的三个宏
SEEK_SET 文件的开头位置
SEEK_CUR 文件的当前位置
SEEK_END 文件的末尾位置
3.返回值:
成功: 返回 0
失败: -1;
用法:
#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;
}
ftell
long ftell(FILE *stream);rewind(fp);
1.功能:
获取当前文件流指针的具体位置,一般以文件开头到当前指针的字节数为返回值。可以用来求文件大小
2.参数:
stream 要返回指针距离的文件流对象
3.返回值:
成功 返回获取到的距离长度,单位是字节;失败 返回-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;
}
rewind()
等效于:fseek(stream,0L,SEEK_SET);功能是回到文件开头
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE* fp = fopen("./01fopen.c","r");
if(NULL == fp)
{
return 1;
}
fseek(fp,0,SEEK_END);
long size = ftell(fp);
printf("size is %ld\n",size);
rewind(fp);
char buf[512]={0};
if(fgets(buf,sizeof(buf),fp))
{
printf("buf is %s\n",buf);
}
else
{
printf("end of file\n");
}
fclose(fp);
return 0;
}
标准io缓冲区
要求掌握fflush函数
stdin标准输入
stdout标准输出
stderr标准错误输出,一般用在程序出现错误时。打印错误信息
行缓冲
1k, terminal,主要用于人机交互stdout。行缓存多是关于终端的一些操作
刷新条件:
1.遇到\n刷新
2.缓存区满刷新,缓存区满(1024个字节)
3.程序正常结束刷新
4.fflush函数刷新 fflush(stdout);
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
//不满足任意条件
/* 1
printf("hello");
while(1)
sleep(1);
*/
//缓存区满刷新
/* 2
int i=0;
for(i=0;i<1025;i++)
{
//printf("a");
fputc('a',stdout);// stdin stdout stderr
}
while(1)
sleep(1);
*/
//程序结束刷新
/*3
printf("hello");
*/
//fflush刷新
printf("hello");
fflush(stdout);
while(1)
sleep(1);
return 0;
}
全缓冲
4k,主要用于文件的读写 ,对普通文件进行标准IO操作,建立的缓存一般为全缓存
刷新条件:
1.缓存区满刷新,缓存区满刷新,缓存区 4096
2.程序结束刷新,正常结束。
3.fflush来刷新 fflush(fp);
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
// 不刷新
/* 1
printf("hello");
while(1)
sleep(1);
*/
//缓存区满刷新
/* 2
int i=0;
for(i=0;i<1025;i++)
{
//printf("a");
fputc('a',stdout);// stdin stdout stderr
}
while(1)
sleep(1);
*/
//程序结束刷新
/*3
printf("hello");
*/
//fflush刷新
printf("hello");
fflush(stdout);
while(1)
sleep(1);
return 0;
}
无缓冲
0k 主要用于出错处理信息的输出 stderr
不对数据缓存直接刷新
printf();==>>stdout
fprintf(strerr,"fopen error %s",filename);
fprintf可以指定输出
两个重要的应用:
1.fputc/fgetc完成文件复制
#include <stdio.h>
// ./a.out 4 5 56 7 8
int main(int argc, char *argv[])
{
if(argc<3)
{
printf("usage:./a.out srcfile dstfile\n");
return 1;
}
FILE *src = fopen(argv[1],"r");
FILE * dst= fopen(argv[2],"w");
if(NULL == src || NULL == dst )
{
printf("fopen error\n");
return 1;
}
while(1)
{
int c = fgetc(src);
if(EOF== c)
{
break;
}
fputc(c,dst);
}
fclose(dst);
fclose(src);
return 0;
}
2.fputs/fgets完成文件复制
#include <stdio.h>
int main(int argc, const char *argv[])
{
if (argc < 3)
{
printf("usage ./a.out srcfile desfile\n");
return 1;
}
FILE *src = fopen(argv[1],"r");
FILE *dst = fopen(argv[2],"w");
if (NULL == src || NULL == dst)
{
printf("fopen error\n");
return 1;
}
char buf[1024] = {0};
while (1)
{
char *s = fgets(buf,sizeof(buf),src);
if (NULL == s)
break;
fputs(buf,dst);
}
fclose(dst);
fclose(src);
return 0;
}
标签:fp,文件,stream,int,stdio,printf,char,io,Linux
From: https://blog.csdn.net/haobe/article/details/141154757