zoukankan      html  css  js  c++  java
  • C语言 文件操作

    前言:只有接触了文件的代码,才算真正的编程,那么,这篇博客就来简单介绍一下文件吧
    文件的定义:
    文件是一个外存的范畴;文件是计算机表达信息的最小逻辑单位;文件就是信息二进制化后在外存中的存储。

    文件的组成

    1. 文件名;
    2. 文件的主体内容;
    3. 文件属性。

    文件内容
    所有的内容都是二进制的!
    在这里要提到一点:操作系统(OS)在管理文件时,使用“文件控制块(FCB)”这样的数据。
    (所谓“文件控制块”,实质上是关于一个文件的一堆数据,数据越详细,OS对于文件的掌控越详尽)而且,FCB是OS的有限资源。
    不同的程序设计语言,都对于文件的操作给出了;
    不同的程序设计语言对于FCB进行了各自的表示和封装(C语言用FILE来封装FCB)

    对文件进行编程,需要先申请FCB。

    现在,就来介绍一下有关文件处理基本的几个函数吧:
    首先,要声明一点,所有相关函数都包含在<stdio.h>头文件中

    1.FILE *fopen(“文件名”,“打开方式”):
    这里的打开方式,有以下几种:
    在这里插入图片描述fopen()的本质申请操作系统的FCB资源

    2.int fclose(FILE *文件指针):
    相对地,fclose的本质相当于归还FCB资源
    关于返回值:
    如果成功关闭,则该方法返回0
    如果失败,则返回 EOF

    3.int fprintf(FILE *文件指针,“格式符”,...):
    功能:向文件指针所指向的文件中写入相应类型的数据。
    (写入数据时,本质上是字符串)
    关于返回值:
    如果成功,则返回写入的字符总数
    如果失败返回一个负数
    注意:fprintf(stdout,"格式符",...)等价于printf("格式符",...)

    4.int fscanf(FILE *文件指针,“格式符”,...):
    从文件指针所指向的文件中读取数值并赋值给相应变量。
    (读取数据时,首先是字符串,然后根据格式符转换为相应格式)
    关于返回值:
    如果成功,该函数返回成功匹配和赋值的个数
    如果到达文件末尾发生读错误,则返回 EOF
    注意:fscanf(stdin,"格式符",...)等价于scanff("格式符",...)

    5. char* fgets(char *目标字符串(str), int 最大字符数, FILE *文件指针):
    功能:从文件指针所指文件中读取一行,并把它存储在 str 所指向的字符串内。
    当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
    关于返回值:
    如果成功,该函数返回相同的 目标字符串
    如果到达文件末尾或者没有读取到任何字符str 的内容保持不变,并返回一个空指针
    如果发生错误返回一个空指针

    6.int fputs(const char *s, FILE *文件指针)
    (说明:s -- 这是一个字符串,包含了要写入的以空字符终止的字符序列)
    功能:把字符串写入到文件指针所指向的文件中,但不包括空字符。
    关于返回值:
    成功返回一个非负值
    如果发生错误返回 EOF

    7.int fgetc(FILE *文件指针):
    功能:从文件指针所指向的文件中读取一字节的信息
    关于返回值:
    该函数以无符号 char 强制转换为 int 的形式返回读取的字符
    如果到达文件末尾发生读错误,则返回 EOF

    8.int putc(int 要被写入的字符, FILE * 文件指针):
    功能:将目标字符写入文件指针所指向的文件中。
    关于返回值:
    如果成功,则返回被写入的字符
    如果发生错误,则返回 EOF,并设置错误标识符

    9.int feof(FILE *文件指针):
    功能:对上一次(紧上一次)的文件操作是否正确判定。
    关于返回值:
    成功返回值为0
    失败,则为返回值非0

    10.size_t fwrite(const void *被写入元素数组的指针, size_t 被写入的每个元素的大小, size_t 元素个数, FILE *文件指针):
    说明:被写入元素的大小按照二进制为单位
    功能:将数组,结构体等类型的值写入指定文件中
    关于返回值:
    如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型
    如果该数字与 元素个数 参数不同,则会显示一个错误

    11.size_t fread(void *要存入元素的数组的指针, size_t 要读取每个元素大小, size_t 元素个数, FILE *文件指针):
    说明:被写入元素的大小按照二进制为单位
    功能:从数组,结构体中读取指定大小数据
    关于返回值:
    成功读取的元素总数会以 size_t 对象返回size_t 对象是一个整型数据类型
    如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾

    12.long int ftell(FILE *文件指针):
    功能:用于查看文件大小或指针对于初始位置的相对偏移量
    说明,正常使用的返回值为当前位置距离初始位置的偏移量,单位为字节。
    关于返回值:
    如果使用成功该函数返回位置标识符的当前值
    如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值

    13.int fseek(FILE *stream, long int 偏移量, int 常量):
    功能:将文件指针指向目标位置;
    说明:关于常量,一共有三种情况:
    在这里插入图片描述
    关于返回值:
    如果成功,则该函数返回零
    否则,返回非零值

    14.int rename(const char *原文件名, const char *新文件名):
    功能:顾名思义,给文件改名的函数。

    15.int remove(const char *要删除的文件名):
    功能;删除指定名的文件。

    那么以上就是我们对于文件操作的基本函数了。

    现在,我们就来实现一些常用的文件操作吧!
    首先,假设已有文件为data.txt
    那么,文件的内容展示(showFile.c):

    #include <stdio.h>
    
    int main() {
    	FILE *fp;
    	int ch;
    
    	fp = fopen("data.txt", "r");
    
    	ch = fgetc(fp);
    	while (!feof(fp)) {
    		printf("%c", ch);
    		ch = fgetc(fp);
    	}
    	printf("
    !!!
    ");
    
    	fclose(fp);
    
    	return 0;
    }
    

    文件内容复制(copyFile.c):
    (假设将data.txt的内容复制给data.sav)

    #include <stdio.h>
    
    int main() {
    	FILE *fpIn;
    	FILE *fpOut;
    	int ch;
    
    	fpIn = fopen("data.txt", "r");
    	fpOut = fopen("data.sav", "w");
    
    	ch = fgetc(fpIn);
    	while (!feof(fpIn)) {
    		fputc(ch, fpOut);
    		ch = fgetc(fpIn);
    	}
    
    	fclose(fpIn);
    	fclose(fpOut);
    
    	return 0;
    }
    

    将 数组 写入指定文件中(aboutBinary.c):

    #include <stdio.h>
    
    int main() {
    	FILE *fp;
    	int arr[10] = {1, 100, 1000, 10000, 100000};	
    	// {0x00000001, 0x00000064, 0x000003E8, 0x00002710, 0x000186A0}
    	int i;
    
    	fp = fopen("abcd.dat", "wb");
    	fwrite(arr, sizeof(int), 5, fp);
    	//等同于 for (i = 0; i < 5; i++) {
    	// 	          fwrite(arr + i, sizeof(int), 1, fp);
    	//            }
    
    	fclose(fp);
    
    	return 0;
    }
    

    将 结构体 写入指定文件中(aboutStruct.c):

    #include <stdio.h>
    
    typedef struct {
    	int one;
    	char two;
    	int three;
    	double four;
    }MY_TYPE;
    
    int main() {
    	MY_TYPE num = {
    		0x12,
    		'A', // 0x41
    		0x135,
    		3.14,
    	};
    	FILE *fp;
    
    	fp = fopen("abcde.dat", "wb");        //wb是用二进制方式写入的打开方式
    	fwrite(&num, sizeof(MY_TYPE), 1, fp);
    
    	fclose(fp);
    
    	return 0;
    }
    

    在之前的一篇博客《(带头节点的链表) 宿舍管理系统)》中,我们提到了文件,那么,现在我们用文件来简单实现一下基本的操作吧:
    首先,录入信息函数:

    boolean enterInf(NEW_TYPE *ptr, int size, int count, FILE *fp){
    	if(NULL == fp) {
    		return FALSE;
    	}
    	fwrite(ptr, size, count, fp);
    	return TRUE;
    }
    

    这里对上面这段这段代码做几点说明:
    1.这个函数存在前提是文件以“wb”形式打开了(有打开就一定要记得关闭);
    2.关于参数size,可以在引用函数时写作sizeof(NEW_TYPE);
    3.关于返回值,可以在主函数中用来判断用户是否使用错误

    其次,是查看信息函数:
    要制作查看函数,我们根据之前制作管理系统的知识,将函数做成查找指定信息和查看单独信息的两个函数
    1.查找单独信息:

    boolean seekOne(FILE *fp, int count, size_t NEW_TYPE) {
    	int no;
        if(NULL == fp) {
    		return FALSE;
    	}
    	printf("请输入要查看信息编号: ");
    	scanf("%d", &no);
    	if(no > count) {
    		return FALSE;
    	}
    	fseek(fp, sizeof(NEW_TYPE) * no, SEEK_SET);
    	return TRUE;
    }
    

    2.显示一个信息:

    void showOne(FILE *fp, size_t NEW_TYPE) {
    	char NEW_TYPE[sizeof(NEW_TYPE)];
    	if(NULL == fp) {
    		return FALSE;
    	}
    	fread(NEW_TYPE, sizeof(NEW_TYPE), 1, fp);
    	printf("%s", NEW_TYPE);
    }
    

    3.显示指定信息:

    void showInf(FILE *fp, size_t NEW_TYPE) {
    	if(NULL == fp) {
    		return FALSE;
    	}
    	seekOne(fp, sizeof(ftell(fp))/sizeof(NEW_TYPE), size_t NEW_TYPE);
    	showOne(fp);
    }
    

    4.显示信息表:

    void showAllInf(FILE *fp, size_t NEW_TYPE) {
    	printf("表头");
    	for(i=0, i<count, i++) {	//这里的count变量是我们存储的信息的数量,我们可以通过一个全局变量实现
    		fseek(fp, sizeof(NEW_TYPE) , SEEK_CUR);
    		showOne(fp);
    	}
    }
    

    再者,增添信息函数:

    boolean addInf(FILE *fp, size_t NEW_TYPE) {
    	int no;
    	printf("请输入要插入信息编号:");
    	scanf("%d", no);
    	if(NULL == fp) {
    		return FALSE;
    	}
    	seekOne(fp, sizeof(ftell(fp))/sizeof(NEW_TYPE), size_t NEW_TYPE);
    	fwrite(&num, sizeof(MY_TYPE), 1, fp);
    }
    
  • 相关阅读:
    POJ 1795 DNA Laboratory
    CodeForces 303B Rectangle Puzzle II
    HDU 2197 本源串
    HDU 5965 扫雷
    POJ 3099 Go Go Gorelians
    CodeForces 762D Maximum path
    CodeForces 731C Socks
    HDU 1231 最大连续子序列
    HDU 5650 so easy
    大话接口隐私与安全 转载
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12410960.html
Copyright © 2011-2022 走看看