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

文件操作~

目录

1.为什么使用文件?

2.什么是文件?

2.1 程序文件

2.2 数据文件

2.3 文件名

3.⼆进制文件和文本文件?

4.文件的打开和关闭

4.1 流和标准流

4.1.1 流

4.1.2 标准流

4.2 文件指针

4.3 ⽂件的打开和关闭

5.文件的顺序读写

5.1 顺序读写函数介绍

5.1.1什么是EOF

5.1.2 fputc函数

5.1.3 fgetc函数

5.1.4 fputs函数

5.1.5 fgets

5.1.6 fprintf函数

5.1.7 fscanf函数

5.1.8 fwrite函数

5.1.9fread函数

5.2 对比⼀组函数:

6.文件的随机读写

6.1fseek

6.2ftell

6.3 rewind

7.文件读取结束的判定

7.1 被错误使用的 feof

8. ⽂件缓冲区


1.为什么使用文件?

如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件。

2.什么是文件?

磁盘(硬盘)上的文件是文件。

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

2.1 程序文件

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

2.2 数据文件

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

本章讨论的是数据文件。

在以前各章所处理数据的输⼊输出都是以终端为对象的,即从终端的键盘输⼊数据,运行结果显示到显示器上。

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

2.3 文件名

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

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

例如: c:\code\test.txt

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

3.⼆进制文件和文本文件?

根据数据的组织形式,数据文件被称为⼆进制文件和文本文件?

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

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

⼀个数据在文件中是怎么存储的呢?

字符⼀律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。

如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符⼀个字节),而⼆进制形式输出,则在磁盘上只占4个字节。

用二进制写入,用文本文件不能打开,只能使用二进制的形式打开

#include <stdio.h>
​
int main() {int a = 1000;FILE* pf = fdopen("test.txt", "wb");fwrite(&a, 4, 1, pf); //找到a的地址写入,写入四个字节,写入一次,找到关联的文件fclose(pf);pf = NULL;return 0;
}

4.文件的打开和关闭

4.1 流和标准流

4.1.1 流

流-->一个媒介,连接程序和外部设备

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。

C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的。

⼀般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作,最后关闭流

4.1.2 标准流

那为什么我们从键盘输入数据(在C语言中),向屏幕上输出数据,并没有打开流呢?

那是因为C语⾔程序在启动的时候,默认打开了3个流:

  • stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。

  • stdout - 标准输出流,⼤多数的环境中输出到显示器界面,printf函数就是将信息输出到标准输出流中。

  • stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯

这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进行输入输出操作的。

stdin、stdout、stderr 三个流的类型是: FILE * ,通常称为文件指针。

C语言中,就是通过 FILE* 的文件指针来维护流的各种操作的。

4.2 文件指针

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

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

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

下⾯我们可以创建⼀个FILE*的指针变量:

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

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

4.3 ⽂件的打开和关闭

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

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

ANSI C 规定使用 fopen 函数来打开文件, fclose 来关闭文件。

文件操作,文件中有路径的话 最好加上两个斜杠

  • E:\C\Code\Cproject\practice6.17\practice6.17(绝对路径)

  • 如果用相对路径, " . " 表示当前路径 ". ."表示上一级路径

    • 那我们要访问该路径的上一级路径的文件时, " .\ \ ..\ \ test.txt "

int main() {//1.打开文件//打开成功返回一个有效的指针//打开失败,返回NULL(判断文件指针是否为空)FILE* pf = fopen("test.txt", "w"); //D:\\WeGameApps\\if (pf == NULL) {perror("fopen");return 1;}//2.写文件操作//...
​//关闭文件fclose(pf);
​
}

5.文件的顺序读写

5.1 顺序读写函数介绍

文件按照顺序去读写,光标

5.1.1什么是EOF

