【C语言】高效处理文件内容:C语言的文件操作技巧与窍门

这篇具有很好参考价值的文章主要介绍了【C语言】高效处理文件内容:C语言的文件操作技巧与窍门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、文件分类

1、按存储介质分类

2、按存储方式分类

二、文本文件

三、二进制码文件 

四、二进制和文件文件的区别 

五、文件缓冲区 

 1、文件缓冲区的刷新方式

2、模拟时钟

3、文件指针

六、文件的API

1、打开文件fopen

2、关闭文件 fclose

3、逐个字符读写 fgetc fputc

4、一次读写一个字符串 fgets fputs

5、一次读写n块文件数据 fread fwrite

 6、格式化读写 fscanf  fprintf​编辑

 1、格式化写  fprintf ( 文件指针,格式字符串,输出表列)

2、格式化读 fscanf ( 文件指针,格式字符串,输出表列)

七、文件的随机读写

1、顺序读写引入随机读写案例

2、随机读写的API

(1)rewind复位文件流指针

 (2)ftell返回文件流指针 距离文件首部的 字节数

(3)fseek文件流指针定位

八、文件加密器


一、文件分类

1、按存储介质分类

磁盘文件:文件的数据 存放在磁盘上(音视频、图片文件、文档文件)

设备文件:通过系统将外部设备抽象文件

2、按存储方式分类

物理上:任何磁盘文件 在物理上都是二进制存储。

逻辑上:磁盘文件分为二进制文件文本文件

二、文本文件

        文本文件基于字符编码,常见编码有 ASCII、UNICODE 等。 一般可以使用文本编辑器直接打开

        例如:

        (1)数 5678 的以 ASCII 存储形式为 ASCII 码:

                 00110101(==53=='5')   00110110   00110111   00111000         共4B

        (2)歌词文件(lrc):文本文件 

三、二进制码文件 

        基于编码,把内存中的数据原样输出到磁盘上 ,一般需要自己判断或使用特定软件分析数据格式

        例如:数 5678 的存储形式为: 二进制码:00010110 00101110

四、二进制和文件文件的区别 

文本文件:

优点:一个字节表示一个意思、便于查看

缺点:空间大、效率低

二进制文件:

优点:效率高、空间小

缺点:不定长、不便于查看

五、文件缓冲区 

【C语言】高效处理文件内容:C语言的文件操作技巧与窍门,C/C++,算法,c语言,开发语言,学习

 1、文件缓冲区的刷新方式

1、行刷新:遇到换行符刷新。

2、满刷新:缓冲区数据放满 刷新

3、强制刷新使用fflush函数 将缓冲刷新

4、关闭耍新 :程序运行结束的时候 将缓冲区数据 全部刷新

2、模拟时钟

#include<unistd.h>
void test()
{
    int i=0;
    while(1)
    {
        printf(\r%02d:%02d",i/60,i%60);//\r回到行首
        fflush(stdout);//强制刷新
        sleep(1);
        i++;
}

3、文件指针

        所有操作文件的库函数 都需要借助文件指针操作文件

为每一个进程 默认打开的3个文件指针:

(1)stdin:标准输入默认为当前终端(键盘)
我们使用的scanf、getchar 函数默认从此终端获得数据

(2)stdout:标准输出﹑默认为当前终端(屏幕)
我们使用的printf、puts 函数默认输出信息到此终端
(3)stderr:标准错误输出设备文件默认为当前终端(屏幕)

当我们程序出错使用:perror函数时信息打印在此终端

例:fgets(buf,sizeof(buf),stdin);

        fwrite("hello world",12,1,stdout);//12块1字节输出

六、文件的API

文件的操作步骤:打开 读写 关闭

1、打开文件fopen

        fopen中f描述其为库函数,其底层使用open函数完成系统调用。

定义:FILE *fopen(const char *path, const char *mode);

path:文件的路径

mode:打开文件方式

返回值:

        成功:就是打开的文件指针

        失败:NULL

文件的打开方式mode:r、w、a、+、t、b

r:只读的方式打开

w:只写的方式打开

a:追加的方式打开(清空重写)

+:可读可写方式打开

t:以文本文件方式打开 (默认方式,可省略)

b:以二进制方式打开(必须显示说明)

 组合方式:

模式 功能
r或rb 以只读方式打开一个文件(不创建文件)
w或wb 以写方式打开文件(使文件长度截断为0字节(删除),创建一个文件)
a或ab 以添加方式打开文件,即在末尾添加内容,当文件不存在时,创建文件用于追加写入
r+或rb+ 以可读、可写的方式打开文件(不创建新文件)
w+或wb+ 以可读、可写的方式打开文件
(使文件长度为0字节(删除),创建一个文件)
a+或ab+ 以添加方式打开文件,打开文件并在末尾更改文件(如果文件不存在,则创建文件)

2、关闭文件 fclose

定义:int fclose(FILE *fp);

返回值:

        成功返回     0

        失败返回  非0

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "r");
	if (fp = NULL)//文件不存在
	{
		perror("fopen");
		return;
	}
	fclose(fp);
}

