C语言中的文件操作那些事儿~~

news2025/1/12 23:05:42

是时候该学着操作文件了

  • 什么是文件
    • 文件种类
    • 文件名
  • 为什么要使用文件
  • 文件的打开和关闭
  • 文件的顺序读写
    • fgetc/fputc
    • fgets/gputs
    • fscanf/fprintf
    • fread/fwrite
  • 文件的随机读写
    • fseek
    • ftell
    • rewind
  • 文件读取结束的判断
  • 文件缓冲区

男人过了二十岁就要学着沉稳,遇到问题不要慌,虽然我们看着目录可能都要咽一口口水,但是想一想都是为了前程,吃点苦又何妨呢?

什么是文件

文件种类

大家看到这个问题是不是都要一愣?
在这里插入图片描述
在大家的印象里面文件是不是都是上面这样一个个的小黄口袋?浅了。上面的都是一个又一个文件夹,整整意义上的文件按照功能可以分为程序文件和数据文件:
在这里插入图片描述
在这里插入图片描述
像这样的以.c .obj .exe的后缀的文件都叫做程序文件,点进去就可以在对应环境下面跑程序的。
数据文件,顾名思义就是我们创建出来存储数据的,我们之前在VS2019里面创建了成千上万的变量,等到今天兄弟们看完我的这篇博客基本上就可以实现存储数据到文件的操作了!

文件名

兄弟们看到一个文件要是说起文件名肯定就是老实巴交地人家显示什么就读什么吧,可不敢这么老实啊!
在这里插入图片描述
在这里插入图片描述
有的时候电脑的使用者常常被自己的一些操作所迷惑,比如这里,不妨把这么东西勾勾选选不影响我们年入百万的!!!
文件名其实由三块构成:文件路径+文件名主干+文件后缀
在这里插入图片描述
一般来说我们口头的文件名仅仅是文件名的主干部分啊!
稍作了解一下!

为什么要使用文件

有没有发现只要是为什么有诸如此类的问题,都可以用存在即合理这一句话来概括。
兄弟们想一想,我们之前是不是讲过生命周期这个概念?如果我们的程序结束并且我们还不对已经存储好的数据进行任何处理,那不管是什么变量什么常量,它的生命周期肯定就结束了,那么它的短暂的一生就这么结束了,只是为了帮助我们解决问题而存在,就连走的时候都不曾掀起一点波澜,专业点就是内存在程序结束之后都会自动还给操作系统,但是对于一些数据我们希望它能够长久地存在啊,这就需要介绍一下我们的文件了!跟普通的变量不同,我们的文件并不依靠内存而存在,我们的文件都是放在C盘D盘这种磁盘上的,只要磁盘不坏,我们的数据就会以文件的形式一直存在!这就是文件存在的价值!

文件的打开和关闭

在进行文件操作之前,我们都是需要进行打开文件的,不然程序怎么读得懂你的故作矜持呢?
在这里插入图片描述
fopen函数就可以帮助我们打开文件:
在这里插入图片描述
这里我们先讲一下这个打开方式:

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

这是阿涛学习的时候老师给我们总结的经验,使用老师讲解的知识应该不算侵犯知识产权吧……
这里给大家强调一下:如果是多个字符还好,兄弟们都应该知道了C语言是没有字符串类型的,但是 “ ” 括起来的内容就是字符串,如果像上面的 ***‘ w ’***这就麻烦了,我真怕兄弟们还是有那个思维定势啊,上去看到字符就用单引号括起来,我们这里参数的类型写的好好的 char* 类型啊,怎么可以传的是一个字符类型的变量呢?这么一思考应该就很容易理解了吧?
在这里插入图片描述
现在我们再来讲第一个变量:const char * filename这里的意思即使让我们输入一个字符串,这个字符串就是文件名。如果我们严格遵守文件名的定义,完完整整地输入那么长的文件名自然是极好的,但是如果我们图省事,也可以不输入文件路径,这样子编译器就会自动帮我们在当前工程下面创建!
老观众都应该知道阿涛喜欢讲解返回类型参数这些东西,这些东西其实就已经包含了很多信息了,就比如现在我们看到了一个从未见过的返回类型:FILE *,首先我们可以确认的是这个 fopen 函数最后会返回一个指针类型!这样吧我们先来上手打开一波文件再来细说!

	FILE* P = fopen("text.txt", "w");

