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

C语言中的文件

文章目录

  • 文件
    • 1. 流
      • 1.1 文件缓冲
      • 1.2 标准流
      • 1.3 文本文件和二进制文件
    • 2. 打开/关闭文件
      • 2.1 fopen
      • 2.2 fclose
    • 3. 读写文件
      • 3.1 fgetc & fputc
      • 3.2 fgets & futs
      • 3.3 fscanf & fprintf
      • 3.4 fread & fwrite
    • 4. 文件定位
    • 5. 错误处理
      • 5.1 errno

文件

1. 流

在 C 语言中, (stream) 表示任意输入的源或任意输出的目的地。流是一个抽象的概念,它既可以表示存储硬盘上的文件,也可以表示网络端口或者打印设备。流这个概念可以很好地屏蔽硬件设备之间的差异,使得 C 语言可以像读写文件一样读写任意的设备。

Linux哲学:一切皆文件。

1.1 文件缓冲

仅仅了解抽象的概念是不够的,有时候我们还需要了解事物运行的机理。由于内存和硬件设备之间存在读写性能上的"鸿沟",所以操作系统会在内存上为流设置缓冲区。

在这里插入图片描述

缓冲区是以先进先出的方式管理数据的。缓冲区分为三种类型:

  • 满缓冲。当缓冲区空时,从输入流中读取数据;当缓冲区满时,向输出流中写入数据。
  • 行缓冲。每次从输入流中读取一行数据;每次向输出流中写入一行数据(stdin、stdout)。
  • 无缓冲。顾名思义,就是没有缓冲区(stderr)。

1.2 标准流

C 语言对流的访问是通过文件指针实现的,它的类型为 FILE* 。并且在<stdio.h>头文件中提供了 3 个标准流。这 3 个标准流可以直接使用——我们不需要对其进行声明,也不用打开或者关闭它们。

文件指针默认含义
stdin标准输入键盘
stdout标准输出屏幕
stderr标准错误屏幕

1.3 文本文件和二进制文件

C 语言支持两种类型的文件:文本文件和二进制文件。文本文件中存储的是字符数据,人类是可以看懂的;二进制文件中的数据,人类是看不懂的。

[!TIP]

二进制文件的存储的基本单位是字节

文本文件的基本单位是字符(字符 = 字节 + 编码(比如GBK UTF-8))

文本文件具有两个独特的性质:

  • 文本文件有行的概念。文本文件被划分为若干行,并且每一行的结尾都以特殊字符进行标记。在 Windows 系统中,是以回车符和换行符 (\r\n) 进行标记的;在 Unix 和 Macintosh 系统中是以换行符 (\n) 标记的。

  • 文本文件可能包含一个特殊的“文本末尾”标记。一些操作系统允许在文本文件的末尾使用一个特殊的字节作为标记。在 Windows 系统中,这个标记为 ‘\x1a’ (Ctrl+Z)。Ctrl+Z不是必需的,但如果存在,它就标志着文件的结束,其后的所有字节都会被忽略。大多数其他操作系统 (包括 UNIX) 是没有文件末尾字符。

    使用 Ctrl+Z 的这一习惯继承自 DOS,而 DOS 中的这一习惯又是从 CP/M (早期用于个人电脑的一种操作系统) 来的。

在写入数据时,我们需要考虑是以文本形式存储还是以二进制的形式存储。比如,存储整数 32767,一种选择是写入字符 ‘3’, ‘2’, ‘7’, ‘6’, ‘7’,需要 5 个字节。

在这里插入图片描述

另一个选择是以二进制形式存储这个数,这种方法只需要两个字节。

在这里插入图片描述

文本形式可以方便人类阅读和编辑;二进制形式可以节省空间,并且转换效率高。

2. 打开/关闭文件

2.1 fopen

读写文件之前,我们需要使用 fopen 函数打开文件。

FILE* fopen(const char* filename, const char* mode);

第一个参数是文件的路径,用来定位文件的;第二个参数表示是以何种模式打开文件的。如果无法打开文件, fopen 返回空指针。

文件路径

文件路径分为两种,一种是绝对路径:从根目录 (或者盘符) 开始,一直到文件所在的位置,比如:“c:/project/test.dat”。另一种是相对路径:从当前工作目录开始,一直到文件所在的位置,比如:“in.dat”。

