C语言之文件操作(详解版)

news2024/12/27 1:19:33

不知不觉我们已经学到C语言的文件操作部分了,这部分内容其实很有意思,因为它可以直接把我们代码中的数据写入硬盘,而不是我们关掉这个程序,代码就没有了,让我们开始学习吧!


目录

1.为什么使用文件

2.什么是文件

2.1程序文件

2.2数据文件

2.3文件名

3.文件的打开和关闭

3.1文件指针

3.2文件的打开和关闭

3.2.1fopen:文件打开函数

3.2.2fclose:关闭文件函数

3.2.3代码示例

3.2.4文件打开(fopen)模式

4.文件读写顺序

4.1文件的顺序读写

4.1.1fputc函数

4.1.2fgetc函数

代码示例

4.1.3fputs函数

4.1.4fgets函数

代码示例

4.1.5fprintf函数

4.1.6fscanf函数

代码示例

4.1.7fwrite函数

4.1.8fread函数

代码示例

4.2文件的随机读写

4.2.1fseek函数

4.2.2ftell函数

4.2.3rewind函数

代码示例

5.文本文件和二进制文件


1.为什么使用文件

1.使用文件我们可以将数据直接存放在电脑的硬盘上,做到数据的持久化

数据存放在内存中:

前面实现的通讯录,当程序运行起来的时候,可以给通讯录增加,删除数据,但是当程序退出的时候,通讯录中的数据自然就不存在了,当下次运行程序的时候,数据又得重新录入,这样的通讯录就很局限

数据存放在硬盘中:

可以把数据记录下来,只有我们自己选择删除数据的时候,数据才会被销毁,否则,我们下次打开这个程序的时候,上一次存入的数据都存在,不会消失。(下篇博客为大家实现)

保持存入通讯录的数据一直存在,这就涉及到我们数据持久化问题

2.我们一般把数据持久化的方法有:

把数据存放在磁盘文件

把数据存放到数据库等方式

3.我们要学的是把数据放到磁盘文件中

2.什么是文件

简单来说,磁盘上的文件就是文件,就比如我们计算机上C盘中的文件夹下的文件

以上都是存放在硬盘中的文件

在程序设计中,我们一般把文件分为两类(从文件功能的角度分):

程序文件

数据文件

我们主要学习数据文件

2.1程序文件

源程序文件(后缀为.c)

目标文件(windows环境后缀为.obj)

可执行程序(Windows环境下后缀为.exe)

2.2数据文件

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

数据在显示器上:

处理数据的输入输出都是以终端为对象的,就是从终端的键盘上输入数据,运行结果显示到显示器上

数据在磁盘文件中:

我们可以把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用

2.3文件名

我们都一个文件要有唯一的文件标识,以方便用户的识别和引用

文件名包含三个部分:文件路径+文件名主干+文件后缀

为了方便起见,文件标识就被认为是文件名

3.文件的打开和关闭

3.1文件指针

1.什么是文件指针:

在缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”,每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(例如:文件名,文件状态,文件当前位置),这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE

2.每当我们打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心其中的细节,一般都是通过FILE指针来维护这个FILE结构的变量,这样使用起来更加方便

3.我们创建一个FTLE*的指针变量,例如FILE* pf,它就是一个文件指针变量

相信很多伙伴们又要问为什么要创建这个指针变量:

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

3.2文件的打开和关闭

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

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

接下来让我们学习一下,文件的打开(fopen)和关闭(fclose)这两个函数

3.2.1fopen:文件打开函数

1.函数功能:打开一个文件

2.头文件:#include<stdio.h>

3.函数格式:FILE *fopen( const char *filename, const char *mode );

filename:文件名

mode:文件打开方式(下面会为大家总结一个表格)

4.函数返回值:

打开文件成功:返回一个指向打开文件的指针

打开文件失败:返回一个空指针

所以我们每次在打开文件的代码下,要加一段代码来检测文件是否打开成功

3.2.2fclose:关闭文件函数

1.函数功能:关闭一个文件

2.头文件:#include<stdio.h>

3.函数格式:int fclose( FILE *stream );

stream:流,就是文件流

这里要为大家拓展关于“流”的知识

在我们C程序运行的时候,默认打开三个流

stdin:标准输入流(就是我们在键盘上可以输入的数据)

