当前位置: 首页 > news >正文

【C语言】文件操作 -- 详解

一、什么是文件

磁盘上的文件是文件。

1、为什么要使用文件

        举个例子,当我们想实现一个 “通讯录” 程序时,在通讯录中新建联系人、删除联系人等一系列操作,此时的数据存储于内存中,程序退出后所有数据都会随之消失。为了让通讯录中的信息得以保存,也就是想让数据持久化,我们就需要采用让数据持久化的方法。我们一般数据持久化的方法有:把数据存放在磁盘文件中,或存放到数据库等方式


在程序设计中,我们一般谈的文件有两种:程序文件数据文件

2、程序文件

包括源程序文件(后缀为 .c ),目标文件( windows 环境后缀为 .obj ),可执行程序( windows 环境后缀为 .exe)。
#include <stdio.h>int main()
{printf("Hello,World!\n");return 0;
}

(1)

 (2)


3、数据文件

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

此时,如果我写的程序在读写这个文件(我可以读这个文件夹的内容进我的程序中,或是将一些内容写到这个文件夹中),那么这个文件就成为数据文件。 


二、文件名

一个文件要有一个唯一的文件标识,方便用户识别和引用。

文件名包含三个部分:文件路径 + 文件名主干 + 文件后缀( 例如:C:\code\test.txt )

 为了方便起见,文件标识常被称为文件名


三、文件类型

  • 根据数据的组织形式,数据文件被称为文本文件或者二进制文件
  1. 数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件
  2. 如果要求在外存上以 ASCII 的形式存储,则需要在存储前转换。以 ASCII 字符的形式存储的文件就是文本文件
一个数据在内存中是怎么存储的呢?
字符一律以  ASCII  形式存储,数值型数据既可以用  ASCII  形式存储,也可以使用二进制形式存储。如有整数 10000 ,如果以  ASCII  码的形式输出到磁盘,则磁盘中占用  个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占 4  个字节(  VS2019  测试)。
#include <stdio.h>int main()
{int a = 10000;FILE* pf = fopen("test.txt", "wb");fwrite(&a, 4, 1, pf); // 二进制的形式写到文件中fclose(pf);pf = NULL;return 0;
}

 

 

 

 


四、文件缓冲区(File Buffer)

        ANSIC 标准采用 缓冲文件系统 处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“ 文件缓冲区 。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据 C 编译系统决定的。

#include <stdio.h>
#include <windows.h>int main()
{FILE* pf = fopen("test.txt", "w");fputs("abcdef", pf); // 先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf); // 刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");Sleep(10000);fclose(pf); // fclose在关闭文件的时候,也会刷新缓冲区pf = NULL;return 0;
}

 

结论: 因为有缓冲区的存在,C 语言在操作文件时,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。如果不做,可能导致读写文件的问题。


五、文件指针

在 C 语言中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。

  • 缓冲文件系统中,关键的概念是文件类型指针,简称文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名 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;

 注意

  1. FILE 的结构在不同的 C 编辑器中包含的内容并不是不完全相同的,但还是颇为相似的。
  2. 每当打开一个文件时,系统会根据文件的状况自动创建一个 FILE 结构的变量,并填充其中的信息。只要文件被读写发生变化,文件信息区也会跟着发生变化。至于文件变化时文件信息区是怎么变化和修改的,我们其实并不需要关心这些细节,因为 C 语言已经帮你弄好了。
  3. 我们一般会通过一个 FILE 的指针来维护这个 FILE 结构的变量。并不会直接使用,而是拿一个结构体指针指向这个结构,通过这个指针来访问和维护相关的数据,这样使用起来会更加方便。
// 以创建一个FILE*的指针变量
FILE* pf; // 文件指针变量
定义  pf  是一个指向  FILE   类型数据的指针变量。可以使  pf  指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件


六、文件的打开和关闭

  • 文件在读写之前应该先打开文件,在使用结束之后应该关闭文件
  • 在编写程序的时候,在打开文件的同时,都会返回一个 FILE* 的指针变量指向该文件,也相当于建立了指针和文件的关系
  • ANSIC 规定使用 fopen 函数来打开文件,fclose 来关闭文件

 

 