在实际工作中,我们一般使用相对路径 (Why? 简单高效)。

模式

模式的选择不仅依赖于后续对文件的操作,还依赖于文件是文本形式还是二进制形式。打开一个文本文件,可以使用下面一些模式:

模式字符串含义
“r”打开文件用于读
“w”打开文件用于写(文件不存在则创建)
“a”打开文件用于追加(文件不存在则创建)
“r+”打开文件用于读和写,从文件头开始
“w+”打开文件用于读和写(文件不存在则创建)
“a+”打开文件用于读和写(文件不存在则创建)

当使用 fopen 打开二进制文件时,需要在模式字符串中包含字母 b。

模式字符串含义
“rb”打开文件用于读
“wb”打开文件用于写(文件不存在则创建)
“ab”打开文件用于追加(文件不存在则创建)
“r+b"或"rb+”打开文件用于读和写,从文件头开始
“w+b"或"wb+”打开文件用于读和写(文件不存在则创建)
“a+b"或"ab+”打开文件用于读和写(文件不存在则创建)

写模式和追加模式是不一样的。如果文件存在,写模式会清空原有的数据,而追加模式会在原有数据的后面写入新的内容。

2.2 fclose

fclose 可以关闭程序不再使用的文件。

int fclose(FILE* stream);

如果成功关闭,fclose返回零;否则返回 EOF。

[!TIP]

注意:当不再使用某个文件时,一定要及时关闭该文件。

下面给出了一个程序框架,展示了在实际工作中是如何打开和关闭文件的:

FILE* fp = fopen(filename, mode);
if (fp == NULL) {// error handling
}
...
fclose(fp);

3. 读写文件

前面介绍了如何打开和关闭文件,接下来我们来学习下如何读写文件。

其中 fgetc/fputc , fgets/fputsfscanf/fprintf 是用来读写文本文件的;

fread/fwrite 是用来读写二进制文件的。

3.1 fgetc & fputc

fgetc

fgetc 可以从输入流中读取一个字符,如果读取成功,返回读取的字符;如果读到文件末尾,或者读取失败,返回 EOF。

int fgetc(FILE* stream);

fgetcgetchar 类似。不同的是 getchar 只能从标准输入流(stdin)中读取字 符,而 fgetc 可以从任意一个输入流中读取字符。

fputc

fputc 可以向输出流中写入一个字符,如果写入成功,返回写入的字符;如果写入失败,返回EOF。

int fputc(int c, FILE* stream);

fputcputchar 类似。不同的是 putchar 只能向标准输出流(stdout)中写入字符,而fputc 可以向任意一个流中写入字符。

示例

#include <stdio.h>
#include <cstdlib>int main(int argc, char** argv) {if (argc != 3) {printf("Error: invalid arguments\n");exit(EXIT_FAILURE);}// 打开文件流FILE* source_fp = fopen(argv[1], "r");if (source_fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}FILE* dest_fp = fopen(argv[2], "w");if (dest_fp == NULL) {printf("Can not open %s\n", argv[2]);fclose(source_fp);exit(EXIT_FAILURE);}// 复制文件int c = 0;while ((c = fgetc(source_fp)) != EOF) {fputc(c, dest_fp);}// 关闭文件流fclose(source_fp);fclose(dest_fp);return 0;
}

3.2 fgets & futs

一个字符一个字符地读写文本文件,效率太慢了。C 语言提供了一次性可以读写一行的函数 fgetsfputs

fgets

从输入流 stream 中,最多读取 count - 1 个字符,并把读取的字符存入 str 指向的字符数组中。 fgets 遇到换行符’\n’,或者文件的末尾就会终止(也就是说,读取的字符数可能不足 count - 1 个),并且会存储换行符’\n’。 fgets 会在最后添加空字符’\0’。

char* fgets(char* str, int count, FILE* stream);
参数:str: 指向一个字符数组count: 能够写入的最大字符数量(通常是str指向字符数组的长度)stream: 输入流
返回值:成功:返回str失败:NULL

fgetsgets 的通用版本,它可以从任意输入流中读取数据,而 gets 只能从 stdin 中读取数据。

fgets 也比 gets 更为安全,因为它限制了读取字符的最大数目 (count - 1)。此外,如果 fgets 是因为读取了换行符而终止,那么它会存储换行符’\n’,而 gets 函数从来不会存储换行符。

