标准IO是指在C库中提供的一组专门用于输入输出的函数
2.特点:不仅在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强制刷新
练习:测试标准输出缓存区的大小 #include【3】打开文件: 1.FILE *fopen#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); return 0; }
FILE *fopen(const char *path, const char *mode);
功能:打开文件
参数:path:文件路径
mode:打开文件的方式
r:只读,文件不存在,会报错
r+:可读可写,文件不存在,会报错
w:只写,文件不存在创建,文件存在清空
w+:可读可写,文件不存在创建,文件存在清空
a:追加(可写),文件不存在创建,存在追加
a+:可读可写,文件不存在创建,存在追加
注:以"a"开头的附加模式下打开后续对该流操作总会写入文件末尾。
返回值:成功:返回文件流指针
失败:NULL
关闭文件:
int fclose(FILE *fp);
练习:使用读写并且不存在创建存在清空权限,打开一个文件,然后关闭这个文件。
#include2.FILE *freopen#include #include int main(int argc, char *argv[]) { FILE *fp; fp = fopen("E:\Code\IOProcess\1\test.txt","w+"); if(fp == NULL) { printf("fopen errn"); return -1; } fclose(fp); return 0; }
FILE *freopen(const char *pathname, const char mode, FILE fp)
功能:将指定的文件流指针重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同上)
fp:文件流指针
返回值:成功:返回文件流指针
失败:NULL
练习:打开一个文件并将标准输出重定向到这个文件,使用printf("hello worldn");来验证
#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 worldn");
fclose(fp);
return 0;
}
练习2:测试一个进程最多可以打开多少个文件? #include【4】每次一个字符的读写: 1.int fgetc#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("%pn", 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【5】每次一行的IO: 1.char *fgets#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 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个字符是’ ’
存放在s所指的空间
参数:s 读到数据的存放位置
size 一次期望读到的数据,若遇到’n’会直接返回
stream 流
返回值:成功返回s的地址
失败或读到文件结尾:NULL
int fputs(const char *s, FILE *stream);
功能:向指定的文件流中写入一串字符
参数:s:要写入的字符内容
stream 流
返回值: 成功 实际写入的数据的个数
失败 EOF
注意:
fgets最多可以读size - 1个,最后一个字符必须是’ ’字符
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【6】直接IO(二进制IO) 1.size_t fread#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("%sn",buf); if(strcmp(buf,"quitn")==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【7】文件的偏移: 1.int fseek#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("%sn",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个字节单位,并且写入一个字符 #includeint 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; }