在这里插入图片描述

在这里我们来选中FILE并且转到定义来看一看FILE究竟是何方神圣!

在这里插入图片描述
这里由于vs2019已经相当高级了,所以我们是没有办法完整看到这个FILE的阵容的,不过我们还是可以直观感受出来,这个神秘的FILE其实本质上就是一个结构体类型重命名得来的,其实里面包含的就是我们创建的这个文件的一些信息,当然了这些东西有些过于深入,就连我都还没有学到,我怀疑当初我的老师也没有学到所以才会让我们不用学的那么深入……哈哈,瞎说的呢!
所以说,每当我们打开一个文件的时候,系统都会自动创建一个FILE类型的(结构体类型)的变量,并且会自动填充好文件的一些信息,并且会返回一个FILE类型的指针变量便于我们程序员进行管理!
通过溯源的思想,我们是不是就可以通过FILE
类型的指针找到系统为我们创建的那个FILE类型的文件信息区,然后再通过文件信息区是不是就可以很方便地管理我们的文件了?
兄弟们还记不记得,就在上一片博客我们还说到过动态内存的相关知识,如果我们动态内存开辟失败,会返回一个空指针,这时候就不能一顿操作了,然后我们还需要手动释放动态内存并亲自把指针置为空?我只能说,学完文件操作之后你会惊讶地发现我们的文件操作和动态内存在整体的结构上面是高度相似的:同样需要判断返回的指针是否为空,同样需要自己关闭文件!

	FILE* p = fopen("text.txt", "w");
	//判断文件是否打开成功
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	//操作文件
	
	
	//关闭文件
	fclose(p);

这就是我们文件使用的大概流程了!

那么肯定有兄弟会有这样的一个疑问:为什么我们对文件进行操作的时候需要手动打开关闭,但是对于像鼠标键盘这样的外设的时候就不需要了呢?
那是因为对于任何一个C语言,只要运行起来就会默认打开三个流:
1.stdin–标准输入流–键盘
2.stdout–标准输出流–屏幕
3.stderr–标准错误流–屏幕

文件的顺序读写

在这里插入图片描述
关于文件的读写阿涛还是有一些心得的,毕竟刚开始的时候阿涛也是被这个东西搞得头疼的要死!
现在我们还是可以进行类比,当我们内存中还什么都没有的时候,这种时候我们需要键盘输入或者是从文件中读取数据,就叫做输入,如果此时我们的内存之中有了数据了,我们想要把数据展示出去,就需要输出,或者说写!有人这时候就在举手手了!阿涛,你看啊我们从键盘上面敲出去的那么多代码,这难道不是我们在“写”代码嘛?怎么能叫读呢?请注意,我们所说的读或者是写,都是对于内存来说的,此时此刻内存中空空如也,请问你想让内存给你写什么?

fgetc/fputc