在C语言中,EOF(End of File)是一个特殊的标记,用于表示文件的结尾。当我们读取文件或者输入数据时,EOF可以帮助我们确定何时到达了文件的末尾。本文将详细介绍EOF的意义和用法,并提供一些示例代码以帮助理解。

  1. EOF的意义 EOF在C语言中用于标识文件的结尾。当我们从文件中读取数据时,EOF可以告诉我们何时已经读取完了文件中的所有内容。这对于文件的处理非常重要,因为它允许我们在读取文件时判断何时停止读取并继续执行其他操作。

  2. EOF的用法 在C语言中,我们可以使用EOF常量来表示文件的结尾。EOF的值是一个特殊的整数常量,通常被定义为-1。当我们从文件中读取数据时,EOF常量可以与读取的字符进行比较,以确定是否已经到达了文件的结尾。

如下代码从文件中读取所有字符 等于EOF就是到了文件结尾,结束循环

while((ch = fgetc(pf)) != EOF)

5.1.2 fputc函数

写字符操作,一个个字符写入 该函数有两个参数 ---> fputc(i,pf); // i表示要写入的内容 pf 文件指针流

int main() {//1.打开文件//打开成功返回一个有效的指针//打开失败,返回NULL(判断文件指针是否为空)FILE* pf = fopen("test.txt", "w");if (pf == NULL) {perror("fopen");return 1;}//2.写文件操作int i = 0;for (int i = 'a'; i <= 'z'; i++) {fputc(i,pf); // i表示要写入的内容 pf 文件指针流}
​//关闭文件fclose(pf);
​
}

5.1.3 fgetc函数

读字符函数, fgetc(pf), 只有一个参数(文件指针流)

int main() {//1.打开文件//打开成功返回一个有效的指针//打开失败,返回NULL(判断文件指针是否为空)FILE* pf = fopen("test.txt", "r");if (pf == NULL) {perror("fopen");return 1;}//2.读文件操作int ch = fgetc(pf); //读取到一个字符赋值给ch 然后光标就往下printf("%c\n", ch);ch = fgetc(pf);    //再读取一个 赋值给ch 光标再往下printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);
​//关闭文件fclose(pf);pf = NULL;
}

另外一种读 操作 使用EOF

int main() {//1.打开文件//打开成功返回一个有效的指针//打开失败,返回NULL(判断文件指针是否为空)FILE* pf = fopen("test.txt", "r");if (pf == NULL) {perror("fopen");return 1;}//2.读文件操作int ch = 0;while ((ch = fgetc(pf)) != EOF){printf("%c", ch);}
​//关闭文件fclose(pf);
​
}
  • 在上面我们所提到的标准流 stdin和stdout也可以用上面的读写函数,他们适合所有的输入输出流

  • 实现在屏幕输入一个字符,在屏幕输出一个字符

int main() {int ch = fgetc(stdin);fputc(ch, stdout);return 0;
}

5.1.4 fputs函数

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

文本输入函数, 第一个参数是输入一个字符串,第二个参数是文件指针流

