【C语言进阶(NEW)】六、文件操作(一)|文件|文件的打开和关闭|文件的顺序读写|文件读取结束的判定

news2024/11/24 15:19:34

目录

一、文件

1.1 什么是文件

1.1.1 程序文件 

1.1.2 数据文件

1.2 为什么使用文件

1.3 文件名

二、文件的打开和关闭

2.1 文件指针

2.2 文件的打开和关闭

三、文件的顺序读写

3.1 fgetc 和 fputc(字符输入输出函数)

3.2 fgets 和 fputs(文本行输入输出函数)

3.3 fscanf 和 fprintf (格式化输入输出函数)

3.4. fread 和 fwrite(二进制输入输出函数)

四、文件的随机读写

4.1 fseek

4.2 ftell

4.3 rewind

五、文件读取结束的判定


一、文件

1.1 什么是文件

        磁盘上的文件是文件。但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)

1.1.1 程序文件 

        包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe) 

1.1.2 数据文件

        文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件

        本次讨论的是数据文件,之前所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上

        其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件

1.2 为什么使用文件

        数据持久化的问题,我们一般数据持久化的方法有,把数据存放在磁盘文件、存放到数据库等方式。使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化

1.3 文件名

        一个文件要有一个唯一的文件标识,以便用户识别和引用。文件名包含3部分:文件路径+文件名主干+文件后缀例如: c:\code\test.txt ,为了方便起见,文件标识常被称为文件名

二、文件的打开和关闭

2.1 文件指针

        缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”

        每个被使用的文件都在内存中开辟了一个相应的文件信息区用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名 FILE

例如,VS2013 编译环境提供的 stdio.h 头文件中有以下的文件类型申明 

struct _iobuf {
    char *_ptr;
    int _cnt;
    char *_base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char *_tmpfname;
};
typedef struct _iobuf FILE;

         不同的C编译器的 FILE 类型包含的内容不完全相同,但是大同小异

        每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节

        一般都是通过一个 FILE 的指针来维护这个FILE结构的变量,这样使用起来更加方便 

创建一个 FILE* 的指针变量

FILE* pf;//文件指针变量

        定义 pf 是一个指向 FILE 类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件

2.2 文件的打开和关闭

        文件在读写之前应该先打开文件,在使用结束之后应该关闭文件

        在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系

//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );

这两个函数的头文件是 stdio.h

fclose 函数,参数是关闭文件的名字

fopen 函数第一个参数是打开文件的名字,第二个参数是访问打开模式,文件打开失败返回 NULL

访问打开模式的方式如下

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建议一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

测试代码

#include <stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "w");
	
	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	//对文件进行一系列操作
	//...

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

三、文件的顺序读写

文件按顺序读写的函数有:

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输入流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输入流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输入流
二进制输入fread文件
二进制输出fwrite文件

3.1 fgetc 和 fputc(字符输入输出函数)

(1)fputc

int fputc( int c, FILE *stream );

        fputc函数的第一个参数是待输出的字符,第二个参数该字符输出的位置,即fputc函数的功能是将一个字符输出到指定的位置。该函数调用完毕会返回用户传入的字符

例如,我们要将小写字母 a~z 写入到 myfile.txt 文件中

#include <stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "w");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	//对文件进行一系列操作
	
	char i = 0;
	for (i = 'a'; i <= 'z'; i++)
	{
		fputc(i, pf);
	}

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

(2)fgetc 

int fgetc( FILE *stream );

        fgetc 函数只有一个参数,即你要读取的文件的文件指针。fgetc 函数的功能就是从指定位置读取一个字符。该函数调用成功会返回读取到的的字符;若读取文件时发生错误,或是已经读取到文件末尾,则返回 EOF

例如,我们要将文件 myfile.txt 文件中的内容读取,并打印到屏幕上

#include <stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "r");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		printf("%c", ch);
	}

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

3.2 fgets 和 fputs(文本行输入输出函数)

(1)fputs