在这里插入图片描述
在这里插入图片描述
现在我们应该已经轻车熟路了,打印字符用“%c”,所以我们应当善于记忆,这边后面是以c结尾,是不是可以联想成跟字符有关呢?或许使用一次读写一个字符?是的没错!我们将会在代码中给兄弟们讲解。

	FILE* p = fopen("10.21.txt","w");//这里我们的想法是把数据先写到我们的记事本里面,
	//然后我们才可以从记事本里面读取数据
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	for (int i = 0;i < 5;i++)
	{
		putc('a' + i, p);//本来我们这里第一个参数的类型应该是int的,而我们的使用的虽然是字符,
		//但是本质上也是字符的ASCII码值,第二个参数指的是文件流,这里刚才我也搞错了,我把文件名
		//给敲了上去,发现不是很对劲,所以我又去看了一下,这里应该是FILE* 的那个指针
		//我们这步就是把自a往后面的五个字符存储到我们的文件里面

下面我们来见证奇迹:
在这里插入图片描述
是不是完美实现了我们的愿景?当然了这个记事本要到你创建的项目那里面去找哦!
别着急,奇迹还没有结束!我们下面就要从这个文件里面把数据拿出来,拿到我们的内存里面!

	FILE* p = fopen("10.21.txt", "r");//这里是以读的方式打开文件,关于读写,可以看看上面的分析
	if (p == NULL)
	{
		perror("fopen:");
		return 1;//异常返回返回的是一
	}
	int ch=0;
	for (int i = 0;i < 5;i++)
	{
		ch = getc(p);//getc的参数只有一个,就是我们的文件流
		printf("%c ",ch);
	}
	fclose(p);

在这里插入图片描述
这里我们已经是把上次写的代码屏蔽掉了,所以我们现在所得到的完完全全就是我们从记事本里面读取到的数据!

fgets/gputs

在这里插入图片描述
在这里插入图片描述
如果c是表示字符,那么我们的s是不是就应该表示字符串?差不多吧……这哥俩叫做文本行输出输入流,就是一行一行操作!

	FILE* p = fopen("10.21.txt", "w");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	char a[] = {"abcd\nef"};//这里为什么要加上一个\n呢?为了测试文本行的行究竟是什么意思
	fputs(a,p);
	fclose(p);
	return 0;

在这里插入图片描述
这里可以看到我们的文件里面就呈现了我们刚才输出的数据,没有遇到\n就停下来,说明我们的fputs是找到\0为止的!
这里我们还可以发现,每当我们重新以写的方式打开一个文件的时候好像把上一个文件残留的部分给覆盖掉了,如果你不想进行覆盖可以考虑用“r+ ”进行追加!

	char s[10] = {0};//本来我想着设计一个指针的,但是出现了问题
	//程序会报错说s可能是一个NULL
	fgets(s, 5, p);//我们的想法是从文件里面把数据拿到我们的内存中,我们就用s来接收
	//那这中间的过程肯定会包括一个解引用,这时候如果是对NULL
	//进行解引用操作那不是乱来吗?所以我们退而求其次,用数组来解决!
	printf("%s",s);
	fclose(p);

在这里插入图片描述
请注意,这里我们是不是明明想要程序输出五个数据,但是我们的数据此时只给了我们四个数据,再来试一试:
在这里插入图片描述
依旧只给了我们四个,所以说这就是我们文本行输入的由来,是按照一行来办的,也就是我们找的是\n。此时此刻是不是有好奇宝宝想问那如果我们还没有读到那个\n咋办啊!
我知道你很急,但是你先别急!我来给兄弟们演示:

	fgets(s, 2, p);
	printf("%s\n", s);
	fgets(s, 3, p);
	printf("%s\n", s);

在这里插入图片描述
欸,从这一次和上一次我们输出的结果来看,我们是不是发现了一点端倪?为什么第一次我们明明想要fgets是的六个字符,但是只出来了 “abcd” 四个字符呢?为什么我们第二次选择了两次fgets又会出现这种情况呢?
我们之前说过的,fgets是文本行输入,是按照行来办的,找的是\n并非\0,但是我们是把一个字符串给放到我们的数组里面,只要是数组是不是就要以 ‘’\0结尾啊?那我们本来要读取六个字符,但是去除最后一个‘\0’,实际上我们能放的最多只有五个字符,而且如果我们已经找到了 ‘\n’,即使后面我们还有空间也不会读取下一行的数据了,直接一个‘\0’潇洒结尾就完事了!
而且兄弟们,看我们第二次敲出来的东西,是不是好像我们并没有对文件进行任何操作,它就自己从a跳到了b啊?这也就说明了fgets会有内部机制,大概就是每当我们调用完一次fgets,它内部的指针都会自动从结束处往下移动一个单位,不然你没法解释第二行是从‘b’开始的!

fscanf/fprintf

那我们的数据类型不光光是一个字符类型,不可能一直fgetc/fgets,万一我们要输的是一个整型?是一个结构体?那其中的格式又该做如何处理?
不要苦恼!前人之述备矣!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
printf和scanf都是老朋友了,大家在使用上面肯定不会陌生了,但是兄弟们不一定熟悉fprintf和fscanf,这里我们把这四者联合起来看,你会有一种后豁然开朗的感觉!好像文件的格式读写就是增加了一个文件流的参数啊!
那我们就好办了:

struct stu
{
	char name[10];
	int age;
	double fee;
};

	FILE* p = fopen("10.21.txt", "w");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	struct stu qxy = { "qxy",20,0.0 };
	fprintf(p, "%s %d %f", qxy.name, qxy.age, qxy.fee);
	fclose(p);

在这里插入图片描述
大家看着那个fprintf,是不是有一种特别熟悉的感觉?是不是就和我们的printf如出一辙?
别急,下面我们还会给大家表演一波,从文件中读取信息:

	FILE* p = fopen("10.21.txt", "r");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	struct stu cyt = {0};
	fscanf(p, "%s %d %lf", cyt.name, &cyt.age, &cyt.fee);//这里不是数组名的记住要加上&
	//scanf使用的时候如果是一个double类型的记得使用ld!
	printf("%s %d %f",cyt.name,cyt.age,cyt.fee);
	fclose(p);
	
	fclose(p);

在这里插入图片描述
此时此刻我们是不是完整地从文件中读取了有格式的数据?

fread/fwrite

之前给大家看过一张文件使用的图标,其中是不是有 “wb”和“rb” 啊,当时后面的解释是以二进制形式读写,那我们一下子就来精神了,以二进制读写这是个什么东西啊?
在这里插入图片描述
在这里插入图片描述
别看这两个函数的参数似乎有一点多,都是纸老虎,对于我们上手来使用的人来说没有一点难度:

	FILE* p = fopen("10.21.txt", "wb");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	struct stu cyt = {"qxy",20,0.0};
	fwrite(&cyt,1,sizeof(struct stu),p);
	fclose(p);
	
	fclose(p);

在这里插入图片描述
虽然我们嘴上说的是二进制我们人眼是很难看懂的,但是有些二进制其实我们也是能看得懂的哈……
那我们再来给兄弟们演示一波:

	FILE* p = fopen("10.21.txt", "wb");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	char arr[10] = { 1,2,3,4,5 };
	//struct stu cyt = {"qxy",20,0.0};
	//fwrite(&cyt,1,sizeof(struct stu),p);
	fwrite(arr, sizeof(arr), 1, p);

	fclose(p);
	}