// open the file
FILE * fopen (const char* filename, const char* mode);// close the file
int fclose (FILE* stream);// filename参数指的是文件名,mode参数为打开方式

#include <stdio.h>int main()
{FILE* pf = fopen("test.dat", "w");if (pf == NULL) // 检查是否为空指针{perror("fopen");return 1;}fclose(pf);pf = NULL; // 将pf置为空指针return 0;
}

 一切正常。

我们把 test.dat 文件删除,然后打开方式改成 r 试试看。

#include <stdio.h>int main()
{FILE* pf = fopen("test.dat", "r");if (pf == NULL) // 检查是否为空指针{perror("fopen");return 1;}fclose(pf);pf = NULL; // 将pf置为空指针return 0;
}

 perror 返回的错误信息。

如果不适用相对路径,使用绝对路径读文件:

可以使用绝对路径,但是要注意转义绝对路径中的斜杠

#include <stdio.h>int main()
{// FILE* pf = fopen("D:\code\0824\0824\test.dat", "w"); // errorFILE* pf = fopen("D:\\code\\0824\\0824\\test.dat", "w"); // 转移字符\if (pf == NULL){perror("fopen");return 1;}fclose(pf);pf = NULL;return 0;
}

注意:不关闭文件的后果:一个程序能够打开的文件是有限的,文件属于一种资源。如果只打开不释放,文件就会被占用。可能会导致一些操作被缓冲在内存中,如果不能正常关闭,缓冲在内存中的数据就不能正常写入到文件中从而导致数据的丢失。


七、文件的顺序读写

  • 顺序读写,简而言之就是按照顺序在文件中读和写。

首先要了解什么是读写:我们写的程序是在内存中,而数据是要放到文件中的,文件又是在硬盘上的。当我们把文件里的数据读到内存中去时,这个动作我们称之为输入 / 读取。反过来,如果把程序中的东西放到硬盘上,这个动作我们称之为输出 / 写入


1、什么是流

⚪stdin:标准输入流 - 键盘

⚪stdout:标准输出流 - 屏幕

⚪stderr:标准错误流 - 屏幕

(它们的类型都是 FILE* )

#include<stdio.h>int main()
{// 从标准输出流里输入数据fputc('b', stdout);// 同printf("b");fputc('i', stdout);fputc('t', stdout);printf("\n");// 从标准输入流里读取数据int ret = fgetc(stdin); // 同scanf("%d", ret);printf("%c\n", ret);ret = fgetc(stdin);printf("%c\n", ret);ret = fgetc(stdin);printf("%c\n", ret);return 0;
}


2、字符输入函数 fgetc

从指定的流 stream 获取下一个字符,并把位置标识符向前移动(字符必须为一个无符号字符)。如果读取成功会返回相应的 ASCII码值,如果读取失败会返回一个 EOF 适用于所有输入流。

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ret = fgetc(pf);printf("%c\n", ret);ret = fgetc(pf);printf("%c\n", ret);ret = fgetc(pf);printf("%c\n", ret);fclose(pf);pf = NULL;return 0;
}

 

读取结束或者读取失败返回 EOF。


3、字符输出函数 fputc

  • 将参数 char 指定的字符写入到指定的流 stream 中,并把位置标识符向前移动 (字符必须为一个无符号字符)。适用于所有输出流。

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL){perror("fopen");return 1;}fputc('a', pf);fputc('b', pf);fputc('c', pf);fclose(pf);pf = NULL;return 0;
}

 abc 成功被写入。

倘若将代码修改为:

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL){perror("fopen");return 1;}/*fputc('a', pf);fputc('b', pf);fputc('c', pf);*/fclose(pf);pf = NULL;return 0;
}

此时再次运行,我们发现那个文件里的内容不见了(大小也变为0kb): 


4、文本行输入函数 fgets

  • 从指定的流 stream 读取一行,并把它存储在 string 所指向的字符串中,当读取(n-1)个字符时,或者读取到换行符、到达文件末尾时,它会停止,具体视情况而定。适用于所有输入流。