3、逐个字符读写 fgetc fputc

一次一个字节:fputc

函数的定义:int fputc(int c, FILE *stream)

函数的说明:fputc将c的值写到stream所代表的文件中。

返回值:
        如果输出成功,则返回输出的字节值;

        如果输出失败,则返回一个EOF

EOF是在stdio.h文件中定义的宏符号常量,值为-1,EOF只是在文本文件中有效

 写入hello world字符串:

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	char* file_data = "hello word";
	while (*file_data != '\0')
	{
		fputc(*file_data, fp);
		file_data++;
	}
	fclose(fp);
}

一次一个字节:fgetc

函数定义:int fgetc(FILE *stream);

函数说明:fgetc 从stream所标示的文件中读取一个字节,将字节值返回

返回值:
        以t的方式:读到文件结尾返回EOF
        以b的方式:读到文件结尾,使用feof函数(后面会讲)判断结尾

 逐个读字符串:

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "r");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	while(1)
	{
		char ch = fgetc(fp);
		if (ch != EOF)
			break;
		printf("%c", ch);
	}
	fclose(fp);
}

4、一次读写一个字符串 fgets fputs

写一个字符串:int fputs(const char *s, FILE *stream)

读一个字符串:char *fgets(char *s, int size, FILE *stream)

读取一个字符串(遇到换行符 结束) ,读取一行文件数据

成功返回目的数组的首地址,即 s

失败返回 NULL

 有test.txt文件下test.txt文件中数据往b.txt中的测试程序:

void test06()
{
    FILE *fp_r = fopen("test.txt", "r");
    if (fp_r == NULL)
    {
         perror("fopen");
         return;
    }
    FILE *fp_w = fopen("b.txt", "w");
    if (fp_w == NULL)
    {
        perror("fopen");
        return;
    }

    while (1)
    {
        char buf[128] = "";//存放读到的数据并写到b.txt中
        //读一行
        char *ret = fgets(buf, sizeof(buf), fp_r);
        if (ret == NULL)
        break;

        //写一行
        fputs(buf, fp_w);
    }

 fclose(fp_r);
 fclose(fp_w);
}

5、一次读写n块文件数据 fread fwrite

块写:size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);

函数说明:fwrite 函数将ptr 指向的内存里的数据,向stream 所标示的文件中写入数据,一块是size个字节,共n块。

:将内存的数据 原样写入磁盘文件

返回值: 实际写入的块数

快写实例: 

#include <string.h>
typedef struct
{
    int num;
    char name[30];
}STU;
void test()
{
    STU A[3]={{1,"lucy"},{2,"bob"},{3,"张三",{4,"李四"}};
    int n = sizeof(hero) / sizeof(hero[0]);
    FILE *fp = fopen("S.txt", "w");
    if (fp == NULL)
    {
         perror("fopen");
        return;
     }
    fwrite(A, sizeof(A), n, fp);
    fclose(fp);
}

快读:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

: 磁盘数据 原样 输入内存

返回值: 实际读到的整块数:不足一块 不计数 但数据是读到的。

块读实例 

#include <string.h>
void test02()
{
    STU A[3];
    memset(A, 0, sizeof(A));
    FILE *fp = fopen("S.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return;
    }
    fread(A, sizeof(STU), 3, fp);
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%d %s\n", A[i].num, A[i].name);
    }
    fclose(fp);
}

 6、格式化读写 fscanf  fprintf

 1、格式化写  fprintf ( 文件指针,格式字符串,输出表列)