![在这里插入图片描述](https://img-blog.csdnimg.cn/c23328c9f3484dcc87db1db11acecfd6.png

这个我不相信兄弟们能够看得出来是什么东西了吧……
人眼虽然识别不出来二进制代码的信息,但是我们的是计算机最擅长的事情就是处理二进制数据啊!
见证奇迹!

FILE* p = fopen("10.21.txt", "rb");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	char arr[10] = {0};

		fread(arr, sizeof(arr), 5, p);
		for (int i = 0;i < 5;i++)
		{
			printf("%d ",arr[i]);
		}
	

	fclose(p);

在这里插入图片描述
兄弟们来看一看,是不是正如我们所说,计算机完美识别出了二进制里面的信息?
那我们刚才还有一个结构体类型的,也顺手打印一下!
在这里插入图片描述

文件的随机读写

fseek

我们之前的读写全都是特别死板的从文件的开始往后一个一个字符的读写,但是我们程序员就是程序里面的king,我们拥有相当大的自主权,只要自己的水平足够,只要执行的操作时程序所认可的,我们就可以做到一些很神奇的事情,就比如这里的随机读写:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
就比如我现在已经自己在文件里面写好了内容了,我想要直接读取这个c,我该怎么办?

	FILE* p = fopen("10.21.txt", "r");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	fseek(p, 2, SEEK_SET);
	int ch = fgetc(p);
	printf("%c",ch);
	fclose(p);
	return 0;

在这里插入图片描述
SEEK_SET表示从文件指针开始偏移
SEEK_END表示从文件指针末尾偏移
SEEK_CUR表示从当前指针位置偏移
为什么会有当前位置一说呢?兄弟们还记不记得我们的fgetc每当我们读取完一个字符后,它都会悄悄地给我们把字符往后移动一格,是不是就有了当前位置这个说法?
兄弟们还要记住一点,fseek函数是支持正负偏移的,正表示向后,负表示向前!

ftell

在这里插入图片描述
ftell是能够告知我们,我们当前指针的位置相较于起始位置偏移了多少!

说起来好像不是很难啊,来兄弟们读一下这段代码:

	FILE* p = fopen("10.21.txt", "r");
	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	int ch = fgetc(p);
	printf("%c\n",ch);
	fseek(p, 2, SEEK_CUR);
	ch = fgetc(p);
	printf("%c\n",ch);
	printf("%d\n",ftell(p));
	fclose(p);
	return 0;

偏移量是多少?
是不是1+2=3?
在这里插入图片描述
兄弟们看好,最后我们还使用了一次fgetc,因此,我们的指针在最后时刻还是往后面偏移了一下!

rewind

有缘之人可以逆转时光回到过去 在我们的C语言里面,还真的有类似于回到过去的操作,就是我们的 rewind
在这里插入图片描述

	if (p == NULL)
	{
		perror("fopen:");
		return 1;
	}
	int ch = fgetc(p);
	printf("%c\n",ch);
	fseek(p, 2, SEEK_CUR);
	ch = fgetc(p);
	printf("%c\n",ch);
	printf("%d\n",ftell(p));
	rewind(p);
	printf("%d\n", ftell(p));
	fclose(p);
	return 0;

在这里插入图片描述
我很希望这个世界上真的反方向的钟是真的存在的,或者说我可以拥有操控时间的能力,不是为了回到过去改变过去,只是为了回到那个爱你的时空,回到你爱我的时空!
虽然现实中不存在这种超能力,好歹我们的C语言帮助我们圆了一个梦,所以我们更要好好学习啊!

文件读取结束的判断

在这里插入图片描述
兄弟们一定要注意啊,这个函数不是为了判断我们的文件是否读取结束,而是我们的文件此时此刻已经读取结束了,我们用它来判断函数结束的原因,是遇到什么错误?还是读取完了整个文件,事了拂身去,深藏功与名。
这里我们直接使用cpp网站上面的代码给兄弟们讲解:

/* feof example: byte counter */
#include <stdio.h>

int main ()
{
  FILE * pFile;
  int n = 0;
  pFile = fopen ("myfile.txt","rb");
  if (pFile==NULL) perror ("Error opening file");
  else
  {
    while (fgetc(pFile) != EOF) {//循环表示如果fgetc没有返回EOF就会继续
      ++n;
    }
    if (feof(pFile)) {//了解feof的返回值
      puts ("End-of-File reached.");
      printf ("Total number of bytes read: %d\n", n);
    }
    else puts ("End-of-File was not reached.");
    fclose (pFile);
  }
  return 0;
}

在这里插入图片描述
我们使用feof就是使用的它的返回值来进行判断:相信以兄弟们的英文水平是很容易读懂上面的这一小串英文的:如果我们读到了文件的末尾,会返回一个非零的值,否则我们就返回零!
这里我们还要注意上面有注释的那一行循环:

1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。

文件缓冲区

缓冲区这个概念我们在讲scanf和getchar的时候应该说过一嘴,我们写下的代码不是直接就呜啦啦塞进变量或者文件的,都是应该先放在缓冲去里面,这里阿涛是真的很想给兄弟们演示一下效果的,但是想要演示的话,就要使用到一个fflush这个函数刷新缓冲区:fflush(pf)刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)!
但是我的vs2019好像不支持fflush的使用,所以只能靠意念给兄弟们描述,意思就是我想要把内存中的一些数据给写进我们的文件里面,我们此时已经写好了,程序也已经跑起来了,但是我们此时打开文件,发现里面空空如也,这就是因为我们并没有刷新缓冲区的原因!
在这里插入图片描述
就像像缓冲地带一样,可以这么理解吧,兄弟们要是实在想知道具体的内容,可以在网上搜索网友们的文章!!

