标准IO与文件IO
1 概述
- stdio 标准IO(优先使用)
- sysio 系统调用IO(文件IO)
sysio是直接实现用户态切换内核态,sysio和平台是有关系的,比如windows和linux,而stdio标准IO提供了一系列标准接口使用,不用去关心平台的限制(stdio底层是依赖sysio实现的),所以stdio的可移植性比sysio好。
2 标准IO
FILE结构体
- FILE类型贯穿始终
2.1 文件打开与关闭
-
fopen() 打开文件
//filename是要打开的文件的名称 //modes是打开文件方式:读、写 //打开文件产能共返回FILE指针,否则返回NULL,并且设置errno extern FILE *fopen (const char *__restrict __filename, const char *__restrict __modes) __wur;
modes :
- “r”,只读且当前流指针指向文件的开头(要求文件存在)
- “r+”,可读可写,且当前流指针指向文件的开头(要求文件存在)
- “w”,如果文件存在则清空文件,不存在则创建文件,同时流指针指向文件开头
- “w+”,以读写形式打开文件,文件有则清空,无则创建,同时流指针指向文件开头
- “a”,以追加写的形式打开文件,且文件不存在会创建文件,同时流指针指向文件末尾
- “a+”,以读写形式打开文件,且文件不存在会创建文件,流指针如果是读则在文件开头,写则在文件末尾
‘b’,字符b用来表示字节流(二进制),不加b则表示是字符流,一个进程能够打开的文件个数是1024个,其中stdin,stdout和stderr是默认打开的,在shell中输入以下命令即可查看open files个最大个数
ulimit -a
-
fclose() 关闭文件
//关闭流 extern int fclose (FILE *__stream);
示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
FILE * fp = fopen("tmp", "r");
if (fp == NULL) {
//fprintf(stderr, "fopen() failed!errno = %d\n", errno);//打印fopen() failed!errno = 2
//perror("fopen()"); //打印fopen(): No such file or directory
fprintf(stderr, "fopen()failed:%s\n", strerror(errno)); //打印fopen()failed:No such file or directory
exit(1);
}
puts("ok");
fclose(fp);
exit(0);
}
2.2 文件输入输出函数
2.2.1 fgetc()/fputc() 字符操作
-
fgetc() 从一个流中读取一个字符,读到文件末尾时返回EOF,否则返回的就是读出来的字符
/* Read a character from STREAM. These functions are possible cancellation points and therefore not marked with __THROW. */ extern int fgetc (FILE *__stream);
-
fuptc() 给一个流中写入一个字符
/* Write a character to STREAM. These functions are possible cancellation points and therefore not marked with __THROW. These functions is a possible cancellation point and therefore not marked with __THROW. */ extern int fputc (int __c, FILE *__stream);
-
示例一:文本文件复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
FILE *src, *dest;
int c;
src = fopen("./src", "r");
if (src == NULL) {
perror("fopen() src");
exit(1);
}
dest = fopen("./dest", "w");
if (dest == NULL) {
perror("fopen() dest");
exit(1);
}
while (1) {
c = fgetc(src);
if (c == EOF) break;
fputc(c, dest);
}
fclose(dest);
fclose(src);
exit(0);
}
- 示例二:统计文本字符
int main() {
FILE *fp;
int cnt = 0;
fp = fopen("./src", "r");
if (fp == NULL) {
perror("fopen() src");
exit(1);
}
while (fgetc(fp) != EOF) {
cnt++;
}
printf("./src文件共有%d个字符\n", cnt);
fclose(fp);
exit(0);
}
2.2.2 fgets()/fputs() 字符串操作
-
fgets() 从流中读取最多n个字符到s中去,读完文件时返回一个NULL,否则返回的就是读出来的字符串
/* Get a newline-terminated string of finite length from STREAM. This function is a possible cancellation point and therefore not marked with __THROW. */ extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) __wur;
fgets()函数的结束条件:
- 读取到了n-1个字符
- 读到’\n’
-
fputs() 像一个流中写入一个字符串
/* Write a string to STREAM. This function is a possible cancellation point and therefore not marked with __THROW. */ extern int fputs (const char *__restrict __s, FILE *__restrict __stream);
-
示例:文本文件复制
#define SIZE 5 int main() { FILE *src, *dest; char buf[SIZE]; src = fopen("./src", "r"); if (src == NULL) { perror("fopen() src"); exit(1); } dest = fopen("./dest", "w"); if (dest == NULL) { perror("fopen() dest"); exit(1); }