注意:假如 n 是 100,读取到的就是 99 个字符(n-1),因为要留一个字符给 '\0'。

 

#include <stdio.h>int main()
{char arr[10] = "xxxxxx"; // 存放处FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}fgets(arr, 4, pf);printf("%s\n", arr);fgets(arr, 4, pf);printf("%s\n", arr);fclose(pf);pf = NULL;return 0;
}


5、文本行输出函数 fputs

  • 将字符串写入到指定的流 stream 中(不包括空字符)。适用于所有输出流。

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL){perror("fopen");return 1;}fputs("abcdef", pf);fputs("123456", pf);fclose(pf);pf = NULL;return 0;
}

如果想要在 "abcdef" 后面换行,只需在 fputs("abcdef\n", pf); 加上换行符即可。 


6、 格式化输入函数 fscanf

  • fscanf 用于对格式化的数据进行读取,从流 stream 读取格式化输入。适用于所有输入流。

#include <stdio.h>struct Student
{char name[10];int id;float score;
};int main()
{struct Student s1 = { 0 };// 对格式化的数据进行写文件FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}fscanf(pf, "%s %d %f", s1.name, &(s1.id), &(s1.score));printf("%s %d %f\n", s1.name, s1.id, s1.score);fclose(pf);pf = NULL;return 0;
}

注意: p1.name本身就是地址(不用&)。


7、格式化输出函数 fprintf

#include<stdio.h>
struct S
{char arr[10];int num;float sc;
};int main()
{struct S s = { "abcdef", 10, 5.5f };FILE* pf1 = fopen("test.txt", "w");if(pf1 == NULL){perror("fopen");return 1;}fprintf(pf1, "%s %d %f", s.arr, s.num, s.sc); // 将结构体格式化的数据写入文件fclose(pf1);pf1 = NULL;struct S temp = { 0 }; // 用于存储读出的数据 FILE* pf2 = fopen("test.txt", "r");if(pf2 == NULL){perror("fopen");return 1;}fscanf(pf2, "%s %d %f", temp.arr, &(temp.num), &(temp.sc));	// 再把数据从文件中读到结构体中printf("%s %d %f\n", temp.arr, temp.num, temp.sc); // 打印fclose(pf2);pf2 = NULL;return 0;
}


8、二进制输入函数 fread

  • 从流中读取,从给定流 stream 读取数据到 buffer 所指向的数组中。

#include <stdio.h>
// 二进制的形式读struct S
{char arr[10];int num;float score;
};int main()
{struct S s = { 0 };FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}fread(&s, sizeof(struct S), 1, pf);printf("%s %d %f", s.arr, s.num, s.score);fclose(pf);pf = NULL;return 0;
}

9、二进制输出函数 fwrite

  •  写一个数据到流中去,把 buffer 所指向的数组中的数据写入到给定流 stream 中。

#include <stdio.h>
// 二进制的形式写struct S
{char arr[10];int num;float score;
};int main()
{struct S s = { "abcde", 10, 5.5f };FILE* pf = fopen("test.txt", "w");if (pf == NULL){perror("fopen");return 1;}fwrite(&s, sizeof(struct S), 1, pf);fclose(pf);pf = NULL;return 0;
}

 

为什么是乱码?为什么 abcde 不是乱码?
  1. 我们刚才用的都是文本编译器,文本编译器打开二进制形式的文件完全是两种状态。
  2. 因为字符串以文本形式写进去和以二进制形式写进去是一样的,但是对于整数、浮点数等来说就不一样了,文本形式写入和二进制形式写入完全是两个概念。

结论:fwritefread 是一对,fwrire 写进去用 fread 读。


八、文件的随机读写

1、文件指针定位函数 fseek

  • 根据文件指针的位置和偏移量来定位文件指针。

int fseek (FILE* stream, long int offset, int origin);// offset是偏移量,origin是起始位置,有三种选项:// 1、SEEK_CUR - 当前文件指针的位置开始偏移。
// 2、SEEK_END - 文件的末尾位置开始偏移。
// 3、SEEK_SET - 文件的起始位置开始偏移。

 

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}