好了那么到这里,我们的文件操作也就告一段落了,阿涛在开始的时候就跟兄弟们保证过,只要你看完这篇文章,那么至少你初步读写个数据肯定是不成问题的,兄弟们下来还是要自己去实践哦!
希望我的这篇博客对兄弟们或多或少有些帮助!
还是那句话:百年大道,你我共勉!!!

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

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

相关文章

【Java】异常

看似不起波澜的日复一日 会突然在某一天让人看到坚持的意义 目录 1.认识异常 1.1 异常的概念 1.2 常见的异常 2.异常的体系结构 3.异常的分类 3.1 编译时异常 3.2 运行时异常 4.异常的处理 4.1 事前防御型 4.2 事后认错型 5.事后认错型处理 5.1 异常的抛出…

第22章 软件安装 RPM/ YUM

上章节是用源代码来编译完成&#xff1b; 发商编译好之后直接把可执行文件发布给用户来安装也是一种方法&#xff0c;类似于windows下的安装&#xff1b; 客户端取得这个文件后&#xff0c;只要通过特定的指令来安装&#xff0c; 那么该软件文件就会依照内部的脚本来检测相依的…

C++数据结构之堆栈

主要参考资料:01.堆栈基础知识 | 算法通关手册 (itcharge.cn)01.堆栈基础知识 | 算法通关手册 (itcharge.cn) 本文主要采用C实现&#xff0c;而参考资料主要采用python实现&#xff0c;可以相互结合食用。 基础知识 定义 堆栈&#xff08;Stack&#xff09;&#xff1a;简称为…