#include <string.h>
typedef struct
{
    int num;
    char name[30];
}STU;
void test()
{
    STU A[3]={{1,"lucy"},{2,"bob"},{3,"张三",{4,"李四"}};
    int n = sizeof(hero) / sizeof(hero[0]);
    FILE *fp = fopen("S.txt", "w");
    if (fp == NULL)
    {
         perror("fopen");
        return;
     }
    //格式化写
   int i = 0;
    for (i = 0; i < n; i++)
    {
        fprintf(fp, "%s %d \n", A[i].num, A[i].name);
    }

    fclose(fp);
}

2、格式化读 fscanf ( 文件指针,格式字符串,输出表列)

#include <string.h>
void test02()
{
    STU A[3];
    memset(A, 0, sizeof(A));
    FILE *fp = fopen("S.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return;
    }
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        fscanf(fp, "%d %s",&A[i].num, A[i].name);
    }
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%d %s\n", A[i].num, A[i].name);
    }
    fclose(fp);
}

七、文件的随机读写

文件默认是流指针顺序读写,读写顺序移动流指针 用户不能更改

                             随机读写:用户可以更改文件流指针的位置

1、顺序读写引入随机读写案例

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
	char buf[100] = "";
    //读时从流指针开始往后顺序读,会读不到字符串hello world
	fgets(buf, sizeof(buf), fp);
	printf("读到的数据:%s\n", buf);//无数据显示
	fclose(fp);
}

顺序读写解决该问题:文件关闭重新打开后流指针会复位。但文件会打开两次关闭两次。

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
    //流指针复位
    fclose(fp);
    fp=fopen("test.txt","r");
    //读取数据
	char buf[100] = "";
	fgets(buf, sizeof(buf), fp);
	printf("读到的数据:%s\n", buf);
	fclose(fp);
}

2、随机读写的API

(1)rewind复位文件流指针

void rewind(FILE *stream);

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
    //复位文件流指针
    rewind(fp);
    //读取数据
	char buf[100] = "";
	fgets(buf, sizeof(buf), fp);
	printf("读到的数据:%s\n", buf);
	fclose(fp);
}

 (2)ftell返回文件流指针 距离文件首部的 字节数

long ftell(FILE *stream);

void test()
{
	FILE* fp = NULL;
	fp = fopen("test.txt", "w+");
	if (fp = NULL)
	{
		perror("fopen");
		return;
	}
	fpus("hello world", fp);//此时流指针指向该字符串末尾
    //复位文件流指针
    long len=ftell(fp);
	printf("文件的大小:%ld\n", len);
	fclose(fp);
}

(3)fseek文件流指针定位

int fseek(FILE *stream, long offset, int whence);

 whence 定位流指针的起始位置

                文件开头 SEEK_SET 0

                文件当前位置 SEEK_CUR 1

                文件末尾 SEEK_END 2

offset:流指针的偏移量,如果为正数向右偏移(单位为字节数)为负数就是向左偏移

案例:一次性读取文件数据

主要步骤:

(1)将文件流指针定位到尾部

(2)ftell返回文件流指针的偏移量 (文件总大小len)

(3)根据文件总大小 从堆区申请空间 len+1

(4)使用fread一次性将文件数据读取 

 实现代码:

#include <stdlib.h>
#include <string.h>
void test06()
{
    FILE *fp = fopen("c.txt", "r");
    if (fp == NULL)
    {
        perror("fopen");
        return;
    }

     fseek(fp, 0, 2);
     long len = ftell(fp);
    //复位文件流指针
    rewind(fp);
    printf("文件总大小:len=%ld\n", len);

     unsigned char *text = (unsigned char *)calloc(1, len + 1);
     fread(text, len, 1, fp);

     printf("%s\n", text);
     fclose(fp);

     //释放堆区空间(不是必须操作)
     if (text != NULL)
     {
         free(text);
        text = NULL;
     }
 }

八、文件加密器

【C语言】高效处理文件内容:C语言的文件操作技巧与窍门,C/C++,算法,c语言,开发语言,学习

main.c

#include <stdio.h>
#include <stdlib.h>
#include "fun.h"