如果我想得到 a a b,该怎么处理呢?
#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL) {perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);// 调整文件指针fseek(pf, -1, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为-1,向前移动1个单位ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}


⚪用 SEEK_SET ,打印 a d e

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);// 调整文件指针fseek(pf, 2, SEEK_CUR); // SEEK_SET为文件的起始位置,偏移量为2,向后移动2个单位ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}


⚪用 SEEK_END ,打印 a e f 

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);// 调整文件指针fseek(pf, -2, SEEK_END); // SEEK_END为当前文件末尾位置,偏移量为-2,向前移动2个单位ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}


2、返回偏移量函数 ftell

  • 返回文件指针相对于起始位置的偏移。

long int ftell ( FILE * stream );
#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}// 调整文件指针fseek(pf, 5, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为5,向后移动5个单位int ch = fgetc(pf);printf("%c\n", ch); // f// 返回偏移量int ret = ftell(pf);printf("%d\n", ret); // 6fclose(pf);pf = NULL;return 0;
}

 


3、文件指针回到起始位置函数 rewind

  • rewind(意为倒带,磁带倒带),设置文件位置为给定流 stream 的文件的开头,让文件指针回到起始位置

#include <stdio.h>int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}// 调整文件指针fseek(pf, 5, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为5,向后移动5个单位// 返回偏移量int loc = ftell(pf);printf("fseek调整文件指针后:%d\n", loc); // 6// 让文件指针回到起始位置rewind(pf);// 再次返回偏移量,看看是不是回到起始位置了loc = ftell(pf);printf("使用rewind后:%d\n", loc); // 6fclose(pf);pf = NULL;return 0;
}


九、文件读取结束的判定 

1、被错误使用的 feof

  • 在文件结束时判断文件因为何种原因导致文件结束的函数判断是因为读取失败而结束,还是因为遇到文件尾而结束。如果文件结束,则返回非 0 值,否则返回 0。

注意feof 函数是个经常被错误使用的一个函数。在文件读取过程中,不能用 feof 函数的返回值直接判断文件是否结束!feof 函数绝对不是用来判断文件是否结束的函数!feof 不是用来判定文件是否结束了的,还是在文件已经结束时,判断是什么原因导致文件结束的

文本文件读取是否结束,判断返回值是否为EOF fgetc),或者NULLfgets

  • fgetc 判断是否为 EOF。
  • fgets 判断返回值是否为 NULL。
#include <stdio.h>
#include <stdlib.h>int main()
{int ch = 0; // 注意:int,非char,要求处理EOFFILE* pf = fopen("test.txt", "r");if (!pf){perror("fopen");return EXIT_FAILURE; // 符号常量EXIT_FAILURE,表示没有成功地执行一个程序}// fgetc - 当读取失败的时候或者遇到文件结束的时候,都会返回EOFwhile ( (ch = fgetc(pf)) != EOF ){putchar(ch);}printf("\n");// 判断文件结束的原因if (ferror(pf)) // ferror - 检查是否出现错误{  puts("读取失败错误(I/O error when reading)");}else if (feof(pf)){puts("遇到文件尾而结束(End of file reached successfully)");}fclose(pf);pf = NULL;
}

 


二进制文件的读取结束判断,判断返回值是否小于实际要读的个数

  • fread 判断返回值是否小于实际要读的个数。
#include <stdio.h>enum { SIZE = 5 };int main(void)
{double a[SIZE] = {1.0,2.0,3.0,4.0,5.0};double b = 0.0;size_t ret_code = 0;FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式fwrite(a, sizeof(*a), SIZE, fp); // 写double的数组fclose(fp);fp = fopen("test.bin","rb");// 读 double 的数组while((ret_code = fread(&b, sizeof(double), 1, fp))>=1){printf("%lf\n",b);}if (feof(fp)){printf("Error reading test.bin: unexpected end of file\n");}else if (ferror(fp)){perror("Error reading test.bin");}fclose(fp);fp = NULL;
}


