C语言:文件读写
这是很基础的教程,我只是写给自己看,作为一个学习笔记记录一下,如果正在阅读的你觉得简单,请不要批评,可以关掉选择离开
如何学好一门编程语言
- 掌握基础知识,为将来进一步学习打下良好的基础。
- 上机实践,通过大量的例题学习怎么设计算法,培养解题思路。
- 养成良好的编码习惯,注释一定要写,要不然保你一周后自己写的代码都不认识了
这篇博客将介绍 C 程序 如何打开、关闭、读取和写入文本文件或二进制文件。一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节
打开文件
C语言中,使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,该函数返回 FILE类型文件指针。
FILE *fopen(const char * filename, const char * mode);
参数
- filename:文件名(字符串)
- mode:模式,如下表
模式 | 描述 |
---|---|
r | 以读模式打开文件 |
w |
以写模式打开文件
|
a |
打开一个文本文件,以追加模式写入文件(在已有的文件内容中追加内容)
|
r+ | 打开一个文本文件,允许读写文件。 |
w+ |
打开一个文本文件,允许读写文件。
|
a+ |
打开一个文本文件,允许读写 |
如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
做一个有高修养的程序员,当我们打开文件夹时,最好做一下判断,是否打开成功
FILE *f; f = fopen("../file","rb"); if (f==NULL){ printf("!Error: Cant't open file.\n"); exit(1); // 终止程序 }
关闭文件
关闭文件使用 fclose( ) 函数
int fclose( FILE *fp );
关闭成功,fclose( ) 函数返回零,关闭文件时发生错误,函数返回 EOF。
关闭后会清空缓冲区中的数据,并释放用于该文件的所有内存。所以应该养成打开文件记得关闭的习惯。
文本 I/O 读&写
fgetc() & fputc()
int fgetc(FILE *stream)
参数:stream:指向FILE对象的指针
返回:从 fp 所指向的输入文件中读取一个字符。返回值是读取的字符,如果发生错误则返回 EOF。
#include <stdio.h> int main() { FILE *fp; int c; int n = 0; fp = fopen("file.txt", "r"); if (fp == NULL) { perror("打开文件时发生错误"); return (-1); } do { c = fgetc(fp); if (feof(fp)) { break; } printf("%c", c); // We are in 2014 } while (1); fclose(fp); return (0); }
int fputc(int char, FILE *stream)
把字符 char (ASCII值)写入到 文件流 中,并把位置标识符往前移动。
返回:如果写入成功,返回被写入的ASCII码对应的字符。如果发生错误,则返回 EOF,并设置错误标识符。
#include <stdio.h> int main() { FILE *fp; int ch; fp = fopen("../file.txt", "w+"); for (ch = 33; ch <= 100; ch++) { fputc(ch, fp); } fclose(fp); return 0; } // file.txt文件 // !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd
fgets() & fputs()
int fgetc(FILE *stream)
参数:stream:指向FILE对象的指针
返回:从 fp 所指向的输入文件中读取一个字符。返回值是读取的字符,如果发生错误则返回 EOF。
#include <stdio.h> int main() { FILE *fp; int c; int n = 0; fp = fopen("file.txt", "r"); if (fp == NULL) { perror("打开文件时发生错误"); return (-1); } do { c = fgetc(fp); if (feof(fp)) { break; } printf("%c", c); // We are in 2014 } while (1); fclose(fp); return (0); }
int fputs(const char *str, FILE *stream)
把字符串str 写入到文件流 stream 中,但不包括空字符。
返回:如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF。
#include <stdio.h> int main() { FILE *fp; fp = fopen("../file.txt", "w+"); fputs("这是 C 语言。", fp); fputs("这是一种系统程序设计语言。", fp); fclose(fp); return (0); } //file.txt内容 //这是 C 语言。这是一种系统程序设计语言。
fscanf() & fprintf()
int fscanf(FILE *stream, const char *format, ...)
从文件流中读取格式化输入,但是在遇到第一个空格和换行符时,它会停止读取。
参数:
- stream:这是指向 FILE 对象的指针,该 FILE 对象标识了流。
- format:这是 C 字符串,
#include <stdio.h> #include <stdlib.h> int main() { char str1[10], str2[10], str3[10]; int year; FILE *fp; fp = fopen("file.txt", "w+"); fputs("We are in 2014", fp); rewind(fp); fscanf(fp, "%s %s %s %d", str1, str2, str3, &year); printf("Read String1 |%s|\n", str1); printf("Read String2 |%s|\n", str2); printf("Read String3 |%s|\n", str3); printf("Read Integer |%d|\n", year); fclose(fp); return (0); } //Read String1 |We| //Read String2 |are| //Read String3 |in| //Read Integer |2014|
int fprintf(FILE *stream, const char *format, ...)
发送格式化输出到文件流中
参数
- stream:文件流
- format:这是 C 字符串,包含了要被写入到流 stream 中的文本。
#include <stdio.h> int main() { FILE *fp; fp = fopen("../file.txt", "w+"); fprintf(fp, "%s %s %s %d", "We", "are", "in", 2021); fclose(fp); return (0); } //file.txt内容 //We are in 2021
二进制 I/O 函数
二进制写
size_t fwrite ( void * ptr, size_t size, size_t count, FILE *stream);
把 指针ptr 所指向的地址中的数据写入到给定文件流中。
参数:
- ptr:指向要被写入的元素的指针。数组就是数组名,结构体要在结构体前面加个&
- size:要被写入的每个元素的大小,以字节为单位。
- count:元素的个数
- stream:文件流
返回:写入成功,返回写入元素的总数(size_t类型)。
#include <stdio.h> int main() { FILE *f; // char str[] = "never blog"; struct Student { int num; int age; } stud = {1, 2}; f = fopen("../R_and_A/test.txt", "wb"); // fwrite(str, sizeof(stud), 1, f); // 写入数组 fwrite(&stud, sizeof(stud), 1, f); // 写入接结构体 fclose(f); return 0; }
二进制读
size_t fread ( void *ptr, size_t size, size_t count, FILE *stream );
从文件流 stream 读取数据到 ptr 所指向的地址中。
参数:
- ptr:读取到的数据 要存放的地址
- size:要读取的每个元素的大小,以字节为单位。
- count:元素的个数,每个元素的大小为 size 字节。
- stream:FILE 对象的指针
返回:读取成功返回count (size_t类型),读取失败返回 -1。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
#include <stdio.h> int main() { FILE *fp; // char str[20]; struct Student { int num; int age; } stud; fp = fopen("../R_and_A/test.txt", "rb"); // fread(str, sizeof(str), 1, fp); // 读取数组 fread(&stud, sizeof(stud), 1, fp); printf("stud.num:%d,stud.age:%d", stud.num, stud.age); // stud.num:1,stud.age:2 fclose(fp); return 0; }
文件流的锚操作
锚可以理解为我们打字时候这个一闪一闪的光标。
设置文件流的 锚的位置为文件开头: void rewind(FILE *stream)
int fseek(FILE *stream, long int offset, int whence)
设置文件流 的偏移 offset
- stream:指向 FILE 对象的指针
- offset:偏移量,以字节为单位
- whence:文件指针的位置
- SEEK_SET:文件开头
- SEEK_CUR:文件指针的当前位置
- SEEK_END:文件的末尾
返回:如果成功,则该函数返回零,否则返回非零值。
int feof(FILE *stream)
测试时候读取到文件末尾,返回一个非零值,否则返回零。
FILE *fp; char buf[512]; fp = fopen("file.txt", "rb"); if(feof(fp)){ fread (buf, sizeof(char), sizeof(buf), fv); }
int ferror(FILE *stream)
测试文件是否读取成功,当读写出现错误时返回一个非零值,否则返回0。
FILE *fp; fp = fopen("file.txt", "w"); if(ferror(fp)){ printf("读取文件:file.txt 时发生错误\n"); }