int main(int argc ,char *argv[])
{
	while(1)
	{	
		


		int cmd=0;
		print_help();
		printf("请输入指令:");
		scanf("%d",&cmd);



		if(cmd==1)
		{
			char dest_file[31]="";
			char src_file[31]="";
			unsigned long file_length=0;
			char  *read=NULL;
			unsigned int password=0;
			//从键盘获取源文件和目的文件名字
			get_file_name(dest_file,src_file);
			
			//从文件中读出内容

			read = read_src_file(&file_length,src_file);
			//获取加密password
			printf("请输入密码:");
			scanf("%u",&password);
			//字符数组加密
			read=file_text_encrypt(read,file_length,password);
			
			//保存文件
			save_file(read,file_length,dest_file);
			

		}
		else if (cmd==2)
		{
			char dest_file[31]="";
			char src_file[31]="";
			unsigned long file_length=0;
			char  *read=NULL;
			unsigned int password=0;
			//从键盘获取源文件和目的文件名字
			get_file_name(dest_file,src_file);
			
			//从文件中读出内容

			read = read_src_file(&file_length,src_file);
			//获取加密password
			printf("请输入密码:");
			scanf("%u",&password);
			//字符数组加密
			read=file_text_decrypt(read,file_length,password);
			
			
			//保存文件
			save_file(read,file_length,dest_file);
			
		}
		else if (cmd==3)
		{
			break;
		}
		else
		{
			printf("输入指令出错!!!\n");
		}

	
	}
	
	return 0;
}

 fun.c

#include <stdio.h>
#include <stdlib.h>

void print_help()
{
	printf("********1:加密文件***********\n");
	printf("********2:解密文件***********\n");
	printf("********3:退出程序***********\n");
}


void get_file_name(char * dest_file_name,char * src_file_name)
{
	printf("请输入源文件的名称:");
	scanf("%s",src_file_name);
	printf("请输入目的文件的名称:");
	scanf("%s",dest_file_name);
	return;
}


char *read_src_file(unsigned long  *file_length,char *src_file_name)
{
	char *data=NULL;
	FILE *fp;

	
	fp=fopen(src_file_name,"r");//只读的方式打开文件
	if(fp==NULL)
	{
		perror("fopen");
		return NULL;
	}
	
	//流指针go尾部
	fseek(fp,0,2);
	//流指针的偏移量
	*file_length = ftell(fp);
	//流指针复位
	rewind(fp);

	//申请空间保存文件
	data=(char *)calloc(1,*file_length);
	if(NULL==data)
	{
		perror("calloc");
		return NULL;
	}

	//一次性读
	fread(data,*file_length,1,fp);

	fclose(fp);
	return data;

}


char *file_text_encrypt(char * src_file_text,unsigned long int length,unsigned int password)
{
	char *data=NULL;
	unsigned int i=0;
	for(i=0;i<length;i++)
	{
		src_file_text[i] += password;
	}
	
	return src_file_text;

	
}


void save_file(char* text,unsigned long int length,char * file_name)
{	
	char *data=NULL;
	FILE *fp;
	fp=fopen(file_name,"w");
	if(NULL==fp)
	{
		perror("fp");
		return;
	}
	
	//写
	fwrite(text,length,1,fp);

	fclose(fp);
	if(text !=NULL)
	{
		free(text);
		text =NULL;

	}
	return;
}


char *file_text_decrypt(char * src_file_text,unsigned long int length,unsigned int password)
{
	char *data=NULL;
	unsigned int i=0;
	for(i=0;i<length;i++)
	{
		src_file_text[i] -= password;
	}
	
	return src_file_text;	
}

 fun.h文章来源地址https://www.toymoban.com/news/detail-609191.html

#ifndef __FUN_H__
#define __FUN_H__

extern void print_help();
extern void get_file_name(char * dest_file_name,char * src_file_name);
extern char *read_src_file(unsigned long  *file_length,char *src_file_name);
extern char *file_text_encrypt(char * src_file_text,unsigned long int length,unsigned int password);
extern void save_file(char* text,unsigned long int length,char * file_name);
extern char *file_text_decrypt(char * src_file_text,unsigned long int length,unsigned int password);

#endif