stdout:标准输出流(我们在屏幕上可以看到的数据)

stderr:标准错误流(我们在屏幕上可以看到的数据)

它们的类型都是FILE*

所以我们在写C程序的时候才不需要在打开流,因为它是默认打开这三个流的

在进行文件操作的时候,我们是没有默认打开流的,这时需要我们手动给它添加一个流

然后进行读取写入等操作

我们这里的 FILE *stream 就是一个文件流

例如:FILE* pf=(“test.txt”,"w");这个语句里,pf这个文件指针就是一个文件流

那么我们为什么要有流呢?我们的数据是不能直接传输到输出设备上的,它是通过流进行传输的,目前我们知道这些,进行文件操作的时候就不会觉得难以理解了。

4.函数返回值:

文件关闭失败:函数返回值是0,同时需要我们把文件指针置为NULL

文件关闭失败:函数返回EOF来指示错误

3.2.3代码示例

现在介绍完fopen和fclose函数了,让我们看个代码来进一步理解这两个函数的使用

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>

int main()
{
	//打开一个文件,以只读的模式打开
	FILE* pf = fopen("test.txt", "r");//这里的文件名,如果我们想要使用
	//已经存在,也就是创建好的文件,我们需要把文件路径给完整的加上

	//检测文件是否打开成功,成功则进入文件,失败返回空指针
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//进入文件,进行读文件
	//...
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

我们运行代码,发现显示了错误信息

提醒我们没有这个文件,这就引出了我们下一个知识点,文件打开模式有哪些,以只读模式打开文件为什么会打开失败。

3.2.4文件打开(fopen)模式

这里给大家总结了一个表格,我们可以对照表格,选择我们需要的文件打开模式

这里我们要注意,以写的形式打开一个文件时,上次书写在文件中的数据将会被销毁,这次打开文件输入的内容将覆盖上一次的内容

4.文件读写顺序

文件读写分为顺序读写和随机读写两类

我们在学习这部分内容之前,还需要明确一个知识点

在我们平时写C语言时,是面向程序的:数据显示到屏幕上

今天学习的面向文件操作:数据显示到文件中

知道输入和输出的面向关系,我们才能更好的学习这部分知识

4.1文件的顺序读写

文件的顺序读写就是,按顺序读写,一个诶一个

这里我们学习几个函数,来帮助我们更好的认识文件顺序读写

字符输入输出函数:fgetc/fputc

文本行输入输出函数:fgets/fputs

格式化输入输出函数:fscanf/fprintf

二进制输入输出函数:fread/fwrite

前三对函数适用于所有流(既适用于标准输出流,也适用于文件流)

最后一对仅适用于文件流

我们一对一对来介绍

4.1.1fputc函数

1.函数功能:将字符写入文件流或者标准输出流

2.头文件:#include<stdio.h>

3.函数格式:int fputc( int c, FILE *stream );

这里的c:要输出(写入)的字符

代码示例我们与fgetc函数放在一起实现

4.1.2fgetc函数

1.函数功能:从文件流或者标准输入流中读取字符

2.头文件:#include<stdio.h>

3.函数格式:int fgetc( FILE *stream );

4.函数返回值:

读取成功:返回作为int读取的字符

读取失败:返回EOF以指示错误或文件结束

下面我们来看个代码,理解这两个函数

代码示例

int main()
{
	//打开一个文件
	FILE* pf = fopen("test1.txt", "w");//以写的形式打开
	//判断文件是否打开成功
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//文件打开成功,进行写文件fputc
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}
	//书写完毕,关闭文件
	fclose(pf);
	pf = NULL;
	//打开这个文件,我们进行读取操作
	FILE* ptf = fopen("test1.txt", "r");//以读的形式打开
	if (ptf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//开始读取,我们读取四次
	int tmp = fgetc(ptf);
	printf("%c\n", tmp);
	tmp = fgetc(ptf);
	printf("%c\n", tmp);
	tmp = fgetc(ptf);
	printf("%c\n", tmp);
	tmp = fgetc(ptf);
	printf("%c\n", tmp);
	//读取完毕,关闭文件
	fclose(ptf);
	ptf = NULL;

	return 0;
}

打开文件所在文件夹,我们可以看到文件中已经存入数据,这是fputc函数的功能,在文件中写入了数据

运行代码,我们可以看到屏幕上的结果,读取到了a b c d ,这是fgetc函数的功能

4.1.3fputs函数

1.函数功能:将字符串写入文件流或者标准输出流

2.头文件:#include<stdio.h>

3.函数格式:int fputs( const char *string, FILE *stream );

string:我们需要写入的字符串

4.函数一次性只能写入一条字符串

代码示例我们与fgets函数放在一起实现

4.1.4fgets函数

1.函数功能:从文件流或者标准输入流中读取字符串

2.头文件:#include<stdio.h>

3.函数格式:char *fgets( char *string, int n, FILE *stream );

string:数据存储的位置,通俗来说,就是从stream中要读的字符串放到string中

n:要读取的最大字符数

4.函数返回值:

读取成功:返回该条字符串

读取失败:返回一个空指针NULL

5.函数一次性只能读取一条字符串

我们来看段代码,加深理解

代码示例

int main()
{
	//打开一个文件
	FILE* pf = fopen("test1.txt", "w");//以写的形式打开
	//判断文件是否打开成功
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//文件打开成功,进行写文件fputc
	fputs("hello world!\n", pf);
	fputs("亚里士多德!\n", pf);
	fputs("hehe!\n", pf);
	//书写完毕,关闭文件
	fclose(pf);
	pf = NULL;
	//打开这个文件,我们进行读取操作
	FILE* ptf = fopen("test1.txt", "r");//以读的形式打开
	if (ptf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//开始读取
	char buf[30] = { 0 };
	fgets(buf, 5, ptf);

	//读取完毕,关闭文件
	fclose(ptf);
	ptf = NULL;

	return 0;
}

我们打开文件可以看到,文件中已经写入(fputs)三行数据

我们运行代码读取(fgets)第一行的数据

我们预想中的hello并没有出现,而是hell,这是因为要留一个字符位置来存放‘\0’,如果想要打印hello,要让n=6

4.1.5fprintf函数

1.函数功能:格式化把数据写入文件流或者标准输出流

2.头文件:#include<stdio.h>

3.函数格式:int fprintf( FILE *stream, const char *format [, argument ]...);

char *format:格式化控制字符串,就是说它以什么形式输出,例如%d %s %f

[argument ]...:可选参数,就是对应形式的打印参数是什么

4.函数返回值:

写入成功:返回写入的字节数

写入失败:函数中的每一个都会返回一个负值

代码示例我们与fscanf函数放在一起实现

4.1.6fscanf函数

1.函数功能:从文件流或者标准输入流中读取格式化数据

2.头文件:#include<stdio.h>

3.函数格式:int fscanf( FILE *stream, const char *format [, argument ]... );

char *format: 格式化控制字符串,就是说它以什么形式输入,例如%d %s %f

[argument ]...:可选参数,就是对应形式的打印参数是什么

4.函数返回值:

读取成功:返回成功转换和分配的字段数

读取失败:发生错误,或者在第一次转换之前到达文件流的末尾的情况下,则返回值为fscanf的EOF

返回值0表示未分配任何字段

我们来看段代码,进一步了解

代码示例

struct S
{
	char name[12];
	int age;
	float score;
};
int main()
{
	//打开一个文件
	struct S s1 = { "张翰",34,94.3 };
	FILE* pf = fopen("test1.txt", "w");//以写的形式打开
	//判断文件是否打开成功
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//文件打开成功,进行写文件fprintf
	fprintf(pf, "%s %d %f", s1.name, s1.age, s1.score);
	//书写完毕,关闭文件
	fclose(pf);
	pf = NULL;
	//打开这个文件,我们进行读取操作
	FILE* ptf = fopen("test1.txt", "r");//以读的形式打开
	if (ptf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//开始读取
	struct S s2 = { 0 };
	fscanf(ptf, "%s %d %f", s2.name,& (s2.age), &(s2.score));
	printf("%s %d %f\n", s2.name, s2.age, s2.score);
	//读取完毕,关闭文件
	fclose(ptf);
	pf = NULL;

	return 0;
}

我们这里的结构体中存放的就是格式化的数据

打开文件,发现文件中已经写入(fprintf)数据

运行代码读取(fscanf),屏幕上显示文件中的数据

4.1.7fwrite函数

1.函数功能:以二进制输出数据,将数据写入文件流

2.头文件:#include<stdio.h>

3.函数格式:size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

void *buffer:指向要写入的数据的指针

size:要写的元素的大小,即每个元素所占字节的大小

count:最多写入几个元素

FILE *stream:文件流

4.函数返回值:

写入成功:写入的完整项目数,即count

写入失败:该数字可能小于count,此外,如果发生错误,则无法确定文件位置指示器

代码示例我们与fread函数放在一起实现

4.1.8fread函数

1.函数功能:以二进制输入数据,从文件中读取数据

2.头文件:#include<stdio.h>

3.函数格式:size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

buffer:数据存储位置

size:要读的元素的大小,即每个元素所占字节的大小

count:最多读取几个元素

4.函数返回值:

读取成功:返回实际读取的完整项目数,即count,如果发生错误或在达到count之前遇到文件末尾,则该数字可能小于count

读取失败:使用feof或ferror函数来区分读取错误和文件结束条件。如果大小或计数为0,则fread返回0,并且缓冲区内容不变。

接下来我们看段代码来加深了解

代码示例

//fwrite  fread
struct S
{
	char name[12];
	int age;
	float score;
};
int main()
{
	//打开一个文件
	struct S s1 = { "张翰",34,94.3 };
	struct S s3 = { "黄晓明",55,88.9 };
	FILE* pf = fopen("test1.txt", "wb");//以二进制写的形式打开
	//判断文件是否打开成功
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//文件打开成功,进行写文件
	fwrite(&s1, sizeof(s1), 1, pf);
	fwrite(&s3, sizeof(s3), 1, pf);
	//书写完毕,关闭文件
	fclose(pf);
	pf = NULL;

	//打开这个文件,我们进行读取操作
	FILE* ptf = fopen("test1.txt", "rb");//以二进制形式打开要读的文件
	if (ptf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//开始读取
	struct S s2 = { 0 };
	fread(&s2, sizeof(s2),1,ptf);
	printf("%s %d %f\n", s2.name, s2.age, s2.score);
	fread(&s2, sizeof(s2), 1, ptf);
	printf("%s %d %f\n", s2.name, s2.age, s2.score);
	//读取完毕,关闭文件
	fclose(ptf);
	pf = NULL;

	return 0;
}

打开文件,我们发现文件中已经被写入(fwrite)二进制数据,我们是看不懂的

我们发现只有汉字我们可以看懂,这是因为汉字的二进制形式与汉字本身形式相同

运行代码,我们读取(fread)数据到屏幕上,屏幕上显示数据,读取成功

4.2文件的随机读写

文件顺序读写有对应的函数,同样,文件的随机读写也有对应的函数,我们在这里介绍3个对应函数,fseek  ftell rewind

我们继续往下了解

4.2.1fseek函数

1.函数功能:将文件指针移动到指定位置

2.头文件:#include<stdio.h>

3.函数格式:int fseek( FILE *stream, long offset, int origin );

offect:偏移量,也就是当前指针位置到目标位置的字节数

指针从左—>右,偏移量为正数

指针从右—>左,偏移量为负数

origin:起始位置,它还被定义了三个量

SEEK_SET:文件其实位置

SEEK_CUR:文件当前指针位置

SEEK_END:文件末尾

4.函数返回值:

读取成功:fseek将返回0

读取失败:它将返回一个非零值,在无法查找的设备上,返回值未定义

我们将代码例子与ftell函数和rewind函数放在一起

4.2.2ftell函数

1.函数功能:获取文件指针的当前位置,通俗来说,这个函数就是让我们来求偏移量的,也就是文件指针相较于起始位置的偏移量

2.头文件:#include<stdio.h>

3.函数格式:long int ftell( FILE *stream );

4.函数返回值:

读取成功:返回文件指针相较于起始位置的偏移量

读取失败:ftell返回–1L(偏移量),errno设置为errno.H中定义的两个常量之一

我们和rewind函数一起来 看代码例子

4.2.3rewind函数

1.函数功能:将文件指针重新定位到文件起始位置

2.头文件:#include<stdio.h>

3.函数格式:void rewind( FILE *stream );

我们来看个代码进一步加深理解这两个函数

代码示例

int main()
{
	FILE* pf = fopen("test2.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//在文件中写入abcdefg
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}
	//写入完成,关闭文件
	fclose(pf);
	pf = NULL;

	//再次打开文件,进行随机读取文件
	FILE* ptf = fopen("test2.txt", "r");
	if (ptf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//先按顺序往下读3个字符
	char tmp = fgetc(ptf);//a
	printf("%c\n", tmp);
	tmp = fgetc(ptf);//b
	printf("%c\n", tmp);
	tmp = fgetc(ptf);//c
	printf("%c\n", tmp);
	//读取完三次后,我们想再次读取b,而不是按顺序读取到d,此时
	//我们需要使用fseek函数
	fseek(ptf, -2, SEEK_CUR);//改变指针位置
	tmp = fgetc(ptf);
	printf("%c\n", tmp);//此时读取到b

	//假设在此时,我们不知道文件指针的当前位置,这时,我们就需要用到
	// ftell函数来求一下当前文件指针的偏移量
	printf("文件指针相较于起始位置的偏移量是%d\n", ftell(ptf));

	//得到这个文件指针偏移量后,我们想把文件指针归到文件起始位置
	// 这时需要用到我们的rewind函数
	rewind(ptf);
	//我们打印一个字符验证一下,查看是否文件指针回到了文件起始位置,如果
	// 回到了,则打印出来的是a
	//进行读取字符
	tmp = fgetc(ptf);
	printf("是起始字符;>%c \n", tmp);
	//读取完毕,关闭文件
	fclose(ptf);
	ptf = NULL;

	return 0;
}int main()
{
	FILE* pf = fopen("test2.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//在文件中写入abcdefg
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}
	//写入完成,关闭文件
	fclose(pf);
	pf = NULL;

	//再次打开文件,进行随机读取文件
	FILE* ptf = fopen("test2.txt", "r");
	if (ptf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//先按顺序往下读3个字符
	char tmp = fgetc(ptf);//a
	printf("%c\n", tmp);
	tmp = fgetc(ptf);//b
	printf("%c\n", tmp);
	tmp = fgetc(ptf);//c
	printf("%c\n", tmp);
	//读取完三次后,我们想再次读取b,而不是按顺序读取到d,此时
	//我们需要使用fseek函数
	fseek(ptf, -2, SEEK_CUR);//改变指针位置
	tmp = fgetc(ptf);
	printf("%c\n", tmp);//此时读取到b

	//假设在此时,我们不知道文件指针的当前位置,这时,我们就需要用到
	// ftell函数来求一下当前文件指针的偏移量
	printf("文件指针相较于起始位置的偏移量是%d\n", ftell(ptf));

	//得到这个文件指针偏移量后,我们想把文件指针归到文件起始位置
	// 这时需要用到我们的rewind函数
	rewind(ptf);
	//我们打印一个字符验证一下,查看是否文件指针回到了文件起始位置,如果
	// 回到了,则打印出来的是a
	//进行读取字符
	tmp = fgetc(ptf);
	printf("是起始字符;>%c \n", tmp);
	//读取完毕,关闭文件
	fclose(ptf);
	ptf = NULL;

	return 0;
}

运行结果

在这里,我们要特别说明一下那个文件光标位置

打开我们写入的文件,我们发现光标在文件起始位置,这是因为文件指针默认指向第一个字符,当我们一次往后读取(fgetc)字符时,文件指针会自增1,会直接往下走,而不是一直打印那一个字符,这个不需要我们程序员来操作。

5.文本文件和二进制文件

什么是文本文件,什么又是二进制文件?

1.根据数据的组织形式,数据文件被称为文本文件或者二进制文件

2.数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件

(ps:这种二进制文件,我们一般是看不懂的,看不懂思密达!!!)

3.如果要求在外存上以ASCII码的形式存储,则需要在存储前转换,以ASCII码字符的形式存储的文件就是文本文件

(ps:看得懂思密达!!!)

我们举个简单的例子来看什么是二进制存储,什么是ASCII存储

例如我们要把整数10000存入内存中

它在内存中原来就是以二进制的补码形式存储的,也就是

00000000 00000000 00100111 00010000

(不清楚源码反码补码关系的伙伴可以去我这篇博客中了解源码反码补码的关系)

以文本文件(ASCII形式)存储:

这是整数10000,它的五个位数一次转换为ASCII对应值,也就是

以二进制的形式存储:

就是不加转换的二进制码:00000000 00000000 00100111 00010000

它在文件中显示出来的数据我们是看不懂的

可以举个代码例子

int main()
{
	//以二进制的形式进行写入
	FILE* pf = fopen("test3.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int a = 10000;
	fwrite(&a, 4, 1, pf);
	fclose(pf);
	pf = NULL;
	//以二进制的形式进行读取
	FILE* ptf = fopen("test3.txt", "rb");
	if (ptf == NULL)
	{
		perror("ptf::fopen");
		return 1;
	}
	int b = 0;
	fread(&b, 4, 1, ptf);
	printf("%d \n", b);
	fclose(ptf);
	ptf = NULL;
	return 0;
}

我们打开对应的文件,可以看到里面存储的数据


由于这篇博客字数已经到极限了,我们还剩下一点内容,文件读取结束的判定和文件缓冲区,我们放到下一篇博客,好了,大家下期再见!!!

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

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

相关文章

伪造referer [极客大挑战 2019]Http1

打开题目 没有发现什么&#xff0c;我们查看源代码 在这里我们发现了提示 访问一下页面得到 提示说不能来自于https://Sycsecret.buuoj.cn&#xff0c;我们尝试访问一下这个url 发现访问不了 我们bp抓包一下 伪造个referer头 referer:https://Sycsecret.buuoj.cn 发包过去…

ChatGPT、GPT-4 Turbo接口调用

接口地址 https://chat.xutongbao.top/api/light/chat/createChatCompletion 请求方式 post 请求参数 model可选值&#xff1a; “gpt-3.5-turbo-1106”、 “gpt-3.5-turbo-16k” 、 “gpt-4”、“gpt-4-1106-preview”。 默认值为&#xff1a; “gpt-3.5-turbo-1106” to…

Delphi TCP服务端监听端口获取客户端RFID网络读卡器上传的刷卡数据

本示例使用设备介绍&#xff1a;液显WIFI无线网络HTTP协议RFID云读卡器可编程实时可控开关TTS语-淘宝网 (taobao.com) unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, ComCtrls, ScktComp, StdCtrls, ScktCom…

JVM源码剖析之软、弱、虚引用的处理细节

目录 写在前面&#xff1a; 源码剖析&#xff1a; Java层面&#xff1a; JVM层面&#xff1a; 使用危险点&#xff1a; 总结&#xff1a; 版本信息&#xff1a; jdk版本&#xff1a;jdk8u40 垃圾回收器&#xff1a;Serial new/old 写在前面&#xff1a; 不同的垃圾回收…

PROFINET和UDP、MODBUS-RTU通信速度对比实验

这篇博客我们介绍PROFINET 和MODBUS-RTU通信实验时的数据刷新速度,以及这种速度不同对控制系统带来的挑战都有哪些,在介绍这篇对比实验之前大家可以参考下面的文章链接: S7-1200PLC和SMART PLC的PN智能从站通信 S7-200 SMART 和 S7-1200PLC进行PROFINET IO通信-CSDN博客文…

远程电脑未连接显示器时分辨率太小的问题处理

背景&#xff1a;单位电脑显示器坏了&#xff0c;使用笔记本通过向日葵远程连接&#xff0c;发现分辨率只有800*600并且不能修改&#xff0c;网上找了好久找到了处理方法这里记录一下&#xff0c;主要用到的是一个虚拟显示器软件usbmmidd_v2 1)下载usbmmidd_v2 2&#xff09;…

Flink SQL自定义表值函数(Table Function)

使用场景&#xff1a; 表值函数即 UDTF&#xff0c;⽤于进⼀条数据&#xff0c;出多条数据的场景。 开发流程&#xff1a; 实现 org.apache.flink.table.functions.TableFunction 接⼝实现⼀个或者多个⾃定义的 eval 函数&#xff0c;名称必须叫做 eval&#xff0c;eval ⽅法…

什么是进程等待?

什么是进程等待 在了解进程等待之前&#xff0c;我们要回顾一下什么是僵尸进程&#xff1a;是指一个已经终止执行的进程&#xff0c;但其父进程还没有通过 wait() 系统调用来获取该进程的退出状态信息。当一个进程正常退出或者被终止时&#xff0c;其所占用的系统资源会被操作…

基于SSM的智能物业管理网站的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

rabbitMq虚拟主机概念

虚拟主机是RabbitMQ中的一种逻辑隔离机制&#xff0c;用于将消息队列、交换机以及其他相关资源进行隔离。 在RabbitMQ中&#xff0c;交换机&#xff08;Exchange&#xff09;用于接收生产者发送的消息&#xff0c;并根据特定的路由规则将消息分发到相应的队列中。而虚拟主机则…

使用 pubsub-js 进行消息发布订阅

npm 包地址 github 包地址 pubsub-js 是一个轻量级的 JavaScript 基于主题的消息订阅发布库 &#xff0c;压缩后小于1b。它具有使用简单、性能高效、支持多平台等优点&#xff0c;可以很好地满足各种需求。 功能特点&#xff1a; 无依赖同步解耦ES3 兼容。pubsub-js 能够在…

快速修复因相机断电导致视频文件打不开的问题

3-5 本文主要解决因相机突然断电导致拍摄的视频文件打不开的问题。 在日常工作中&#xff0c;有时候需要使用相机拍摄视频&#xff0c;比如现在有不少短视频拍摄的需求&#xff0c;如果因电池突然断电的原因&#xff0c;导致拍出来的视频播放不了&#xff0c;这时候就容易出大…

el-table 多表格弹窗嵌套数据显示异常错乱问题

1、业务背景 使用vueelement开发报表功能时&#xff0c;需要列表上某列的超链接按钮弹窗展示&#xff0c;在弹窗的el-table列表某列中再次使用超链接按钮点开弹窗&#xff0c;以此类推多表格弹窗嵌套&#xff0c;本文以弹窗两次为例 最终效果如下示例页面 2、具体实现和问题…

hub.docker访问不了的问题(一步解决)

暂时我也不清楚&#xff0c;但是下面这个网址可以用(可以先用着)Docker Hub Container Image Library | App Containerization (axlinux.top)https://hub.axlinux.top/

美格智能5G RedCap模组顺利完成中国联通5G物联网OPENLAB开放实验室认证

近日&#xff0c;美格智能5G RedCap模组SRM813Q顺利通过中国联通5G物联网OPENLAB开放实验室端到端的测试验收&#xff0c;并获得OPENLAB实验室的认证证书。这标志着该模组产品各项性能均已符合RedCap商用标准&#xff0c;为5G RedCap规模商用奠定了坚实基础。 中国联通5G物联网…

使用WinDbg分析软件突然崩溃的问题

为了测试windbg有多么牛逼&#xff0c;所以仅仅只是测试一下&#xff0c;属于事后诸葛亮型&#xff0c;也只是为了验证一下&#xff0c;把此方法学会即可。 模拟场景&#xff1a; 软件运行后&#xff0c;点击按钮&#xff0c;直接崩溃掉&#xff0c;什么提示都没有。因此&…

统计学习笔记第 1 部分:Hoeffding 的不等式推导与模拟

照片由Unsplash上的Luca Bravo拍摄 1&#xff1a;背景与动机 霍夫丁不等式是数理统计和机器学习 (ML) 中的一个重要的集中不等式&#xff0c;广泛应用于统计学习理论等理论领域以及强化学习等应用领域。 我注意到&#xff0c;在机器学习社区的一些地方&#xff0c;通常将 Hoeff…

图数据库Neo4j详解

文章目录 第一章 图和Neo4j1.1 图数据库概念1.1.1 图论起源1.1.2 节点-关系及图1.1.3 图数据库1.1.4 图数据库分类1.1.4 图数据库应用场景1.1.5 与关系型数据库对比1.1.6 图数据库优势 1.2 Neo4j介绍1.2.1 Neo4j是什么1.2.2 Neo4j特点1.2.3 Neo4j的优势1.2.4 Neo4j的限制1.2.5 …

网络安全(黑客)-高效自学

首先给大家简单介绍一下网络安全&#xff1a; 1.什么是网络安全&#xff1f; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、…

eNsp使用技巧

文章目录 显示网格对齐到网络水平对齐和垂直对齐 显示所有接口添加文本进入CLI界面数据抓包方式一方式二 显示网格 对齐到网络 水平对齐和垂直对齐 显示所有接口 添加文本 进入CLI界面 数据抓包 方式一 方式二