int fputs( const char *string, FILE *stream );

        fputs函数的第一个参数是待输出的字符串,第二个参数该字符串输出的位置,即fputs函数的功能是将一个字符串输出到指定的位置。该函数调用成功会返回一个非负值;若输出时发生错误,则返回EOF

例如,我们要将字 "hello world!" 写入到 myfile.txt文件中 

#include <stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "w");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	char arr[] = "hello world!";
	fputs(arr, pf);

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果 

(2)fgets

char *fgets( char *string, int n, FILE *stream );

        fgets 函数的第一个参数是你所读取到的数据的储存位置,第二个参数是你要读取的字符个数,第三个参数是你要读取的文件的文件指针。fgets 函数的功能就是从指定位置读取指定字符个数的数据储存到指定位置。该函数调用成功会返回用于储存数据的位置的地址,如果读取过程中发生错误,或是读取到了文件末尾,则返回一个空指针 NULL

例如,我们要从 myfile.txt 文件中读取数据

#include <stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "r");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	char arr[10] = { 0 };
	fgets(arr, 6, pf);
	printf("%s\n", arr);

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

        注意:对于 fgets 函数来说,实际从文件中读取的字符的个数会比指定的字符个数少一个,因为最后一个字符会被用于字符串的结束标志’\0’ 

        fgets 函数读取到指定字符数之前,若读取到换行符(’\n’),则停止读取,读取带回的字符包含换行符

3.3 fscanf 和 fprintf (格式化输入输出函数)

(1)fprintf

int fprintf( FILE *stream, const char *format [, argument ]...);

fprintf 函数的第一个参数是数据输出的目的地,后面的参数是可变参数列表,像 printf 一样使用即可,fprintf 只不过多了第一个参数

//printf函数的声明
int printf( const char *format [, argument]... );

 例如,我们要将一个结构体类型的变量信息 输出到 myfile.txt文件中去

#include<stdio.h>

struct People
{
	char name[20];
	char sex[5];
	int age;
};

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "w");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	struct People p1 = { "zhangsan", "nan", 26 };
	fprintf(pf, "%s %s %d\n", p1.name, p1.sex, p1.age);

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

(2)fscanf

int fscanf( FILE *stream, const char *format [, argument ]... );

 fscanf函数的第一个参数是读取数据的位置,后面的参数是可变参数列表,像 scanf一样使用即可,fscanf 只不过多了第一个参数

//scanf 定义
int scanf( const char *format [,argument]... );

 例如,我们要将刚才用 fprintf 函数输出到 myfile.txt 文件中的数据读取出来

#include<stdio.h>

struct People
{
	char name[20];
	char sex[5];
	int age;
};

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "r");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	struct People tmp = { 0 };
	fscanf(pf, "%s %s %d", tmp.name, tmp.sex, &(tmp.age));
	//将tmp中的内容打印出来,看是否读取成功
	printf("%s %s %d\n", tmp.name, tmp.sex, tmp.age);

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

3.4. fread 和 fwrite(二进制输入输出函数)

(1)fwrite函数

size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

        fwrite 函数的第一个参数是输出数据的位置,第二个参数是要输出数据的元素个数,第三个参数是每个元素的大小,第四个参数是数据输出的目标位置。该函数调用完后,会返回实际写入目标位置的元素个数,当输出时发生错误或是待输出数据元素个数小于要求输出的元素个数时,会返回一个小于 count 的数

例如,我们要将数组 arr中的10个元素以二进制的形式输出到 myfile.txt 文件中去 

#include<stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "w");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	fwrite(arr, sizeof(int), 10, pf);

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

 运行结果

(2) fread

size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

        fread 函数的第一个参数是接收数据的位置,第二个参数是要读取的每个元素的大小,第三个参数是要读取的元素个数,第四个参数是读取数据的位置。函数调用完会返回实际读取的元素个数,若在读取过程中发生错误或是在未读取到指定元素个数时读取到文件末尾,则返回一个小于count的数

例如,我将刚才用 fwrite 函数输出到 myfile.txt文件的数据读取出来