2、正确判定文件是否读取结束的方法

  • 文本文件读取是否结束,判断返回值是否为 EOFfgetc),或者 NULLfgets)。
  1. fgetc 函数在读取结束时会返回 EOF,正常读取时,返回读取到的字符的 ASCII 码值
  2. fgets 函数在读取结束时会返回 NULL,正常读取时,返回存放字符串的空间的起始地址
  3. fread 函数在读取结束时会返回实际读取到的完整元素的个数,如果发现读取到的完整的元素个数小于指定的元素个数,那么就是最后一次读取了。

相关文章:

【C语言】文件操作 -- 详解

一、什么是文件 磁盘上的文件是文件。 1、为什么要使用文件 举个例子&#xff0c;当我们想实现一个 “通讯录” 程序时&#xff0c;在通讯录中新建联系人、删除联系人等一系列操作&#xff0c;此时的数据存储于内存中&#xff0c;程序退出后所有数据都会随之消失。为了让通讯录…...

飞天使-k8s基础组件分析-持久化存储

文章目录 emptyDirhostpathpv和pvc介绍nfs作为静态pv案例nfs作为动态pv案例使用本地文件夹作为pv改变默认存储类及回收策略参考文档 emptyDir 重启文件还有&#xff0c;但是如果杀了进程&#xff0c;则会丢失文件 创建pod # kubectl apply –f redis.yaml校验pod是否处于运行&…...

python连接PostgreSQL 数据库

执行如下命令安装 pip3 install psycopg2 python代码 Author: tkhywang 2810248865qq.com Date: 2023-08-21 11:42:17 LastEditors: tkhywang 2810248865qq.com LastEditTime: 2023-08-21 11:51:56 FilePath: \PythonProject02\PostgreSQL 数据库.py Description: 这是默认设置…...

数字图像处理—— Lab、YCbCr、HSV、RGB之间互转

Lab “Lab” 图像格式通常指的是 CIELAB 色彩空间&#xff0c;也称为 Lab 色彩空间。它是一种用于描述人类视觉感知的颜色的设备无关色彩空间&#xff0c;与常见的 RGB 和 CMYK 色彩空间不同。CIELAB 由国际照明委员会&#xff08;CIE&#xff09;于1976年定义&#xff0c;用于…...

自动驾驶SLAM技术第四章习题2

在g2o的基础上改成ceres优化&#xff0c;高博都写好了其他的部分, 后面改ceres就很简单了. 这块我用的是ceres的自动求导&#xff0c;很方便&#xff0c;就是转化为模板仿函数的时候有点麻烦&#xff0c; 代码部分如下 ceres_type.h : ceres优化核心库的头文件 这个文件写的内…...

vue拖拽div盒子实现上下拖动互换

vue拖拽div盒子实现上下拖动互换 <div v-for"(item, index) in formList" :key"index" draggable"true"dragstart"handleDragStart($event, item)"dragenter"handleDragEnter($event, item)"dragover.prevent"han…...

Visual Studio 2022 右键单击项目没有出现View | View Class Diagram(Visual Studio 无法使用类设计器)

文章目录 问题描述原因.NET Core项目.NET Framework项目 问题描述 当我们在Solution Explorer窗口右键单击项目时&#xff0c;快捷菜单中没有出现“查看”&#xff0c;或者出现了“查看”&#xff0c;但是“查看”里没有View Class Diagram。 原因 首先你要确保你安装了类设…...

EFCore常见用法

EFCore官方文档置顶&#xff0c;看这个就行。下面的内容只是总结&#xff0c;算是备忘录。 一、创建和删除 //1、创建数据库和表 db.Database.EnsureCreated();//将创建数据库&#xff08;如果不存在&#xff09;并初始化数据库架构。 如果存在任何表 (包括另一 DbContext 类)…...

概率论与数理统计:第六章:数理统计

文章目录 Ch6. 数理统计(一) 总体与样本(二) 统计量 (5个)2.5个常用统计量3.矩的概念 (三) 抽样分布 (3个)0.上α分位点1.χ分布2.t分布3.F分布 (四) 抽样分布定理1.单个正态总体2.两个正态总体 Ch6. 数理统计 (一) 总体与样本 1.概念&#xff1a; (1)总体 (2)样本 简单随机…...

拥塞控制(TCP限制窗口大小的机制)