fputs

将 str 指向的字符串,写入输出流 stream 中。

int fputs(const char* str, FILE* stream);
参数:str: 要写的字符串('\0'结尾的字符串)stream: 输出流
返回值:成功:返回一个非负值。失败:返回EOF,并设置errno。

fputsputs 的通用版本,它可以将字符串写入到任意的输出流中,而 puts 只能 写入到 stdout 中。此外, fputs 是原样输出字符串,而 puts 会在字符串后面而外 输出一个换行符’\n’。

示例

#include <stdio.h>
#include <cstdlib>int main(int argc, char** argv) {if (argc != 3) {printf("Error: invalid arguments\n");exit(EXIT_FAILURE);}// 打开文件流FILE* source_fp = fopen(argv[1], "r");if (source_fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}FILE* dest_fp = fopen(argv[2], "w");if (dest_fp == NULL) {printf("Can not open %s\n", argv[2]);fclose(source_fp);exit(EXIT_FAILURE);}// 复制文件(fgets & fputs)char str[1024];while (fgets(str, sizeof(str), source_fp) != NULL) {fputs(str, dest_fp);}// 关闭文件流fclose(source_fp);fclose(dest_fp);return 0;
}

3.3 fscanf & fprintf

fscanf

fscanfscanf 类似,是用来进行格式化输入的。

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

不同的是, scanf 是从标准输入(stdin)中读取数据,而 fscanf可以从任何一个流中读取数据。也就是说,当 fscanf 的第一个参数为 stdin 时,它的效果等价于scanf

顺便提一下,sscanf 可以从字符串中读取数据。

fprintf

fprintfprintf 类似,是用来进行格式化输出的。

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

不同的是, printf 始终是向标准输出(stdout)写入内容的,而 fprintf 可以向任何一个输出流中写入内容。也就是说,当 fprintf 的第一个参数为 stdout 时,它的效果等价于 printf

顺便提一下, sprintf 可以将内容写入到一个字符数组中。

格式化输入输出,可以用于序列化和反序列化过程中。所谓序列化,就是将程序中的对象转换成一种可以保存的格式(二进制或文本),从而方便存储(存储到文件或数据库中)或传输(通过网络传输给另一台机器)。反序列化则是序列化的逆过程,它将按一定格式存储的数据转换成程序中的对象。

示例

#include <stdio.h>
#include <cstdlib>typedef struct {char name[25];int age;char gender;
} Student_t;int main(int argc, char** argv) {if (argc != 2) {printf("Error: invalid arguments\n");exit(EXIT_FAILURE);}Student_t stu1 = {"tom", 18, 'f'};FILE* fp = fopen(argv[1], "w");if (fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}// 序列化fprintf(fp, "%s %d %c", stu1.name, stu1.age, stu1.gender);fclose(fp);fp = fopen(argv[1], "r");if (fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}// 反序列化Student_t stu2 = {"jack", 19, 'm'};fscanf(fp, "%s %d %c", stu2.name, &stu2.age, &stu2.gender);fclose(fp);printf("Stu2.name: %s Stu2.age: %d Stu2.gender: %c\n", stu2.name, stu2.age, stu2.gender);return 0;
}

3.4 fread & fwrite

freadfwrite 主要是用来处理二进制文件的。 fread 可以每次读取一大块数据, fwrite 可以每次写入一大块数据。

fread 从输入流 stream 中,最多读取 count 个元素,并把它们依次存放到 buffer 指向的数组中。

size_t fread(void* buffer, size_t size, size_t count, FILE* stream);
参数:buffer: 指向存放数据的数组size: 每个元素的大小(以字节为单位)count: 最多可以读取的元素个数stream: 输入流
返回值:成功读取元素的个数。当读到文件末尾,或者发生错误时,返回值可能小于count。我们可以通过feof和ferror函数来判断,到底是读到了文件末尾,还是发生了错误。

fwrite 将存放在 buffer 指向的数组中的 count 个元素写入到输出流 stream 中。

size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
参数:buffer: 指向存放数据的数组。size: 每个元素的大小(以字节为单位)count: 要写入元素的个数stream: 输出流
返回值:成功写入元素的个数。当发生错误时,这个值可能小于count。

fread/fwrite 不仅可以用于读写二进制文件,还可以用于序列化和反序列化过程中。