#include<stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "r");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	int arr[10] = { 0 };
	fread(arr, sizeof(int), 10, pf);
	//将arr中的内容打印出来,看是否读取成功
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

四、文件的随机读写

        在上面我们介绍了文件顺序读写的相关函数及其操作,上面只能按照顺序进行读写,所以还得学会文件的随机读写,提高对文件中的数据的访问效率

4.1 fseek

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

        fseek函数的第一个参数既是要移动位置的文件指针,第三个参数是“初始位置”(并非文件信息区的起始位置),第二个参数是文件指针经操作后相对于这个“起始位置”的偏移量,单位为字节。fseek函数如果调用成功,则返回0;若调用失败,则返回一个非0的值

关于fseek函数的第三个参数,可以有以下三种形式

用 fseek函数,对文件中的数据 “abcdefg”进行操作,使其下一次读取字符时能读取到字符’d’,则有以下三种写法 

(1)让文件指针相对于文件开头偏移3个字节(即指向文件开头)

fseek(pf, 3, SEEK_SET);//调整文件指针位置
ch = fgetc(pf);//读取到字符'd'
printf("%c\n", ch);

 (2)让文件指针相对于文件末尾向前偏移 -3个字节

fseek(pf, -3, SEEK_END);//调整文件指针位置
ch = fgetc(pf);//读取到字符'd'
printf("%c\n", ch);

4.2 ftell

long ftell( FILE *stream );

        ftell 函数的参数是一个文件指针。ftell函数调用成功,则返回文件指针相对于起始位置的偏移量;若调用失败,则返回 - 1,它用于计算当前文件指针相对于起始位置的偏移量

例如,对文件中的数据 “abcdefg”,读取了三个字符后,文件指针 pf 相对于起始位置的偏移量,可以这样计算,此时,变量Offset中存放的就是pf指针相对于起始位置的偏移量

long Offset = ftell(pf);

4.3 rewind

void rewind( FILE *stream );

        rewind函数的作用是让传入的文件指针返回文件的起始位置

例如,对文件中的数据 “abcdefg”,读取了三个字符后,文件指针 pf 在 ‘d’ 的位置,想让文件指针 pf 直接返回文件的起始位置,使用该函数即可

rewind(pf);//调整文件指针位置

五、文件读取结束的判定

被错误使用的 feof, feof 头文件也是 stdio.h

int feof( FILE *stream );

        feof 函数的功能也是判断使用某一文件指针的过程中,是否读取到文件末尾,若使用时没有读取到文件末尾,则feof函数返回0;否则,feof函数将返回一个非零的值。调用feof函数时,也只需将待检查的文件指针传入即可

        注意:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束,而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束

if (feof(pf))
{
	printf("文件指针使用时,读取到文件末尾\n");
}

 注意函数的返回值

ferror 函数

int ferror( FILE *stream );

        ferror 函数的功能就是判断使用某一文件指针的过程中,是否发生错误,若使用时没有发生错误,则ferror函数返回0;否则,ferror函数将返回一个非零的值。调用ferror函数时,我们只需将待检查的文件指针传入即可,头文件也是 stdio.h

if (ferror)
{
	printf("文件指针使用时,发生错误\n");
}

feof 函数的正确使用

#include<stdio.h>

int main()
{
	//打开文件
	FILE* pf = fopen("myfile.txt", "r");

	//文件打开失败
	if (pf == NULL)
	{
		perror("fopen");//输出失败原因
		return 1;
	}

	//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF) // 标准C I/O读取文件循环
	{
			printf("%c", ch);
	}

	//循环结束,判断是什么原因结束的
	if (ferror(pf)) 
	{
		//ferror(fp)为真,说明由读取失败引起
		printf("I/O error when reading");
	}
	else if (feof(pf))  
	{
		//feof(fp)为真,说明由遇到文件尾引起
		printf("End of file reached successfully");
	}
		
	//关闭文件
	fclose(pf); //关闭pf指向的文件
	pf = NULL;//及时置空

	return 0;
}

运行结果

----------------我是分割线---------------

文章到这里就结束了,下篇即将更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154545.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20行原生JS代码手写ElementUI表格组件

