C语言讲义——文件操作

fopen( ) 函数:创建一个新的文件或者打开一个已有的文件

FILE *fopen( const char * filename, const char * mode );

关于参数mode的取值

r
w 写(无文件则创建)(从头写)
a 写(无文件则创建)(追加)
r+ 读写
w+ 读写。如果文件存在,则截断为零长度,如果文件不存在,则创建一个新文件。
a+ 从头读,追加写(无文件则创建)

新建 从头 追加
r
w
a
r+
w+
a+

写文件示例

#include <stdio.h>

int fileWrite() {
	FILE *fp = NULL;

	fp = fopen("test.txt", "a+");
	if(NULL == fp) {
		// 将文件设为"只读",可测此处代码
		puts("fopen出错");
		// 使用perror()显示错误信息
		perror("fopen() Err");
		return -1;
	}
	fprintf(fp, "云想衣裳花想容,春风拂槛露华浓。\n");
	fputs("若非群玉山头见,会向瑶台月下逢。\n", fp);

	fclose(fp);
	return 0;
}
main() {
	fileWrite();
}

读文件示例

#include <stdio.h>

int  fileRead() {
	FILE *fp = NULL;
	char buff[255];

	fp = fopen("test.txt", "r");
	if(NULL == fp) {
		perror("fopen Error");
		return -1;
	}
	fscanf(fp, "%s", buff);
	printf("读取到空白字符: %s\n", buff );

	fgets(buff, 255, (FILE*)fp);
	printf("读取一行: %s\n", buff );

	fclose(fp);
	return 0;
}
main() {
	fileRead();
}

偏移

	fp = fopen(g_sFile, "r");
	// int fseek(FILE *stream, long offset, int fromwhere);
	// 第一个参数stream为文件指针
	// 第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移
	// 第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
	// SEEK_SET:文件开头(0)
	// SEEK_CUR:当前位置(1)
	// SEEK_END:文件结尾(2)
	// 定位成功:返回0
	// 定位失败:返回非0
	fseek(fp,1,SEEK_CUR);

示例:修改指定人员的成绩记录

现有成绩文件: data.dat

Apple,100;
Banana,098;
Cat,060;
Dog,032;

修改Cat的成绩为59分,即[Cat,060;]→[Cat,059;]前后内容都不变
为了方便定位,约定成绩都是3位字符表示

SEEK_CUR版

偏移数值问题——Unix和Windows不同

Unix(不算LF):fseek(fp, -4, SEEK_CUR)

Windows(算CR LF):fseek(fp, -6, SEEK_CUR)

SEEK_SET版

即使使用SEEK_SET从头找,找到上一行尾,再加,也有区别:

Unix:fseek(fp, nCurLen+4, SEEK_SET);
WIndows:fseek(fp, nCurLen+6, SEEK_SET);

结论:CRLF在内存中是不同的,所以fseek的参数有差别;但是反映在字符串上,都是一个\n(ASCII 10),比如第一行,strlen都是11

参考代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int updateFile() {
	int nRet = 0;
	FILE * fp = NULL;

	fp = fopen("data.dat", "r+");// r+:读写
	if (NULL == fp) {
		perror("fopen() Err");
		return 0;
	}
	// 读取文件
	char buff[1024]= {0};
	while(fgets(buff, 1024, fp)) {
		// char *strstr(char *str1, const char *str2);
		// 判断字符串str2是否是str1的子串。
		// 是:返回str2在str1中首次出现的地址;
		// 否:返回NULL
		if(strstr(buff, "Cat") != NULL) {
			//此时"光标"在读到的内容后面
			int nSeek = fseek(fp, -6, SEEK_CUR);
			if(nSeek != 0) {
				perror("fseek");
				break;
			} else {
				// 修改文件
				fprintf(fp, "%s", "059");
				nRet = 1;
				break;
			}
		}
	}
	// 无果:关闭文件
	fclose(fp);
	return nRet;
}
int main(int argc, char *argv[]) {
	updateFile();

	return 0;
}

应用:读写log

#include <stdio.h>
#include <io.h>
#include <time.h>
#include <direct.h>

enum Level { DEBUG, INFO, WARING, ERROR};

const char* g_sDir = "temp";
const char* g_sFile = "temp/info.txt";

void getTime(char* sTime_o) {
	time_t _time;
	time(&_time);
	struct tm *p =localtime(&_time);

	// 格式化,并写入到字符串中
	sprintf(sTime_o, "%d-%02d-%02d %02d:%02d:%02d",
	        p->tm_year+1900,
	        p->tm_mon + 1,
	        p->tm_mday,
	        p->tm_hour,
	        p->tm_min,
	        p->tm_sec);
}
int makeDir() {
	// access:判断文件或文件夹是否存在
	// <io.h>
	// F_OK:判断是否存在
	// success:0
	// fault:-1
	if (access(g_sDir, F_OK ) == 0) {
		// 文件夹存在
	} else {
		// _mkdir:创建文件夹
		// <direct.h>
		// success:0
		// fault:-1
		if (_mkdir(g_sDir) == -1) {
			printf("创建文件夹失败");
			return -1;
		}

	}
	return 0;
}
int logWrite(Level lvl, char*msg) {
	// 获取时间
	char sTime_o[200];
	getTime(sTime_o);
	//-------------------------
	// 创建log文件夹
	if(makeDir() == -1) {
		return -1;
	}
	// 打开文件
	FILE *fp = NULL;
	fp = fopen(g_sFile, "a+");
	if(NULL == fp) {
		printf("无法打开文件%s\n", g_sFile);
		return -1;
	}
	// 根据log级别,写入log
	if (lvl == DEBUG) {
		fprintf(fp, "%s [DEBUG] %s\n",sTime_o,msg);
	} else if(lvl == INFO) {
		fprintf(fp, "%s [INFO] %s\n",sTime_o,msg);
	}
	fclose(fp);
	return 0;
}
int logRead() {
	FILE *fp = NULL;
	fp = fopen(g_sFile, "r");
	if(NULL == fp) {
		puts("文件读取失败");
		return -1;
	}

	//TEST: 当前位置右移1
	fseek(fp,1,SEEK_CUR);

	// 读取文件
	char buff[255] = {0};
	while(fgets(buff, 255, (FILE*)fp)!=NULL) {
		printf("> %s", buff );
	}
	fclose(fp);
	return 0;
}
main() {
	// 能写,才读;不写,不读
	if (logWrite(INFO,"郭德纲") == 0) {
		logRead();
	}
}
posted @ 2019-07-15 21:47  虎老狮  阅读(243)  评论(0编辑  收藏  举报