1. 简介
标准IO相对于第三章文件IO来说,标准IO是库函数调用,而文件IO是系统调用。标准IO实现了读写数据的缓存机制,因此能够一定程度提高读写效率。标准IO提供了多个方便用户在不同应用场合的IO接口,这些IO接口有不同的缓冲类型,包含全缓冲、行缓冲和不带缓冲。标准IO围绕一个流的数据结构进行操作,标准IO库打开或创建文件时,都有一个流对象与之关联。标准输入流、标准输出流和标准错误流分别对应的流对象是stdin(STDIN_FILENO)、stdout(STDOUT_FILENO)和stderr(STDERR_FILENO)。
2. 函数原型
int fwide(FILE *fp, int mode) | 返回值:返回正值,则流是宽字节定向的;返回负值,则流是字节定向的;返回0,则流是未定向的 |
void setbuf(FILE *restrict fp, char *restrict buf) int setvbuf(FILE *restrict fp, char *restrict buf, int mode size_t size) |
更改缓冲类型 setvbuf返回值:若成功,返回0;若出错,返回-1 |
int fflush(FILE *fp) |
强制冲洗一个流 返回值:若成功,返回0;若出错,返回-1 |
FILE *fopen(const char *pathname, const char *mode) FILE *fdopen(int fd, const char *mode) FILE *freopen(const char *pathname, const char *mode, FILE *stream) |
打开一个流 3个函数返回值:若成功,返回文件指针;若出错,返回NULL |
int fclose(FILE *fp) |
关闭一个流 返回值:若成功,返回0;若出错,返回EOF |
int getc(FILE *fp) int fgetc(FILE *fp) int getchar(void) |
getc可以被实现为一个宏,fgetc必须是一个函数 3个函数返回值:若成功,返回下一个字符;若出错或到达文件末尾,返回EOF |
int ferror(FILE *fp) int feof(FILE *fp) | 2个函数返回值:若条件为真,返回非0;若条件为假,返回0 |
void clearerr(FILE *fp) | 清除错误和文件结束标志 |
int ungetc(int c, FILE *fp) |
将字符压回流中(先进后出) 返回值:若成功,返回c;若出错,返回EOF |
int fputc(int c, FILE *stream) int putc(int c, FILE *stream) int putchar(int c) |
putc可以被实现为一个宏,fputc必须是一个函数 3个函数返回值:若成功,返回c;若出错,返回EOF |
char *fgets(char *s, int size, FILE *stream) char *gets(char *buf) | 2个函数返回值:若成功,返回buf;若出错或到达文件末尾,返回NULL |
int fputs(const char *s, FILE *stream) int puts(const char *s) | 2个函数返回值:若成功,返回非负值;若出错,返回EOF |
ize_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream) |
二进制IO 2个函数返回值:读或写的对象数 |
int fseek(FILE *stream, long offset, int whence) long ftell(FILE *stream) void rewind(FILE *stream) |
ftell返回值:若成功,返回当前文件位置指示,若出错,返回-1 fseek返回值:若成功,返回0,若出错,返回-1 rewind将流设置到文件的起始位置 |
int fseeko(FILE *stream, off_t offset, int whence) off_t ftello(FILE *stream) | 与fseek和ftell作用相同 |
int fgetpos(FILE *stream, fpos_t *pos) int fsetpos(FILE *stream, const fpos_t *pos) | 2函数返回值:若成功,返回0;若出错,返回非0 |
int printf(const char *format, ...) int fprintf(FILE *stream, const char *format, ...) int vprintf(const char *format, va_list ap) | 格式化输出函数 |
int scanf(const char *format, ...); int vscanf(const char *format, va_list ap); | 格式化输入函数 |
int fileno(FILE *fp) | 返回值:返回与该流关联的文件描述符 |
char *tmpnam(char *s) FILE *tmpfile() char *mkdtemp(char *template) int mkstemp(char *template) | 创建临时文件或目录 |
FILE *fmemopen(void *buf, size_t size, const char *mode) FILE *open_memstream(char **ptr, size_t *sizeloc); FILE *open_wmemstream(wchar_t **ptr, size_t *sizeloc); | 创建内存流 |
3. 实例
#include <stdio.h>
#include <wchar.h>
#include <unistd.h>
#include <string.h>
#define TEST_STR "Hello world!"
struct test_binary_rw {
int n;
short s1;
short s2;
char buf[8];
};
struct test_binary_rw binary_rw[] = {
{1, 2, 3, "Hello"},
{4, 5, 6, "world"},
{7, 8, 9, "!"}
};
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
int main()
{
int c;
FILE *fp = fopen("test.txt", "w+");
printf("fp: %d\n", fwide(fp, 0));
printf("fp: %d\n", fwide(fp, -1));
for (int i = 0; i < strlen(TEST_STR); i++) {
c = fputc(TEST_STR[i], fp);
if (c != TEST_STR[i]) {
printf("fputc error: %c\n", c);
break;
}
}
rewind(fp);
while(1) {
c = fgetc(fp);
if (c == EOF) {
break;
}
printf("%c", c);
}
printf("\n");
FILE *fp2 = fopen("test2.txt", "w+");
fwrite(binary_rw, sizeof(binary_rw[0]), ARRAY_SIZE(binary_rw), fp2);
fwrite(TEST_STR, sizeof(char), strlen(TEST_STR), fp2);
struct test_binary_rw tmp_rw[ARRAY_SIZE(binary_rw)+1] = {0};
rewind(fp2);
int r = fread(tmp_rw, sizeof(binary_rw[0]), ARRAY_SIZE(binary_rw)+1, fp2);
printf("r = %d\n", r);
for (int i = 0; i < ARRAY_SIZE(binary_rw); i++) {
printf("n = %d, s1 = %d, s2 = %d, buf = %s\n", tmp_rw[i].n, tmp_rw[i].s1, tmp_rw[i].s2, tmp_rw[i].buf);
}
printf("TEST_STR: %s\n", (char *)&tmp_rw[ARRAY_SIZE(binary_rw)]);
char wbuf[32] = {0};
memset(wbuf, 'a', sizeof(wbuf)-1);
printf("wbuf = %s\n", wbuf);
FILE *mFp1 = fmemopen(wbuf, sizeof(wbuf), "w+");
printf("wbuf = %s\n", wbuf);
fprintf(mFp1, "123");
printf("wbuf = %s\n", wbuf);
fflush(mFp1);
printf("wbuf = %s\n", wbuf);
memset(wbuf, 'b', sizeof(wbuf)-1);
fprintf(mFp1, "456");
printf("wbuf = %s\n", wbuf);
fseek(mFp1, 0, SEEK_SET);
printf("wbuf = %s\n", wbuf);
memset(wbuf, 'c', sizeof(wbuf)-1);
fprintf(mFp1, "789");
fflush(mFp1); // ??
printf("wbuf = %s\n", wbuf);
fprintf(mFp1, "ab");
fflush(mFp1);
printf("wbuf = %s\n", wbuf);
fprintf(mFp1, "cd");
fflush(mFp1);
printf("wbuf = %s\n", wbuf);
}
4. 小结
1. 理解文件IO和标准IO的区别,标准IO的3种缓冲特性
2. 二进制IO函数的(fread和fwrite)的理解和应用以及各个字符和行相关的IO函数
3. 了解格式化输入和输出一系列函数
4. 了解临时文件的创建和应用
4. 了解内存流的使用