又是许久没有写博客了&#xff0c;这几年的疫情&#xff0c;总是居家&#xff0c;时间久了&#xff0c;慢慢的总会想很多。现在越发觉得想做的事情一定要尽早去做&#xff0c;不然总说等下一次&#xff0c;很多时候&#xff0c;就没有下一次了。 今天给大家分享一下如何用原生…

从0到1完成一个Vue后台管理项目(十七、使用Echarts:柱状图、折线图)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

DB性能跟不上,加缓存就够了?

服务端软件开发时&#xff0c;通常会把数据存储在DB。而服务端系统遇到的第一个性能瓶颈&#xff0c;往往发生在访问DB时。 这时大部分开发会拿出“缓存”&#xff0c;通过使用Redis在DB前提供一层缓存数据&#xff0c;缓解DB压力&#xff0c;提升服务端性能。 在数据库前添加…

nohup后台运行,进程查看与终止(ubuntu)

1.nohup用途&#xff1a;不挂断地运行命令。语法&#xff1a;nohup Command [ Arg … ] [ & ]无论是否将 nohup 命令的输出重定向到终端&#xff0c;输出都将附加到当前目录的 nohup.out 文件中。如果当前目录的 nohup.out 文件不可写&#xff0c;输出重定向到 $HOME/nohu…

threejs 学习一

前提 threejs官网&#xff1a;https://threejs.org/ 由于官网访问慢&#xff0c;可以github下载压缩包解压后本地启动 github地址&#xff1a;https://github.com/mrdoob/three.js/ 下载好后解压 安装依赖 npm install 启动&#xff1a;npm start 目录介绍&#xff1a; …

语音识别技术简叙述

语音识别技术简述 语音识别的概念 语音识别技术都是让智能设备能够听懂人类语言&#xff0c;其实一门涉及数学信号处理、人工智能、语言学、数理统计学、声学、情感学及心理学等多学科交叉的学科。这项技术可以提供比如自动客服、自动语音翻译、命令控制&#xff0c;语音验证…

【vue】关于vue2和vue3响应式原理的区别

我们都知道&#xff0c;在Vue2中的数据响应式原理存在许多缺陷。 例如无法对新增和直接删除的数据做到响应式&#xff0c;无法直接操作数组进行响应式处理等等。 而在Vue3中&#xff0c;作者很好的解决了这些缺陷&#xff0c;让我们来对比一下Vue2与Vue3对数据响应式处理的具体…

前端如何保证设置的font-family成功生效?

背景 最近开发的一个新页面&#xff0c;在产品验收的时候跟我反馈说页面里的字体跟设计稿中的字体不一样&#xff1b; 问题的关键是我明明记得我有单独设置过 font-family属性&#xff0c;于是我通过Chorme浏览器的调试工具查看了一下DOM的生效样式&#xff1b; 明明是已经设…

IDEA、TortoiseSVN,TortoiseGit提交忽略文件或文件夹

使用IDEA 的SVN插件提交文件是总是会提交一些不需要提交的文件; 我们可以通过一些简单设置忽略这些文件&#xff1a; 1、IDEA 1、idea设置<<--File Types<<--ignore files and folders 原有的过滤条件&#xff1a;*.hprof;*.pyc;*.pyo;*.rbc;*.yarb;*~;.DS_Store…

yolov3-tiny的darknet权重转onnx

前言 之前一直鸽了yolov3-tiny的onnx模型修复&#xff0c;今天终于把最后一个bug解决了&#xff0c;如果想直接享受成果的&#xff0c;直接点我的github仓库下载&#xff0c;使用说明都写了&#xff0c;这篇文章呢主要是给大家分享一下思路和过程&#xff0c;希望能够启发更多…

初识Linux

文章目录初识Linux操作系统概述硬件和软件操作系统常见操作系统总结初识LinuxLinux的诞生Linux内核Linux发行版总结虚拟机介绍虚拟机总结远程连接Linux系统图形化、命令行使用命令行学习Linux系统远程连接工具总结初识Linux 操作系统概述 硬件和软件 我们所熟知的计算机是由…

