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);
    }
    
  • 相关阅读:
    在 Eclipse 中使用 JUnit4 进行单元测试
    版本控制之道使用Git
    程序员成熟的标志
    Java 编程需要注意的细节
    【netty】netty的websocketframe
    求一个数内含1个次数
    apache bench的使用
    更改centos epel源
    [linux]centos7下解决yum install mysqlserver没有可用包
    cacti的安装与配置
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12410960.html
Copyright © 2011-2022 走看看