标准IO:库函数
- 一、基本概念
- 1.文件类型
- 2.标准I/O介绍
- 3.流的概念
- 4.文本流和二进制流
- 5.流的缓冲类型
- 6.标准I/O流(stdin、stdout、stderr)
- 二、标准I/O函数
- 1.fopen、fclose、errrno、strerror、perror(打开、关闭文件,输出错误码信息)
- 2.fgetc、fputc、getchar、putchar(读写一个字符)
- 3.fgets、fputs、gets、puts(读写一行)
- 4.fread、fwrite(读写若干个对象)
- 5.feof、ferror(判断文件是否结束或出错)
- 6.sprintf、snprintf、fprintf(格式化输出到内存、文件)
- 7.time、localtime(获取系统时间,将系统时间转为本地时间)
- 8.fflush(刷新缓冲区)
- 9.fseek、rewind、ftell(定位文件指针)
- 10.freopen(重定向输入输出流)
- 三、示例代码
- 1.fgetc(统计文本文件字符数)
- 2.fputc(将a~z写入文件)
- 3.fgets(标准输入流写入buff)
- 4.fputs(将内存数据输出到标准输出流)
- 5.fread、fwrite(二进制文件读写)
- 6.fflush(刷新流,刷新缓冲区)
- 7.ftell、fseek、rewind(定位流指针)
- 8.fprintf、sprintf(格式化输出数据到文件、内存,常用sprintf)
- 9.fscanf、sscanf(将文件、内存数据格式化输入,可用作解析字符串)
- 四、案例源码
- 1.复制文件1
- 2.统计文本文件行数
- 3.复制文件2
- 4.获取文件长度
- 5.按指定格式打印时间
一、基本概念
1.文件类型
概念:一组相关数据的有序集合
文件类型:
- 常规文件 r
- 目录文件 d
- 字符设备文件 c
- 块设备文件 b
- 管道文件 p
- 套接字文件 s
- 符号链接文件 l
2.标准I/O介绍
标志I/O由ANSI C标准定义,主流操作系统上都实现了C库
标准I/O通过缓冲机制减少系统调用,实现更高的效率
3.流的概念
FILE:
标准I/O用一个结构体类型来存放打开的文件的相关信息
标准I/O的所有操作都是围绕FILEl来进行
流(stream):
FILE又被称为流(stream)
文本流/二进制流
4.文本流和二进制流
windows
二进制流:换行符 <—> ‘\n’
文本流:换行符 <—> ‘\r’‘\n’
Liniux
换行符 <—> ‘\n’
5.流的缓冲类型
全缓冲
当流的缓冲区无数据或无空间时才执行实际I/O操作
行缓冲
当输入和输出中遇到换行符(‘\n’)时,进行I/O操作
当流和一个终端关联时,典型的行缓冲
无缓冲
数据直接写入文件,流不进行缓冲
6.标准I/O流(stdin、stdout、stderr)
标准I/O预定义3个流,程序运行时自动打开
标准输入流 | 0 | STDIN_FILENO | stdin |
标准输出流 | 1 | STDOUT_FILENO | stdout |
标准错误流 | 2 | STDERR_FILENO | stderr |
二、标准I/O函数
1.fopen、fclose、errrno、strerror、perror(打开、关闭文件,输出错误码信息)
FILE *fopen(const char *pathname, const char *mode);
功能:打开文件(标准IO)
参数:@pathname:想要打开文件的路径及名字 "./hello.txt" "/home/linux/1.c"@mode:打开文件的方式 "a" "a+" "w" "w+" "r" "r+"r 以只读的方式打开文件,将光标定位到文件的开头r+ 以读写的方式打开文件,将光标定位到文件的开头w 以只写方式打开文件,如果文件存在就清空,如果文件不存在就创建,将光标定位到开头w+ 以读写方式打开文件,如果文件存在就清空,如果文件不存在就创建,将光标定位到开头a 以追加的方式打开文件,如果文件不存在就创建,如果文件存在不会清空,将光标定位到结尾a+ 以读和追加的方式打开文件,如果文件不存在就创建,读光标在开头,写光标在结尾(光标就一个)
返回值:成功返回文件指针,失败返回NULL,置位错误码errno
int fclose(FILE *stream);
功能:关闭文件
参数:@stream:文件指针返回值:成功返回0,失败返回EOF(-1),置位错误码 //#define EOF (-1)
#include <errno.h>
extern int errno;
errno 存放错误码
#include <string.h>
char *strerror(int errnum);
功能:将错误码转换为错误信息
参数:@errnum:错误码
返回值:错误信息的字符串
void perror(const char *s);
功能:打印错误信息
参数:@s:用户的附加信息
返回值:无
2.fgetc、fputc、getchar、putchar(读写一个字符)
int fgetc(FILE *stream);
功能:从文件中读取一个字符(光标自动向后移动)
参数:@stream:文件指针
返回值:成功返回读取到的字符的ASCII,读取到结尾或者遇到错误就返回EOF
int fputc(int c, FILE *stream);
功能:向文件中写入一个字符(光标自动向后移动)
参数:@c:字符的ascii的值 ‘c’ 65@stream:文件指针
返回值:成功返回读取到的字符的ASCII,失败返回EOF
int getchar(void);
getchar()等同于fgetc(stdin)
int putchar(int c);
putchar(c)等同于fputc(ch, stdout)
3.fgets、fputs、gets、puts(读写一行)
char *fgets(char *s, int size, FILE *stream);
功能:从文件中向s指向的内存中读取字符串,最多读size-1个字符(最后一个用于存‘\0’)。fgets遇到EOF或者换行符的时候就会停止,如果遇到换行符停止的,换行符也会被存储到s中。
参数:@s:指向存储字符的首地址@size:想要读取字符的个数@stream:文件指针
返回值:成功返回s,失败返回NULL
int fputs(const char *s, FILE *stream);
功能:将s中的字符串写入到文件中
参数:@s:被写字符串的首地址@steam:文件指针
返回值:成功返回大于0的值,失败返回EOF
char *gets(char *s);
功能:gets从标准输入stdin读字符串到s
返回值:成功返回时s,遇到'\n'或已输入size-1个字符时返回,总是包含'\0',到文件末尾或出错返回NULL
gets不推荐使用,容易造成缓冲区溢出
int puts(const char *s);
功能:puts将缓冲区s中的字符串输出到stdout,并追加'\n'
返回值:成功时返回输出的字符个数,失败返回EOF
4.fread、fwrite(读写若干个对象)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从stream中读取nmemb项数据,每一项的大小是size,将它们存到ptr
参数:@ptr:存储读取到数据的首地址@size:每一项的大小@nmemb:项目的个数@stream:文件指针
返回值:成功返回读取到的项目的个数,如果小于项目的个数就是错误或者到文件的结尾了。
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:将ptr中的数据写入到stream中,写nmemb向,每一项的大小是size
参数:@ptr:被写数据的首地址@size:每一项的大小@nmemb:项目的个数@stream:文件指针
返回值:成功返回项目的个数,失败返回小于项目的个数。
5.feof、ferror(判断文件是否结束或出错)
fread返回值无法区分是到达了文件的结尾还是错误发生了,调用者必须通过feof或者ferror函数来判断。
int feof(FILE *stream);
功能:判断是否读取到了文件的结尾,如果到了文件的结尾将返回真
参数:@stream:文件指针
返回值:如果到了文件的结尾返回真,如果没有到文件结尾返回假int ferror(FILE *stream);
功能:如果在读文件的时候发生了错误,这个函数返回真
参数:@stream:文件指针
返回值:如果发生了错误返回真,如果没有发生错误返回假
6.sprintf、snprintf、fprintf(格式化输出到内存、文件)
int sprintf(char *str, const char *format, ...);
功能:将format控制格式的内容写到str对应的内存中(不会向终端显示)
参数:@str:内存地址@format:和printf的参数完全相同
返回值:成功返回格式化的字符的个数,失败返回负数
int snprintf(char *str, size_t size, const char *format, ...);
功能:将format控制格式的内容写到str对应的内存中(不会向终端显示)
参数:@str:内存地址@size:最多格式化size个字符,其中还包括一个'\0'@format:和printf的参数完全相同
返回值:成功返回格式化的字符的个数,失败返回负数
int fprintf(FILE *stream, const char *format, ...);
功能:将控制格式格式化的字符串写入到文件中
参数:@stream:文件指针@format:控制格式
返回值:成功返回格式化的字符的个数,失败返回负数
7.time、localtime(获取系统时间,将系统时间转为本地时间)
#include <time.h>
time_t time(time_t *tloc);
功能:获取自1970-01-01 00:00:00到当前的秒钟数
参数:@tloc:NULL
返回值:成功返回秒钟数,失败返回-1,并置位错误码
struct tm *localtime(const time_t *timep);
功能:将time_t的秒钟转换为tm的结构体(结构体中包含年、月、日...)
参数:@timep:秒钟变量的地址
返回值:成功返回tm结构体指针,失败返回NULL,并置位错误码struct tm {int tm_sec; /* Seconds (0-60) */int tm_min; /* Minutes (0-59) */int tm_hour; /* Hours (0-23) */int tm_mday; /* Day of the month (1-31) */int tm_mon; /* Month (0-11) */ //+1int tm_year; /* Year - 1900 */ //+1900int tm_wday; /* Day of the week (0-6, Sunday = 0) */ //周几int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ //这一年中的第几天int tm_isdst; /* Daylight saving time */ //夏令时};
8.fflush(刷新缓冲区)
int fflush(FILE *fp);
功能:将流缓冲区里的数据写入到实际的文件,Linux下只能刷新输出缓冲区
参数:@fp:文件指针
返回值:成功返回0,失败返回EOF
9.fseek、rewind、ftell(定位文件指针)
int fseek(FILE *stream, long offset, int whence);
功能:设置光标的位置
参数:@stream:文件指针@offset:光标的偏移>0 向后偏移=0 不偏移<0 向前偏移@whence:从那个位置偏移SEEK_SET //从开头开始偏移SEEK_CUR //从当前位置偏移SEEK_END //从结尾的位置偏移
返回值:成功返回0,失败返回-1置位错误码 eg:fseek(fp,0,SEEK_END); //将光标定位到文件的结尾fseek(fp,50,SEEK_SET);//将光标定位到第50个字节的位置fseek(fp,-5,SEEK_CUR);//将光标从当前位置向前偏移5个字节1. 文件a模式打开时,函数fseek无效2. rewind(fp)相当于fseek(fp, 0, SEEK_SET)3. 这3个函数只适用于2G以下的文件
void rewind(FILE *stream);
功能:将光标恢复到文件的开头(rewind = fseek(stream, 0, SEEK_SET))
参数:@stream:文件指针
返回值:无
long ftell(FILE *stream);
功能:返回光标到文件开头的字节数
参数:@stream:文件指针
返回值:成功返回字节数,失败返回-1置位错误码
10.freopen(重定向输入输出流)
#include <stdio.h>int main(int argc, const char **argv)
{if (freopen("1.txt", "w", stdout) == NULL) {perror("freopen");return -1;}printf("stdout --> 1.txt\n");fclose(stdout);printf("end!\n");return 0;
}
三、示例代码
1.fgetc(统计文本文件字符数)
#include <stdio.h>int main(int argc, const char **argv)
{int ch;FILE *fp;int count = 0;if (argc < 2) {printf("Usage: %s <file>\n", argv[0]);return -1;}//1ch = fgetc(stdin);if (ch == EOF) {perror("fgetc");return -1;}printf("ch is %c\n", ch);//2if ((fp = fopen(argv[1], "r")) == NULL) {perror("fopen");return -1;}while ((ch = fgetc(fp)) != EOF) {count++;}printf("%s total %d bytes!\n", argv[1], count);fclose(fp);return 0;
}
2.fputc(将a~z写入文件)
#include <stdio.h>int main(int argc, const char **argv)
{int ch;int ret;FILE *fp;if (argc < 2) {printf("Usage: %s <file>\n", argv[0]);return -1;}//1ret = fputc('a', stdout);if (ret == EOF) {perror("fputc");return -1;}putchar('\n');//2if ((fp = fopen(argv[1], "w")) == NULL) {perror("fopen");return -1;}for (ch = 'a'; ch <= 'z'; ch++) {fputc(ch, fp);}fclose(fp);return 0;
}
3.fgets(标准输入流写入buff)
#include <stdio.h>
#define N 6int main(int argc, char **argv)
{char buff[N];fgets(buff, N, stdin);printf("%s", buff);return 0;
}
4.fputs(将内存数据输出到标准输出流)
#include <stdio.h>int main(int argc, char **argv)
{puts("hello world"); //加换行char buff[] = "hello world\n"; //不加换行fputs(buff, stdout);return 0;
}
5.fread、fwrite(二进制文件读写)
#include <stdio.h>
#include <string.h>struct stu {char name[15];int age;char sex[10];
};int main(int argc, char **argv)
{ FILE *fp;struct stu s1,s2;int ret;if ((fp = fopen("1.bin", "w+")) == NULL) {perror("fopen");return -1;}strcpy(s1.name, "tanpeng");s1.age = 21;strcpy(s1.sex, "male");ret = fwrite(&s1, sizeof(s1), 1, fp);if (ret == EOF) {perror("fwrite");return -1;}fclose(fp);if ((fp = fopen("1.bin", "r+")) == NULL) {perror("fopen");return -1;}ret = fread(&s2, sizeof(s2), 1, fp);if (ret == EOF) {perror("fread");return -1;}printf("name:%s age:%d sex:%s\n", s2.name, s2.age, s2.sex); fclose(fp);return 0;
}
6.fflush(刷新流,刷新缓冲区)
#include <stdio.h>
#include <unistd.h>int main(int argc, char **argv)
{FILE *fp;int ret;if ((fp = fopen("1.bin", "a+")) == NULL) {perror("fopen");return -1;}ret = fwrite("abcdef", 6, 1, fp);if (ret == EOF) {perror("fwrite");return -1;}fflush(fp);while(1) {sleep(1);}fclose(fp);return 0;
}
7.ftell、fseek、rewind(定位流指针)
#include <stdio.h>
#include <unistd.h>int main(int argc, char **argv)
{FILE *fp;int ret;if ((fp = fopen("1.bin", "w")) == NULL) {perror("fopen");return -1;}ret = fwrite("abcdef", 6, 1, fp);if (ret == EOF) {perror("fwrite");return -1;}printf("start fp:%d\n", (int)ftell(fp));ret = fseek(fp, -4, SEEK_CUR); ret = fwrite("ss", 2, 1, fp);if (ret == EOF) {perror("fwrite");return -1;}printf("fseek fp:%d\n", (int)ftell(fp));rewind(fp); ret = fwrite("rr", 2, 1, fp);if (ret == EOF) {perror("fwrite");return -1;}printf("rewind fp:%d\n", (int)ftell(fp));fclose(fp);return 0;
}
8.fprintf、sprintf(格式化输出数据到文件、内存,常用sprintf)
#include <stdio.h>int main(int argc, char **argv)
{FILE *fp;char buff[40];int year = 2022;int month = 8;int day = 7;if ((fp = fopen("1.txt", "w+")) == NULL) {perror("fopen");return -1;}fprintf(fp, "%d-%d-%d\n", year, month, day);sprintf(buff, "%d-%d-%d", year, month, day);printf("%s\n", buff);fclose(fp);return 0;
}
9.fscanf、sscanf(将文件、内存数据格式化输入,可用作解析字符串)
#include <stdio.h>int main(int argc, char **argv)
{ FILE *fp;char buff[40];int year = 2022;int month = 8;int day = 7;int fyear,fmonth,fday;int syear,smonth,sday;//1.fscanfif ((fp = fopen("1.txt", "w+")) == NULL) {perror("fopen");return -1;}fprintf(fp, "%d-%d-%d", year, month, day);rewind(fp);fscanf(fp, "%d-%d-%d", &fyear, &fmonth, &fday);printf("after fscanf:\n");printf("%d,%d,%d\n", fyear, fmonth, fday);//2.sscanfsprintf(buff, "%d-%d-%d", year, month, day);printf("%s\n", buff);sscanf(buff, "%d-%d-%d", &syear, &smonth, &sday);printf("after sscanf:\n");printf("%d,%d,%d\n", syear, smonth, sday);fclose(fp); return 0;
}
四、案例源码
1.复制文件1
#include <stdio.h>int main(int argc, char *argv[])
{FILE *fps, *fpd;int ch;if (argc < 3) {printf("Usage : %s <src_file> <dst_file>\n", argv[0]);return -1;}if ((fps = fopen(argv[1], "r")) == NULL) {perror("fopen");return -1;}if ((fpd = fopen(argv[2], "w")) == NULL) {perror("fopen");return -1;}while ((ch = fgetc(fps)) != EOF) {fputc(ch, fpd);}fclose(fps);fclose(fpd);return 0;}
2.统计文本文件行数
#include <stdio.h>
#include <string.h>#define N 64int main(int argc, char *argv[])
{FILE *fp;int line = 0;char buf[N];if (argc < 2) {printf("Usage: %s <file>\n", argv[0]);return -1;}if ((fp = fopen(argv[1], "r")) == NULL) {printf("fopen error\n");return -1;}while (fgets(buf, N, fp) != NULL) {if (buf[strlen(buf)-1] == '\n') line++;}printf("the line of %s is %d\n", argv[1], line);return 0;}
3.复制文件2
#include <stdio.h>#define N 64int main(int argc, char *argv[])
{FILE *fps, *fpd;int buf[N];int n;if (argc < 3) {printf("Usage : %s <src_file> <dst_file>\n", argv[0]);return -1;}if ((fps = fopen(argv[1], "r")) == NULL) {perror("fopen src file");return -1;}if ((fpd = fopen(argv[2], "w")) == NULL) {perror("fopen dst file");return -1;}while ((n = fread(buf, 1, N, fps)) > 0) {fwrite(buf, 1, n, fpd);}fclose(fps);fclose(fpd);return 0;}
4.获取文件长度
#include <stdio.h>int main(int argc, char *argv[])
{FILE *fp;if ((fp = fopen("test.txt", "r+")) == NULL) {perror("fopen");return -1;}fseek(fp, 0, SEEK_END);printf("length is %ld\n", ftell(fp)); return 0;}
5.按指定格式打印时间
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <string.h>int main()
{FILE *fp;int line = 0;char buf[64];time_t t;struct tm *tp;if ((fp = fopen("test.txt", "a+")) == NULL) {perror("fopen");return -1;}while (fgets(buf, 64, fp) != NULL){if (buf[strlen(buf)-1] == '\n') line++;} while ( 1 ){time(&t);tp = localtime(&t);fprintf(fp, "%02d, %d-%02d-%02d %02d:%02d:%02d\n", ++line, tp->tm_year+1900, tp->tm_mon+1,tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);fflush(fp);sleep(1);} return 0;}