领域驱动设计:微服务设计为什么要选择DDD?

我们知道&#xff0c;微服务设计过程中往往会面临边界如何划定的问题&#xff0c;我经常看到项目团队为微服务到底应该拆多小而争得面红耳赤。不同的人会根据自己对微服务的理解而拆分出不同的微服务&#xff0c;于是大家各执一词&#xff0c;谁也说服不了谁&#xff0c;都觉得…

Day855.生产者-消费者模式 -Java 并发编程实战

生产者-消费者模式 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于生产者-消费者模式的内容。 Worker Thread 模式类比的是工厂里车间工人的工作模式。 但其实在现实世界&#xff0c;工厂里还有一种流水线的工作模式&#xff0c;类比到编程领域&#xff0c;就是生…

RoboMaster EP 实用功能开发(三): 基于树莓派的ROS2机器人系统搭建

功能&#xff1a;在树莓派4b上安装ros2系统&#xff0c;引入robomaster sdk&#xff0c;搭建一个基于ROS2的机器人系统&#xff0c;用于ROS系统的学习、开发和实践。 硬件&#xff1a;RobotMaster EP、树莓派4b 系统平台&#xff1a;Ubuntu 20.04、ROS2&#xff08;Foxy&…

Selenium【Selenium环境搭建与Junit5】

Selenium【Selenium环境搭建与Junit5】&#x1f34e;一. 自行下载谷歌浏览器或者火狐浏览器&#x1f352;1.1 安装好之后需要去掉谷歌(火狐)浏览器自动更新(建议)&#x1f352;1.2下载谷歌(火狐)驱动&#x1f34e;二.Selenium下载与配置&#x1f352;2.1Selenium下载&#x1f3…

服务案例|SQL Server数据库监控反复重启问题

监控平台对主流数据库的监控&#xff0c;能够及时发现异常&#xff0c;快速响应&#xff0c;保障业务系统的稳定。平台通过对SQL Server数据库监控&#xff0c;帮助用户在数据库出现异常时事件处理。 SQL Server数据库监控内容如下 1 、数据库服务器基本性能监控。包括&#…

Hive/MaxCompute SQL性能优化(三):数据倾斜优化实战

SQL性能优化系列&#xff1a;Hive/MaxCompute SQL性能优化(一)&#xff1a;什么是数据倾斜Hive/MaxCompute SQL性能优化(二)&#xff1a;如何定位数据倾斜前面介绍了如何定位数据倾斜&#xff0c;本文介绍如果遇到各种数据倾斜的情况该怎样优化代码。Map长尾优化一、Map读取数据…

ArcGIS如何将Excel表格转换为SHP格式

概述数据的获取渠道是多种多样的&#xff0c;获取的数据格式也是多种多样&#xff0c;作为一名GISer&#xff0c;需要熟练掌握各种格式的数据之间的转换&#xff0c;例如本文要介绍的Excel格式的数据&#xff0c;经常会遇到&#xff0c;这里为大家介绍一下转换方法&#xff0c;…

区块链基础知识(二)

密码学与安全技术 参考书籍 《区块链原理、设计与应用》 Hash算法 加解密算法 混合加密机制 离散对数与Diffie-Hellman秘钥交换协议 消息认证码 数字签名 PKI体系 PKI基本组件 证书签发 证书的撤销 Merkle tree结构 默克尔树逐层记录哈希值的特点&#xff0c;让它具有了一些独特…

【我的渲染技术进阶之旅】关于C++轻量级界面开发框架Dear ImGui介绍

文章目录一、怎么知道ImGui的1.1 Filament中有使用ImGui1.2 其他很多渲染框架都有使用ImGui二、ImGui介绍2.1 ImGui风格2.2 Imgui介绍2.2.1 Imgui简介2.2.2 Imgui用法2.2.3 Demo示例2.2.4 集成2.2.5 更多案例2.3 查看Imgui实例源代码2.3.1 运行demo2.3.2 项目结构分析2.3.3 示例…