int main() {//1.打开文件FILE* pf = fopen("test.txt", "w");if (pf == NULL) {perror("fopen");return 1;}//2.操作文件fputs("i am a man", pf);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

5.1.5 fgets

char * fgets ( char * str, int num, FILE * stream );

第一个参数用一个字符数组存储读到的字符串,第二个参数,最多读到多少个字符,第三个参数文件指针流

注意:在读字符的时候,实际读到的只是(num-1)个字符因为包含了一个\0,或者遇到换行的时候也会终止读取

int main() {//1.打开文件FILE* pf = fopen("test.txt", "r");if (pf == NULL) {perror("fopen");return 1;}//2.操作文件char arr[20] = { 0 };fgets(arr, 5, pf);printf("%s", arr);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

同样以上两个函数同样适合所有的输入输出流,以下实现在屏幕输入和输出字符串

int main() {char arr[20] = {0};fgets(arr, 10, stdin);fputs(arr, stdout);
}

5.1.6 fprintf函数

int fprintf ( FILE * stream, const char * format, ... )

格式化输出函数(所有类型都可以) ,适合所有输出流,该函数和printf函数多了个文件指针流,

int main() {char name[20] = "aaa";int age = 20;float score = 95.7f;//1.打开文件FILE* pf = fopen("test.txt", "w");if (pf == NULL) {perror("fopen");return 1;}//2.操作文件fprintf(pf, "%s %d %.1f", name, age, score);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

我们也可以把数据放到结构体里

struct S
{char name[20];int age;float score;
};
​
​
int main() {struct  S s = { "lisi",18,96.2f };//1.打开文件FILE* pf = fopen("test.txt", "w");if (pf == NULL) {perror("fopen");return 1;}//2.操作文件fprintf(pf, "%s %d %.1f", s.name, s.age, s.score);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

5.1.7 fscanf函数

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

要先把数据读出放到一个结构体中,再输出到屏幕

struct S
{char name[20];int age;float score;
};
​
​
int main() {struct  S s = { 0 };//1.打开文件FILE* pf = fopen("test.txt", "r"); //读文件if (pf == NULL) {perror("fopen");return 1;}//2.操作文件//name不用加&符号,因为本来name就是数组首元素地址//把文件中的数据读出来后放到结构体中fscanf(pf, "%s %d %.1f", s.name, &(s.age), &(s.score)); //再把结构体的数据读出printf(" %s %d %.1f", s.name, s.age, s.score);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

5.1.8 fwrite函数

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

第一个参数,取需要写入文件的数据的地址,第二个参数该数据的大小,第三个参数该数据的个数,

以二进制的形式输出到文件中

struct S
{char name[20];int age;float score;
};
int main() {struct  S s = { "lisi",18,96.2f };//1.打开文件 二进制形式写入FILE* pf = fopen("test.txt", "wb");if (pf == NULL) {perror("fopen");return 1;}//2.操作文件fwrite(&s, sizeof(struct S), 1, pf);//3.关闭文件fclose(pf);pf = NULL;return 0;
}
​

5.1.9fread函数

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

将文件中以二进制的形式读出放到ptr指向的空间里

struct S
{char name[20];int age;float score;
};
int main() {struct  S s = { "lisi",18,96.2f };//1.打开文件 二进制形式写入FILE* pf = fopen("test.txt", "rb");if (pf == NULL) {perror("fopen");return 1;}//2.操作文件fread(&s, sizeof(struct S), 1, pf);printf("%s %d %f", s.name, s.age, s.score);//3.关闭文件fclose(pf);pf = NULL;return 0;
}
​

5.2 对比⼀组函数:

  • scanf/fscanf/sscanf

  • printf/fprintf/sprintf

  • 这里重点介绍sscanf函数和sprintf函数

    1.sprintf函数,将其他类型的数据转化成字符串

    struct S
    {char name[20];int age;float score;
    };
    ​
    int main() {char arr[100] = {0};struct  S s = { "aa",17,96.2f};sprintf(arr, "%s %d %f", s.name, s.age, s.score);printf("%s\n", arr);return 0;
    }

    2.sscanf函数 将字符串转化成其他类型的数据

    struct S
    {char name[20];int age;float score;
    };
    ​
    int main() {char arr[100] = {0};struct  S s = { "aa",17,96.2f};//临时变量struct S tmp = { 0 };
    ​sprintf(arr, "%s %d %f", s.name, s.age, s.score);/*printf("%s\n", arr);*/sscanf(arr, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score));printf("%s %d %f", tmp.name, tmp.age, tmp.score);return 0;
    }

6.文件的随机读写

6.1fseek

根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。

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

offsetof --- 计算结构体成员相比于起始位置的偏移量

我们看下面代码 如果想单独读字符e就会比较麻烦,我们可以用fseek函数

int main() {FILE* pf = fopen("test.txt", "rb");if (pf == NULL) {perror("fopen");return 1;}//2.读文件int ch = fgetc(pf); //读取到一个字符赋值给ch 然后光标就往下printf("%c\n", ch);ch = fgetc(pf);    //再读取一个 赋值给ch 光标再往下printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);
​fclose(pf);pf = NULL;return 0;
}

fseek函数,第三个参数可以有三种选项

SEEK_SET文件开头位置
SEEK_CUR文件指针指向的当前位置
SEEK_END文件末尾
int main() {FILE* pf = fopen("test.txt", "rb");if (pf == NULL) {perror("fopen");return 1;}//2.读文件int ch = fgetc(pf); //读取到一个字符赋值给ch 然后光标就往下printf("%c\n", ch);ch = fgetc(pf);    //再读取一个 赋值给ch 光标再往下printf("%c\n", ch);fseek(pf, 2, SEEK_CUR);//在当前位置偏移两个位置找到ech = fgetc(pf);    printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}

6.2ftell

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

我们看下面代码,读完e之后往下一光标,输出偏移量为5

int main() {FILE* pf = fopen("test.txt", "rb");if (pf == NULL) {perror("fopen");return 1;}//2.读文件int ch = fgetc(pf); //读取到一个字符赋值给ch 然后光标就往下printf("%c\n", ch);ch = fgetc(pf);    //再读取一个 赋值给ch 光标再往下printf("%c\n", ch);fseek(pf, 2, SEEK_CUR);ch = fgetc(pf);    printf("%c\n", ch);//输出文件指针相比于文件的起始位置的偏移量printf("%d", ftell(pf));fclose(pf);pf = NULL;return 0;
}

6.3 rewind

让文件指针的位置回到文件的起始

void rewind ( FILE * stream );

7.文件读取结束的判定

7.1 被错误使用的 feof

牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。

因为文件结束有两种,1.遇到文件结尾,2.遇到错误

feof 的作用是:当文件读取结束的时候,再判断是读取结束的原因是否是:遇到文件尾结束。

feof的返回值,如果没有设置就默认返回0(还没到文件末尾),返回1的话代表已经到达文件末尾

1.文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )

例如:

  • fgetc 判断是否为 EOF .

  • fgets 判断返回值是否为 NULL .

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

例如:fread判断返回值是否小于实际要读的个数。

文本文件例子:

include <stdio.h>
#include <stdlib.h>
int main(void)
{int c; // 注意:int,⾮char,要求处理EOFFILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环{ putchar(c);}//判断是什么原因结束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);
}

二进制的例子

#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code == SIZE) {puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n)printf("%f ", b[n]);putchar('\n');}else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);
}
  • ferro函数,如果返回一个非零的整数值,说明读取出问题;返回一个0则表示没有问题

小练习:写一个程序将一个txt文件的内容复制到另外一个txt文件

int main() {//打开文件FILE* pfread = fopen("test.txt", "r");if (pfread == NULL) {perror("fopen\n");return 1;}FILE* pfwrite = fopen("test2.txt","w");if (pfwrite == NULL) {perror("fopen\n");fclose(pfread); //如果打开文件操作出错,则关闭pfread流return 1;}//读或写文件int ch = 0; //返回值要为int类型while ((ch = fgetc(pfread)) != EOF) {fputc(ch, pfwrite); //ch表示要写入的字符}//关闭文件fclose(pfread);pfread = NULL;fclose(pfwrite);pfwrite = NULL;
}

8. ⽂件缓冲区

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

简单来说,就是不能一直让操作系统处理数据,先把数据存起来,再一次过处理,而不是每发一次就处理一次

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

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

相关文章:

文件操作~

目录 1.为什么使用文件&#xff1f; 2.什么是文件&#xff1f; 2.1 程序文件 2.2 数据文件 2.3 文件名 3.⼆进制文件和文本文件&#xff1f; 4.文件的打开和关闭 4.1 流和标准流 4.1.1 流 4.1.2 标准流 4.2 文件指针 4.3 ⽂件的打开和关闭 5.文件的顺序读写 5.1 …...

身边的故事(十二):阿文的故事:消失

那以后就再也没有任何阿文的消息。刚开始还打过几次电话&#xff0c;他都没接。后来也就慢慢的淡忘了&#xff0c;为自己的工作生活而奔波&#xff0c;时间冲淡一切。在那几年里&#xff0c;阿文就像消失了一样。直到2021的某一天&#xff0c;电话那端传来了熟悉但是有点陌生的…...

智能扫地机器人程序中出现的问题可以参考的解决方案

在解决智能扫地机器人程序中可能遇到的问题时&#xff0c;可以参考以下分点表示和归纳的解决方案&#xff1a; 环境感知与地图构建 ① 使用先进的传感器技术&#xff1a;如激光雷达、超声波和红外传感器&#xff0c;以提高环境感知的准确性和可靠性。 ② 优化地图构建算法&a…...

如何借用物联网快速实现高标准农田信息化

如何借用物联网快速实现高标准农田信息化 高标准农田信息化&#xff0c;作为现代农业发展的重要基石&#xff0c;是指在建设高产、稳产、节水、环保的农田基础上&#xff0c;深度融合现代信息技术&#xff0c;实现农田管理的精准化、智能化和高效化。物联网&#xff08;Intern…...

计算机网络基础入门

计算机网络基础入门 目录&#xff1a; 简介网络分层模型数据封装与解封装IP地址与子网掩码网络协议示例代码 1. 简介 计算机网络是指将地理位置不同的多台计算机及外部设备通过通信线路连接起来&#xff0c;实现信息资源共享和信息传递的系统。计算机网络是现代信息社会的基…...

uniApp vue2 vue3配置代理

vue2配置代理 在manifest.json中增加如下配置 "h5" : {"router" : {"mode" : "history"},"devServer" : {"disableHostCheck" : true,"proxy" : {"/api" : {"target" : "请…...

运维锅总详解RocketMQ

本文尝试从Apache RocketMQ的简介、主要组件及其作用、3种部署模式、Controller集群模式工作流程、最佳实践等方面对其进行详细分析。希望对您有所帮助&#xff01; 一、Apache RocketMQ 简介 Apache RocketMQ 是一个开源的分布式消息中间件&#xff0c;由阿里巴巴集团开发并…...

【Linux】使用ntp同步时间

ntp介绍 NTP&#xff08;Network Time Protocol&#xff0c;网络时间协议&#xff09;是一种用于同步计算机时间的协议&#xff0c;工作在UDP的123端口上。它是一种客户端-服务器协议&#xff0c;用于同步计算机的时钟。通过连接到网络上的时间服务器&#xff0c;计算机可以获…...

【FedMut】Generalized Federated Learning via Stochastic Mutation

基于随机变异的泛化联邦学习 来源&#xff1a;AAAI2024 Abstract 问题&#xff1a; FedAvg 将相同的全局模型派发给客户端进行本地训练&#xff0c;容易陷入尖锐解&#xff0c;导致训练出性能低下的全局模型 提出 FedMut&#xff1a; 本文提出了一种名为 FedMut 的新型FL方法…...

在线教育项目(一):如何防止一个账号多个地方登陆

使用jwt做验证&#xff0c;使用账号作为redis中的key,登录的时候生成token放到redis中&#xff0c;每次申请资源的时候去看token 有没有变&#xff0c;因为token每次登录都会去覆盖&#xff0c;只要第二次登录token就不一样了...

旋转变压器软件解码simulink仿真

1.介绍 旋转变压器是一种精密的位置、速度检测装置&#xff0c;尤其适用于高温、严寒、潮湿、高速、振动等环境恶劣、旋转编码器无法正常工作的场合。旋转变压器在使用时并不能直接提供角度或位置信息&#xff0c;需要特殊的激励信号和解调、计算措施&#xff0c;才能将旋转变压…...

LeetCode 1321, 209, 102

目录 1321. 餐馆营业额变化增长题目链接表要求知识点思路代码 209. 长度最小的子数组题目链接标签暴力法思路代码 滑动窗口思路代码 102. 二叉树的层序遍历题目链接标签思路代码 1321. 餐馆营业额变化增长 题目链接 1321. 餐馆营业额变化增长 表 表Customer的字段为custome…...

vant ( weapp ) - - - - - van-tabs组件选中下划线初始位置异常

这里写自定义目录标题 1. 当前效果展示2. 官方解释 & 方案 1. 当前效果展示 明显可以看到框内的光标位置偏移了&#xff0c;但当切换一次之后就会显示正常。 只有初次打开的时候&#xff0c;才会出现上述问题。 代码如下&#xff1a; <van-popup show"{{ makeSho…...

007 栈(lua)

文章目录 Lua本身支持动态数组&#xff0c;通过表&#xff08;table&#xff09;实现&#xff0c;它类似于Java中的ArrayList。Lua的表是灵活的数组和字典的混合体。对于栈的实现&#xff0c;我们可以简单地使用一个表来模拟。 这里是一个简单的Lua栈实现&#xff0c;它包含了p…...

SQL中Order by详解

在 MySQL 中&#xff0c;ORDER BY 语句用于对查询结果进行排序。 语法&#xff1a; SELECT column1, column2,... FROM table_name ORDER BY column_name [ASC | DESC];以下是对其主要部分的详细解释&#xff1a; column_name &#xff1a;指定要依据其进行排序的列名。 ASC…...

【git】存在git LFS文件时如何处理

目录 1. 安装 Git LFS2. 初始化 Git LFS3. 跟踪大文件4. 添加和提交文件5. 克隆和拉取包含 LFS 文件的仓库 1. 安装 Git LFS 首先&#xff0c;你需要在你的系统上安装 Git LFS。你可以使用以下命令来安装&#xff1a; 在 Linux 上 # 对于基于 Debian 的系统 (如 Ubuntu) sud…...

面向阿克曼移动机器人(自行车模型)的LQR(最优二次型调节器)路径跟踪方法

线性二次调节器&#xff08;Linear Quadratic Regulator&#xff0c;LQR&#xff09;是针对线性系统的最优控制方法。LQR 方法标准的求解体系是在考虑到损耗尽可能小的情况下, 以尽量小的代价平衡其他状态分量。一般情况下&#xff0c;线性系统在LQR 控制方法中用状态空间方程描…...

【运维】在 Docker 容器中指定 UTF-8 编码:方法与技巧

在 Docker 容器中指定 UTF-8 编码&#xff1a;方法与技巧 在日常开发中&#xff0c;我们常常需要确保应用程序能正确处理各种字符编码&#xff0c;尤其是 UTF-8 编码。在 Docker 容器中运行应用程序时&#xff0c;正确设置字符编码尤为重要&#xff0c;因为容器通常是跨平台、…...

primetime中cell和net的OCV

文章目录 前言一、Cell OCV1. POCV coefficient file2. POCV Slew-Load Table in Liberty Variation Format&#xff08;LVF lib&#xff09; 二、Net OCV三、如何check OCV是否已加上&#xff1f;总结 前言 在生产中&#xff0c;外界环境的各种变化&#xff0c;比如PVT&#…...

FlinkX学习

FlinkX学习 FlinkX安装 由于flinkx已经改名chunjun 官网已不存在 (https://gitee.com/lugela/flinkx#flinkx)这里可以看到flinkx的操作文档 1、上传并解压 unzip flinkx-1.10.zip -d /usr/local/soft/2、配置环境变量 FLINKX_HOME/usr/local/soft/flinkx-1.10 export PATH$F…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...