拥塞控制机制可以使滑动窗口在保证可靠性的前提下&#xff0c;提高传输效率 关于滑动窗口的属性以及部分机制推荐看TCP中窗口和滑动窗口的含义以及流量控制 拥塞控制出现的原因 看了上面推荐的博客我们已经知道了&#xff0c;由于接收方接收数据的能力有限&#xff0c;所以要通…...

校园供水系统智能管理

import pandas as pd data1pd.read_excel("C://Users//JJH//Desktop//E//附件_一季度.xlsx") data2pd.read_excel("C://Users//JJH//Desktop//E//附件_二季度.xlsx") data3pd.read_excel("C://Users//JJH//Desktop//E//附件_三季度.xlsx") data4…...

Flask-SocketIO和Flask-Login联合开发socketio权限系统

设置 Flask, Flask-SocketIO, Flask-Login: 首先&#xff0c;确保安装了必要的库: pip install Flask Flask-SocketIO Flask-Login基础设置: from flask import Flask, render_template, redirect, url_for, request from flask_socketio import SocketIO, emit from flask_…...

航空电子设备中的TSN通讯架构—直升机

前言 以太网正在迅速取代传统网络&#xff0c;成为航空电子设备和任务系统的核心高速网络。本文提出了以太网时间敏感网络(TSN)在航空电子设备上应用的技术优势问题。在实际应用中&#xff0c;TSN已成为一个具有丰富的机制和协议的工具箱&#xff0c;可满足与时间和可靠性相关…...

elment-ui中使用el-steps案例

el-steps案例 样式 代码 <div class"active-box"><div class"active-title">请完善</div><el-steps :active"active" finish-status"success" align-center><el-step title"第一步" /><…...

FPGA解析串口指令控制spi flash完成连续写、读、擦除数据

前言 最近在收拾抽屉时找到一个某宝的spi flash模块&#xff0c;如下图所示&#xff0c;我就想用能不能串口来读写flash&#xff0c;大致过程就是&#xff0c;串口向fpga发送一条指令&#xff0c;fpga解析出指令控制flah&#xff0c;这个指令协议目前就是&#xff1a; 55 AA …...

msvcp120.dll丢失的解决方法,分享三种快速修复的方法

今天&#xff0c;我将和大家分享一个关于电脑问题的解决方法——msvcp120.dll丢失的解决方法。希望对大家有所帮助。 首先&#xff0c;让我们来了解一下msvcp120.dll文件。msvcp120.dll是Microsoft Visual C 2010 Redistributable Package的一个组件&#xff0c;它包含了一些运…...

mysql 8.0 窗口函数 之 序号函数 与 sql server 序号函数 一样

sql server 序号函数 序号函数 ROW_NUMBER() 顺序排序RANK() 并列排序&#xff0c;会跳过重复的序号&#xff0c;比如序号为1&#xff0c;1&#xff0c;3DENSE_RANK() 并列排序&#xff0c;不会跳过重复的序号&#xff0c;比如 序号为 1&#xff0c;1&#xff0c;2 语法结构…...

fastgpt构建镜像

1.把client目录复制到服务器 .next和node_modules文件夹不用上传到服务器 在服务器目录运行 docker build -t fastgpt:1.0.3 . 构建服务 再运行 docker ps 就可以看到容器了...

Git笔记--分支常用命令

目录 1--git branch -v 2--git branch 3--git checkout 4--git merge 1--git branch -v git branch -v git branch -v 用于查看分支版本&#xff1b; 2--git branch git branch xxxxx # xxxxx表示分支名 git branch 用于创建分支&#xff1b; 3--git checkout git check…...

常见设计模式学习+面试总结

一 设计模式简介 二 面试总结 1 什么是单例模式&#xff1f;都有哪些地方用到单例&#xff1f; 内存中只会创建且仅创建一次对象的设计模式&#xff0c;保证一个类只有一个实例&#xff0c;并且提供一个访问该全局访问点。 应用场景&#xff1a; 网站的计数器&#xff0c;一般…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目&#xff0c;核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容&#xff0c;附学习方向和应试技巧&#xff1a; 一、施工组织与进度管理 核心目标&#xff1a; 规…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...