到了这里,关于【C语言】高效处理文件内容:C语言的文件操作技巧与窍门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言如何使用文件读写来处理文件操作?

    首先,让我们来谈谈文件读写,这听起来有点像一个神秘的活动,就像你是一个特工在阅读和修改机密文件一样!所以,假设你是一个特工小鱼,正在进行秘密任务。 首先,你需要给自己起一个特工代号。我们先把你叫做Agent007。接下来,你需要打开一个目标文件,就像你发

    2024年02月12日
    浏览(52)
  • 操作系统实验——处理机调度算法(C语言)

    目录 实验要求 代码实现 运行结果 代码解析   1、设定系统中进程数,每一个进程用一个进程控制块表示。 2、输入每个进程的“优先数”和“要求运行时间”。 3、为了调度方便,将进程按给定的优先数从大到小连成就绪队列。用一单元指出队列首进程 4、处理机调度总是选

    2023年04月27日
    浏览(42)
  • pandas DataFrame内存优化技巧:让数据处理更高效

    Pandas 无疑是我们数据分析时一个不可或缺的工具,它以其强大的数据处理能力、灵活的数据结构以及易于上手的API赢得了广大数据分析师和机器学习工程师的喜爱。 然而,随着数据量的不断增长,如何高效、合理地管理内存,确保 Pandas DataFrame 在运行时不会因内存不足而崩

    2024年03月14日
    浏览(52)
  • C 语言文件处理全攻略:创建、写入、追加操作解析

    在 C 语言中,您可以通过声明类型为 FILE 的指针,并使用 fopen() 函数来创建、打开、读取和写入文件: FILE 基本上是一个数据类型,我们需要创建一个指针变量来使用它 ( fptr )。现在,这行代码并不重要。它只是在处理文件时需要的东西。 要实际打开文件,请使用 fopen() 函数

    2024年02月03日
    浏览(47)
  • 深入探索Git的高级技巧与神奇操作(分支,高效合并)

    欢迎来到我的博客,代码的世界里,每一行都是一个故事 在软件开发的世界中,Git已经成为版本控制的标准工具。然而,许多人只使用Git的基础功能,而忽略了一些强大且令人惊叹的高级技巧。本文将带你探索Git的更深层次,让你成为Git大师。 1. 什么是强制推送? 在Git中,

    2024年02月04日
    浏览(52)
  • Java实战:高效提取PDF文件指定坐标的文本内容

    临时接到一个紧急需要处理的事项。业务侧一个同事有几千个PDF文件需要整理:需要从文件中的指定位置获取对应的编号和地址。 要的急,工作量大。所以就问到技术部有没有好的解决方案。 问技术的话就只能写个demo跑下了。 PDF的文档看起来比较简单,因为只是需要读取两

    2024年02月13日
    浏览(57)
  • 探秘C语言数组:解锁高效数据管理与多维空间编程技巧"

    ✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C语言学习 贝蒂的主页:Betty‘s blog 前面贝蒂给大家介绍了选择结构与循环结构,今天,贝蒂准备给大家介绍C语言中一个非常重要的结构——数组 数组到底是什么呢,顾名思义就是很多数的

    2024年03月09日
    浏览(55)
  • Linux命令小技巧:显示文件指定行的内容

    工作中会有很多千奇百怪的需求,比如:如何在 Linux 命令行中快速找到某个文件的第 n 行?如何显示从第 x 行到第 y 行之间的内容? 想要实现以上效果,其实有很多办法可以实现。 比如,假如要显示第 13 行内容,可以使用 head 命令组合 tail 命令,如下: 例如: 输出: 或者

    2024年02月11日
    浏览(52)
  • 【头歌】——数据分析与实践-基于Python语言的文件与文件夹管理-文本 文件处理-利用csv模块进行csv文件的读写操作

    第1关 创建子文件夹 第2关 删除带有只读属性的文件 第3关 批量复制文件夹中的所有文件 未通过本题,如果您通过了本题欢迎补充到评论区,有时间我会整理进来 第1关 读取宋词文件,根据词人建立多个文件 第2关 读取宋词文件,并根据词人建立多个文件夹 第3关 读取宋词文

    2024年01月25日
    浏览(73)
  • R语言【技巧】——判断自定义函数的传参内容是否符合要求

    比如 对一个应该传入 数值型 ,数值为 0 或 1 的参数: 比如 对一个应该传入 字符型 ,字符串为 某个向量元素之一 的参数,类似于选项框:

    2024年01月23日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包