1.fopen与fclose
FILE *fopen(char *filename, char *mode);
fopen的函数如上,第一个参数文件名(路径),第二个参数为打开方式。
打开方式包括打开权限:r,w,a,r+,w+,a+六种,与读写方式t,b两种。
r:读,若不存在该文件,fopen返回NULL。
w:写,若不存在则新建,若存在删除新建。
a:追加,若不存在则新建,若存在写入内容追加在已存在文件后。
+:读写,前面加上r,w,a,则是以x方式打开文件,拥有读写权限。r+,若不存在该文件,则fopen返回NULL。w+,若不存在则新建,存在删除新建,拥有读写。
t:文本格式
b:二进制格式
tb不能书写格式不能在第一位:rb+,r+t。
int fclose(FILE *fp);
正常关闭返回0,关闭异常返回非0。
一个程序,打开demo文件,读取每一行数据:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define N 100
int main(){
FILE* fp;
char buffer[N+1];
if((fp=fopen("E:\\demo.txt","rt"))==NULL){
puts("file open error!");
exit(0);
}
while(fgets(buffer,N,fp)!=NULL){
printf("%s",buffer);
}
if(fclose(fp)!=0){
puts("file close error!");
exit(0);
}
return 0;
}
2.fgetc与fputc(字符读写)
int fgetc (FILE *fp);
int fputc ( int ch, FILE *fp );
两个函数,成功都是返回读(写)的字符,失败返回EOF(宏定义)。
文件中有面向用户隐藏的指向标记,每fgetc一个字符,标记向下移动一个字符位置,读取结束,返回EOF。
int ferror(FILE* fp);
int feof(FILE* fp);
ferror函数用来判断文件读取是否出错,出错返回非0值,反之返回0。
feof函数用来判断文件标记是否读取岛结尾,指向末尾返回非0值,反之返回0。
读取demo的所有数据:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
int main(){
FILE* fp;
char ch;
if((fp=fopen("E:\\demo.txt","rt+"))==NULL){
puts("file open error!");
exit(0);
}
while((ch=fgetc(fp))!=EOF){
printf("%c",ch);
}
if(ferror(fp)!=0){
puts("file get char error!");
exit(0);
}
fclose(fp);
return 0;
}
往demo中写入数据:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
int main(){
FILE* fp;
char ch;
if((fp=fopen("E:\\demo.txt","a+t"))==NULL){
puts("file open error!");
exit(0);
}
while((ch=getchar())!='\n'){
fputc(ch,fp);
}
fputc('\n', fp);
fclose(fp);
return 0;
}
3.fgets与fputs(字符串读写)
char *fgets ( char *str, int n, FILE *fp );
int fputs( char *str, FILE *fp );
读取字符串,不是读取一整行,而是读取n个字符的字符串。一共两点:1.fgets会自动补’\0’,所以char数组大小应该为n+1。2.fgets与gets不同的是,fgets自动识别换行符,而gets不会自动识别换行符。
写入字符串,写入成功返回非0值,失败返回EOF。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4996)
#define N 100
int main(){
FILE* fp;
char buffer[N+1];
char putStr[102]={0};//在inpStr前添加换行符
char inpStr[100]={0};//键盘输入
if((fp=fopen("E:\\demo.txt","a+t"))==NULL){
puts("file open error!");
exit(0);
}
gets_s(inpStr);
strcat(putStr,"\n");
strcat(putStr,inpStr);
if(fputs(putStr,fp)!=EOF){
puts("put the str succeed!");
}
fclose(fp);
if((fp=fopen("E:\\demo.txt","a+t"))==NULL){
puts("file open error!");
exit(0);
}
while(fgets(buffer,N,fp)!=NULL){
printf("%s",buffer);
}
fclose(fp);
return 0;
}
4.fread与fwrite(块读写)
size_t fread ( void *ptr, size_t size, size_t count, FILE *fp );
size_t fwrite ( void * ptr, size_t size, size_t count, FILE *fp );
两个返回的的都是count,若返回的count小于参数内的count,
fread可能表示读取错误,也可能读取到末尾。利用ferror与feof检测。
fwrite表示写入错误。
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define N 5
int main(){
int a[N];
int b[N];
size_t size = sizeof(int);
FILE* fp;
if((fp=fopen("E:\\demo.txt","r+b"))==NULL){
puts("file open error!");
exit(0);
}
puts("please enter five nubmers:");
for(int i=0;i<N;i++){
scanf("%d",&a[i]);
}
if((fwrite(a,size,N,fp))!=N){
puts("file write error!");
exit(0);
}
rewind(fp);
fread(b,size,N,fp);
if(ferror(fp)!=0){
puts("file read error!");
exit(0);
}
for(int i=0;i<N;i++){
printf("%d",b[i]);
}
fclose(fp);
return 0;
}
块输入,读写方式需要采用b二进制方式打开文件,因为在windows下。
rewind函数表示把标记重置到指向数据第一位置。
使用块读写读写结构体:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define N 2
struct stu {
char name[10];
int num;
int age;
int score;
}stuA[N], stuB[N], * ptrA, * ptrB;
int main() {
ptrA = stuA;
ptrB = stuB;
size_t size = sizeof(struct stu);
FILE* fp;
if ((fp = fopen("E:\\demo", "w+b")) == NULL) {
puts("file open error");
exit(0);
}
puts("please enter two students' data:");
for (int i = 0; i < N; i++, ptrA++) {
scanf("%s %d %d %d", ptrA->name, &ptrA->num, &ptrA->age, &ptrA->score);
}
if ((fwrite(stuA, size, N, fp)) != N) {
puts("file write error!");
exit(0);
}
rewind(fp);
fread(stuB, size, N, fp);
if (ferror(fp) != 0) {
puts("file read error!");
exit(0);
}
for (int i = 0; i < N; i++, ptrB++) {
printf("student:%s %d %d %d", ptrB->name, ptrB->num, ptrB->age, ptrB->score);
}
fclose(fp);
return 0;
}
5.fscanf与fprintf(格式读写)
fscanf:从文件中以格式读出。
fprintf:以格式写入文件。
int fscanf ( FILE *fp, char * format, … );
int fprintf ( FILE *fp, char * format, … );
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define N 2
struct stu{
char name[10];
int num;
int age;
float score;
}stuA[N],stuB[N],*ptrA,*ptrB;
int main(){
ptrA = stuA;
ptrB = stuB;
FILE* fp;
if((fp=fopen("E:\\demo.txt","w+t"))==NULL){
puts("file open error!");
exit(0);
}
puts("please enter the student's data:");
for(int i=0;i<N;i++,ptrA++){
scanf("%s %d %d %f",ptrA->name,&ptrA->num,&ptrA->age,&ptrA->score);//输入即把数据放入某地址内存,所以别忘了&
}
ptrA=stuA;//ptrA在main中为全局变量,别忘了重置指针位置。
for(int i=0;i<N;i++,ptrA++){
fprintf(fp,"%s %d %d %f\n",ptrA->name,ptrA->num,ptrA->age,ptrA->score);//写入即把数据写入文件,而不是将地址写入,所以不需要&
}
rewind(fp);
for(int i=0;i<N;i++,ptrB++){
fscanf(fp,"%s %d %d %f\n",ptrB->name,&ptrB->num,&ptrB->age,&ptrB->score);
}
ptrB=stuB;
for(int i=0;i<N;i++,ptrB++){
printf("%s %d %d %f\n",ptrB->name,ptrB->num,ptrB->age,ptrB->score);
}
fclose(fp);
return 0;
}
tips:写入的时候是将数据写入文件,而不是将地址写入,取值即可。读出的时候,是将文件数据读出后存储在stuB中,需要存入结构体中内存,即存入内存地址中,需要取地址存储。
6.fseek
int fseek ( FILE *fp, long offset, int origin );
参数说明:
-
fp 为文件指针,也就是被移动的文件。
-
offset 为偏移量,也就是要移动的字节数。之所以为 long 类型,是希望移动的范围更大,能处理的文件更大。offset 为正时,向后移动;offset 为负时,向前移动。
-
origin 为起始位置,也就是从何处开始计算偏移量。C语言规定的起始位置有三种,分别为文件开头、当前位置和文件末尾,每个位置都用对应的常量来表示:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define N 3
struct stu {
char name[10];
int num;
int age;
float score;
}stuA[N],stuB[N],*ptrA,*ptrB;
int main() {
FILE* fp;
ptrA = stuA;
if ((fp = fopen("E:\\DEMO.TXT", "wb+")) == NULL) {
puts("file open error!");
exit(0);
}
puts("please enter student's data:");
for (int i = 0; i < N; i++, ptrA++) {
scanf("%s %d %d %f", ptrA->name, &ptrA->num, &ptrA->age, &ptrA->score);
}
fwrite(stuA, sizeof(struct stu), N, fp);
fseek(fp, sizeof(struct stu), 0);
fread(stuB, sizeof(struct stu), 2, fp);
ptrB = stuB;
for (int i = 0; i < 2; i++, ptrB++) {
printf("%s %d %d %f\n", ptrB->name, ptrB->num, ptrB->age, ptrB->score);
}
fclose(fp);
return 0;
}