MySQL数据库学习(4)

DQL分组查询 语法&#xff1a; SELECT 字段列表 FROM 表名[ WHERE条件 ] GROUP BY 分组字段名 [HAVING分组后过滤条件]; 我们发现分组查询中有两个条件&#xff0c;这两个条件的区别是什么呢&#xff1f;执行时机不同: where是分组之前进行过滤&#xff0c;不满足where条件&a…

基于SSM的疫情管控系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

大数据Hadoop之——Apache Hudi 数据湖实战操作(Spark,Flink与Hudi整合)

文章目录一、概述二、Hudi CLI三、Spark 与 Hudi 整合使用1&#xff09;Spark 测试2&#xff09;Spark 与 Hudi 整合使用1、启动spark-shell2、导入park及Hudi相关包3、定义变量4、模拟生成Trip乘车数据5、将模拟数据List转换为DataFrame数据集6、将数据写入到hudi四、Flink 与…

前端ES6相关的面试题

前端ES6相关的面试题 文章目录前端ES6相关的面试题一. var let constvarletconst二 . 函数的扩展reset参数箭头函数三 . 数组的扩展四.Set和map数据结构Setmap五. Promise六. 模块化一. var let const var var存在声明提升 >先上车,后买票 var声明的变量会挂载到window下面…

Java实操避坑指南四、spring中的坑

文章目录1. 项目搭建过程1. pom 依赖2. 在没有配置数据库相关时不要引入依赖包&#xff0c;如spring-boot-starter-data-jpa2. spring bean 默认生成策略的正确使用1. 代码示例2. 单元测试3. 工具类 [参考](#test2)4. 报错信息5. 分析6. 使用说明2. 使用了Autowired 注解&#…

【5G RAN】5G gNB间的N2/NGAP切换(handover)那点事儿

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

@Import注解详解