示例1(复制二进制文件)

int main(int argc, char** argv) {if (argc != 3) {printf("Error: invalid arguments\n");exit(EXIT_FAILURE);}// 打开文件流FILE* source_fp = fopen(argv[1], "r");if (source_fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}FILE* dest_fp = fopen(argv[2], "w");if (dest_fp == NULL) {printf("Can not open %s\n", argv[2]);fclose(source_fp);exit(EXIT_FAILURE);}// 复制文件(fread & fwrite)char str[1024];int n = 0;while ((n = fread(str, 1, sizeof(str), source_fp)) != 0) {fwrite(str, 1, n, dest_fp);}// 关闭文件流fclose(source_fp);fclose(dest_fp);return 0;
}

示例2(序列化与反序列化)

#include <stdio.h>
#include <cstdlib>typedef struct {char name[25];int age;char gender;
} Student_t;int main(int argc, char** argv) {if (argc != 2) {printf("Error: invalid arguments\n");exit(EXIT_FAILURE);}Student_t stu1 = {"jerry", 20, 'm'};FILE* fp = fopen(argv[1], "w");if (fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}/* ********** 使用fscanf & fprintf ********** */// 序列化fwrite(&stu1, sizeof(Student_t), 1, fp);fclose(fp);fp = fopen(argv[1], "r");if (fp == NULL) {printf("Can not open %s\n", argv[1]);exit(EXIT_FAILURE);}Student_t stu2 = {"jack", 19, 'm'};// 反序列化fread(&stu2, sizeof(Student_t), 1, fp);fclose(fp);printf("Stu2.name: %s Stu2.age: %d Stu2.gender: %c\n", stu2.name, stu2.age, stu2.gender);return 0;
}

4. 文件定位

每个流都有相关联的文件位置。在执行读写操作时,文件位置会自动推进,并按照顺序访问文件。顺序访问是很好的,但是有时候,我们可能需要跳跃地访问文件。为此, 提供了几个函数来支持这种能力:

int fseek(FILE* stream, long int offset, int whence);
long int ftell(FILE* stream);
void rewind(FILE* stream);

fseek

fseek 可以改变与 stream 相关联的文件位置。其中 whence 表示参照点,参照点有 3 个选择:

  • SEEK_SET:文件的起始位置
  • SEEK_CUR:文件的当前位置
  • SEEK_END:文件的末尾位置

offset 表示偏移量 (可能为负),它是以字节进行计数的。比如:移动到文件的起始位置,可以这样写:

fseek(fp, 0L, SEEK_SET);

移动到文件的末尾,可以这样写:

fseek(fp, 0L, SEEK_END);

往回移动10个字节,可以这样写:

fseek(fp, -10L, SEEK_CUR);

通常情况下, fseek 会返回 0;如果发生错误 (比如,请求的位置不存在),那么 fseek 会返回非 0 值。

ftell

ftell 以长整数形式返回当前文件位置;如果发生错误,ftell返回-1L。ftell 一般的用法是:记录当前位置,方便以后返回。

long int filePos = ftell(fp);
...
fseek(fp, filePos, SEEK_SET);

rewind

rewind 会将文件位置设置为起始位置,类似于调用:

fseek(fp, 0L, SEEK_SET);

练习

用户输入文件名,将整个文件的内容读入到字符数组中,并在后面添加空字符’\0’。

char* readFile(const char* path);
char* readFile(const char* path) {// 打开文件FILE* fp = fopen(path, "rb");if (fp == NULL) {printf("Can not open %s\n", path);exit(EXIT_FAILURE);}// 文件结尾位置fseek(fp, 0L, SEEK_END);long int file_len = ftell(fp);// 将文件内容复制到buffer中rewind(fp); // 回到文件开头,因为要从开头开始复制char* buffer = (char*)malloc(file_len + 1);fread(buffer, 1, file_len, fp);// 在数组末尾添加空字符buffer[file_len] = '\0';fclose(fp);return buffer;
}int main(int argc, char* argv[]) {if (argc != 2) {printf("Error: invalid arguments\n");exit(EXIT_FAILURE);}char* buffer = readFile(argv[1]);printf("buffer content: \n%s\n", buffer);free(buffer);return 0;
}

5. 错误处理

错误的检测和处理并不是 C 语言的强项,C 语言没有其它高级语言 (C++, Java, C#等) 所具有的异常处理机制。

C 语言往往是通过函数的返回值,或者是测试 errno 变量来检测错误的;并且需要程序员自己编写代码来处理错误。

5.1 errno

errno 是一个 int 类型的全局变量 (C11 修改为线程本地变量,即每个线程都有一个独有的 errno 变量),它定义在 <errno.h> 头文件中。

标准库中有些函数 (比如与文件相关的一些函数),如果在调用过程中发生了错误,它会设置 errno 的值,以表明发生 了何种类型的错误。

程序启动时,会将 errno 的值设为 0,表示没有错误发生。其它非 0 值都表示发生了某种类型的错误。

我们可以通过 perrorstrerror 来显示错误信息。其中, perror 定义在 <stdio.h> 头文件 中, strerror 定义在 <string.h> 头文件中。

示例

int main(void) {printf("%d\n", errno); // errno == 0FILE* fp = fopen("not_exist.txt", "r");printf("%d\n", errno); // errno == 2printf("%s\n", strerror(errno)); // No such file or directoryperror("not_exist.txt"); // not_exist.txt: No such file or directoryreturn 0;
}

相关文章:

C语言中的文件

文章目录 文件1. 流1.1 文件缓冲1.2 标准流1.3 文本文件和二进制文件 2. 打开/关闭文件2.1 fopen2.2 fclose 3. 读写文件3.1 fgetc & fputc3.2 fgets & futs3.3 fscanf & fprintf3.4 fread & fwrite 4. 文件定位5. 错误处理5.1 errno 文件 1. 流 在 C 语言中…...

利用分治策略优化快速排序

1. 基本思想 分治快速排序&#xff08;Quick Sort&#xff09;是一种基于分治法的排序算法&#xff0c;采用递归的方式将一个数组分割成小的子数组&#xff0c;并通过交换元素来使得每个子数组元素按照特定顺序排列&#xff0c;最终将整个数组排序。 快速排序的基本步骤&#…...

前端工程化的具体实现细节

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

数据分析--数据清洗

一、数据清洗的重要性&#xff1a;数据质量决定分析成败 1.1 真实案例警示 电商平台事故&#xff1a;2019年某电商大促期间&#xff0c;因价格数据未清洗导致错误标价&#xff0c;产生3000万元损失医疗数据分析&#xff1a;未清洗的异常血压值&#xff08;如300mmHg&#xff…...

✨1.HTML、CSS 和 JavaScript 是什么?

✨✨ HTML、CSS 和 JavaScript 是构建网页的三大核心技术&#xff0c;它们相互协作&#xff0c;让网页呈现出丰富的内容、精美的样式和交互功能。以下为你详细介绍&#xff1a; &#x1f98b;1. HTML&#xff08;超文本标记语言&#xff09; 定义&#xff1a;HTML 是一种用于描…...

QT--常用对话框

文章目录 前言一、颜色对话框颜色对话框代码解析 二、文本对话框文本对话框代码解析 三、输入对话框1.整型输入对话框2.浮点数输入对话框3.条目对话框 四、提示对话框1.提问对话框2.消息对话框3.警告对话框4.关键对话框 五、进度对话框六、向导对话框总结 前言 今天介绍几种标…...

基于 Ollama 工具的 LLM 大语言模型如何部署,以 DeepSeek 14B 本地部署为例

简简单单 Online zuozuo :本心、输入输出、结果 文章目录 基于 Ollama 工具的 LLM 大语言模型如何部署,以 DeepSeek 14B 本地部署为例前言下载 Ollama实际部署所需的硬件要求设置 LLM 使用 GPU ,发挥 100% GPU 性能Ollama 大模型管理命令大模型的实际运行资源消耗基于 Ollam…...

图的最小生成树算法: Prim算法和Kruskal算法(C++)

上一节我们学习了最短路径算法, 这一节来学习最小生成树. 最小生成树(Minimum Spanning Tree, MST)算法是图论中的一种重要算法, 主要用于在加权无向图中找到一棵生成树, 使得这棵树包含图中的所有顶点, 并且所有边的权重之和最小. 这样的树被称为最小生成树. 最小生成树广泛应…...

WPS的AI助手进化跟踪(灵犀+插件)

Ver V0.0 250216: 如何给WPS安装插件用以支持其他大模型LLM V0.1 250217: WPS的灵犀AI现在是DeepSeek R1(可能是全参数671B) 前言 WPS也有内置的AI&#xff0c;叫灵犀&#xff0c;之前应是自已的LLM模型&#xff0c;只能说是属于“能用&#xff0c;有好过无”&#xff0c;所…...

我用AI做数据分析之数据清洗

我用AI做数据分析之数据清洗 AI与数据分析的融合效果怎样&#xff1f; 这里描述自己在使用AI进行数据分析&#xff08;数据清洗&#xff09;过程中的几个小故事&#xff1a; 1. 变量名的翻译 有一个项目是某医生自己收集的数据&#xff0c;变量名使用的是中文&#xff0c;分…...

一周学会Flask3 Python Web开发-request请求对象与url传参

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili request请求对象封装了从客户端发来的请求报文信息&#xff0c;我们可以从中获取所有数据。 request对象包含的常用属性&…...

【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析④】

ISO 14229-1:2023 UDS诊断【ECU复位0x11服务】_TestCase04 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025年02月17日 关键词&#xff1a;UDS诊断协议、ECU复位服务、0x11服务、ISO 14229-1:2023 TC11-004测试用例 用例ID测试场景验证要点参考条款预期结果TC…...

网络技术变迁:从IPv4走向IPv6

目录 前言 旧时代产物&#xff1a;IPv4 什么是IPv4&#xff1f; IPv4的工作方式 IPv4的缺点 为什么要从IPv4过渡到IPv6&#xff1f; 走向IPv6&#xff1a;新一代互联网协议 IPv6的技术特性 我们需要过渡技术 双栈&#xff08;Dual Stack&#xff09; 隧道技术&#…...

DeepSeek教unity------事件管理

1. 定义事件类型 定义一个枚举来表示不同类型的事件。组织和识别不同的事件。 2. 创建事件参数类 为了让事件携带数据&#xff0c;创建一个通用的事件参数类或者为每个事件类型创建特定的参数类。 3. 实现事件管理器 创建一个EventManager类&#xff0c;用于管理事件的注册…...

确保设备始终处于最佳运行状态,延长设备的使用寿命,保障系统的稳定运行的智慧地产开源了

智慧地产视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。通过计算机视觉和…...

RedisTemplate存储含有特殊字符解决

ERROR信息: 案发时间: 2025-02-18 01:01 案发现场: UserServiceImpl.java 嫌疑人: stringRedisTemplate.opsForValue().set(SystemConstants.LOGIN_CODE_PREFIX phone, code, Duration.ofMinutes(3L)); // 3分钟过期作案动机: stringRedisTemplate继承了Redistemplate 使用的…...

28、深度学习-自学之路-NLP自然语言处理-做一个完形填空,让机器学习更多的内容程序展示

import sys,random,math from collections import Counter import numpy as npnp.random.seed(1) random.seed(1) f open(reviews.txt) raw_reviews f.readlines() f.close()tokens list(map(lambda x:(x.split(" ")),raw_reviews))#wordcnt Counter() 这行代码的…...

【NLP 22、语言模型 language model】

有时候我也想听听&#xff0c;我在你心里&#xff0c;是什么样子 —— 25.1.12 一、什么是语言模型 语言是灵活的&#xff0c;也是有规律的 了解一门语言的人可以判断一句话是否“合理” 通俗来讲&#xff0c;语言模型用来评价一句话(句子可以看作是字的组合)是否“合理”或…...

刚性平衡机建模

这两个公式是动平衡机中用于描述旋转部件振动行为的动力学方程。它们分别描述了旋转部件在平移振动和扭转振动中的运动规律&#xff0c;用于分析不平衡量对系统的影响。以下是详细解释&#xff1a; 1. 第一个公式&#xff1a;平移振动的动力学方程 M d 2 y d t 2 2 K y 0 m 1…...

【算法】双指针(上)

目录 双指针 左右指针(对撞指针) 快慢指针 移动零 双指针解题 复写零 暴力解题 双指针解题(快慢指针) 快乐数 双指针解题(快慢指针) 盛最多水的容器 暴力解题(会超时) 双指针解题(左右指针) 有效三角形的个数 暴力解题 双指针解题(左右指针) 双指针 常见的双指…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...