Import这个注解非常重要&#xff0c;而且在springboot项目当中随处可见&#xff0c;就拿springboot启动类来说&#xff0c;我们经常会遇到一些Enable相关的注解&#xff0c;例如开启异步EnableAsync、开启缓存支持EnableCaching、开启定时任务EnableScheduling等等… 目录一、I…

Oracle通过DBLINK访问达梦数据库

环境需求 需要安装配置以下相关软件&#xff1a; 1、Oracle Gateways 2、ODBC数据源&#xff08;gateway机器&#xff09; 3、达梦数据库软件&#xff08;gateway机器&#xff09; 安装配置 Windows环境 安装达梦数据库软件 安装步骤省略&#xff0c;可以参考DM 数据库…

【嵌入式Linux开发一路清障-连载02】Ubuntu22.04安装Shutter进行截图和标注

Ubuntu22.04安装Shutter进行截图和标注障碍 05&#xff0d;Ubuntu22.04中不会给截图做标注&#xff0c;写Bolg举步维艰命令行方式安装Shuttershutter中的常用命令为截取活动窗口设置快捷键安装gnome-web-photo截取长图--失败--未完待续小结下节预告障碍 05&#xff0d;Ubuntu22…

一起来部署项目-采购一台云服务器

前言 不会运维的程序员不是一个好程序员&#xff0c;你是这样认为吗&#xff1f;不&#xff0c;不重要&#xff0c;关键是很多小企业是让后端程序员去干运维的&#xff0c;省钱~~~o(╥﹏╥)o。特别是在YQ严重的当下&#xff0c;所以为了提高自己的竞争力&#xff0c;从今天起&…

万字爽文一篇带你掌握Java8新特性

陈老老老板说明&#xff1a;新的专栏&#xff0c;本专栏专门讲Java8新特性&#xff0c;把平时遇到的问题与Java8的写法进行总结&#xff0c;需要注意的地方都标红了&#xff0c;一起加油。本文是介绍Java8新特性与常用方法&#xff08;此篇只做大体介绍了解&#xff0c;之后会把…

Java8中LocalDate详解Date线程不安全的原因

LocalDate 分类分工 java.time.LocalDate ->只对年月日做出处理 java.time.LocalTime ->只对时分秒纳秒做出处理 java.time.LocalDateTime ->同时可以处理年月日和时分秒优点 除了使用起来更加简单和灵活&#xff0c;主要是传统的时期处理类Date、Calendar不是多线…

刷爆leetcode第十二期 0026 数组中数字出现的次数

编号0026 数组中数字出现的次数 一个整型数组 nums 里除两个数字之外&#xff0c;其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n)&#xff0c;空间复杂度是O(1)。 题目示例如下 这里其实是一道我一个月之前做的题目 在学弟的博客里刚好看…

【数据结构与算法】Java实现七大排序算法汇总

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【数据结构与算法】 ✈️✈️本篇内容: Java实现七大排序算法汇总&#xff01; &#x1f680;&#x1f680;由于本篇博客涉及代码较多&#xff0c;博主把代码都提…

刷爆leetcode第十一期 0023~0025

刷爆leetcode第十一期 编号0023 相同的树编号0024 对称二叉树编号0025 另一个树的子树编号0023 相同的树 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是…

多旋翼无人机仿真 rotors_simulator:用键盘控制无人机飞行

多旋翼无人机仿真 rotors_simulator&#xff1a;用键盘控制无人机飞行前言书接上文接口测试键盘指令发布指令转换与发布修改 rotors_simulator 的控制接口节点测试前言 RotorS 是一个MAV gazebo 仿真系统。 提供了几种多旋翼仿真模型&#xff0c;例如 AscTec HummingbirdAsc…

PHP反序列化

序列化与反序列化 序列化 反序列是指把对象转换为字符串的过程&#xff0c;便于在内存、文件、数据库中保存、传输&#xff0c;PHP中使用serialize函数进行序列化。 <?phpclass Person{public $name"php";protected $id;private $age;}$a new Person();$a_se…