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

【Linux】从C语言文件操作 到Linux文件IO | 文件系统调用

文章目录

  • 前言
  • 一、C语言文件I/O复习
    • 文件操作:打开和关闭
    • 文件操作:顺序读写
    • 文件操作:随机读写
    • stdin、stdout、stderr
  • 二、承上启下
  • 三、Linux系统的文件I/O
    • 系统调用接口介绍
      • open()
      • close()
      • read()
      • write()
      • lseek()

Linux文件相关重点

  • 复习C文件IO相关操作
  • 认识文件相关系统调用接口
  • 认识文件描述符,理解重定向
  • 对比fd和FILE,理解系统调用和库函数的关系
  • 理解文件系统中inode的概念
  • 认识软硬链接,对比区别
  • 认识动态静态库,学会结合gcc选项,制作动静态库

前言

  1. 文件 = 内容 + 属性

  2. 所以对文件的所有操作被分为:
    a. 对内容操作
    b. 对属性操作

  3. 我们要访问一个文件的时候,都是要先把这个文件打开的:
    打开前:是普通的磁盘文件
    打开后:文件被加载到内存中
    打开的步骤是由操作系统来做的!

  4. 一个进程可以打开很多文件,所以操作系统运行时被打开的文件是很多的,操作系统当然要对这些被打开的文件做管理,管理的方式是:先描述,再组织。因此,一个文件要被打开,一定要先在内核中,形成被打开的文件对象。请添加图片描述

  5. 本文研究的文件操作的本质是:进程内存中被打开(被加载)的文件 的关系


一、C语言文件I/O复习

文件操作:打开和关闭

函数签名描述
FILE fopen(const char path, const char* mode)打开文件并返回指向文件的指针
int fclose(FILE *stream)关闭文件
模式描述
“r”读取:打开文件进行输入操作。文件必须存在。
“w”写入:创建一个空文件进行输出操作。如果同名文件已存在,其内容将被丢弃,文件被视为新的空文件。
“a”追加:打开文件进行输出操作,将数据追加到文件末尾。输出操作总是在文件末尾写入数据,扩展文件大小。重新定位操作(fseek、fsetpos、rewind)将被忽略。如果文件不存在,则创建文件。
“r+”读取/更新:打开文件进行更新操作(既可读又可写)。文件必须存在。
“w+”写入/更新:创建一个空文件并打开它进行更新操作(既可读又可写)。如果同名文件已存在,其内容将被丢弃,文件被视为新的空文件。
“a+”追加/更新:打开文件进行更新操作(既可读又可写),所有输出操作都在文件末尾写入数据。重新定位操作(fseek、fsetpos、rewind)影响下一次的输入操作,但输出操作将位置移回文件末尾。如果文件不存在,则创建文件。

[!Attention] 不带+号的模式在文件打开时会对原文件进行擦除(覆盖)操作,具体来说:

  • "w"模式: 如果使用 “w” 模式打开一个文件,它会创建一个空文件,如果同名文件已存在,则会清空该文件的内容。换句话说,打开文件时,如果文件已经存在,原文件的内容将被抹掉。
  • "a"模式: 如果使用 “a” 模式打开一个文件,文件指针会移动到文件末尾,写入的数据将追加到文件的末尾。如果文件不存在,则会创建一个新文件。原文件的内容不会被清空,而是保留在文件中。

这是在不带+号的写入模式下的行为。要同时进行读写而不清空文件内容,可以考虑使用带+号的模式,如 “r+” 或 “a+”。

实验一下:

#include <stdio.h>int main() 
{FILE *filePointer;// 打开文件filePointer = fopen("test.txt", "w");if (filePointer == NULL) {printf("文件打开失败。\n");return 1;}printf("文件打开成功,执行其他文件操作...\n");// 执行其他文件操作...// 关闭文件if (fclose(filePointer) == 0) {printf("文件关闭成功。\n");} else {printf("文件关闭失败。\n");}return 0;
}

请添加图片描述

文件操作:顺序读写

函数签名描述
int fputc(int c, FILE *stream)将一个字符写入文件
int fgetc(FILE *stream)从文件中读取一个字符
char *fgets(char *s, int size, FILE *stream)从文件中读取一行内容,并存储到字符串 s 中
int fputs(const char *s, FILE *stream)将字符串 s 写入文件
size_t fread(void *ptr, size_t size, size_t count, FILE *stream)从文件中读取二进制数据
size_t fwrite(void *ptr, size_t size, size_t count, FILE *stream)向文件中写入二进制数据
#include <stdio.h>int main() {FILE *filePointer;char ch;// 写入文件filePointer = fopen("test.txt", "w");if (filePointer == NULL) {printf("文件打开失败。\n");return 1;}fputc('A', filePointer);fclose(filePointer);// 读取文件filePointer = fopen("test.txt", "r");if (filePointer == NULL) {printf("文件打开失败。\n");return 1;}ch = fgetc(filePointer);printf("读取的字符:%c\n", ch);fclose(filePointer);return 0;
}

请添加图片描述

文件操作:随机读写

函数签名描述
int fseek(FILE *stream, long offset, int whence)设置文件指针偏移量,用于定位读写位置
long ftell(FILE *stream)返回当前文件指针的位置
void rewind(FILE *stream)将文件指针重置到文件开头
int feof(FILE *stream)检测是否到达文件末尾
#include <stdio.h>int main() {FILE *filePointer;// 写入文件filePointer = fopen("test.txt", "w");if (filePointer == NULL) {printf("文件打开失败。\n");return 1;}fputs("Hello, World!", filePointer);fclose(filePointer);// 随机读取文件filePointer = fopen("test.txt", "r");if (filePointer == NULL) {printf("文件打开失败。\n");return 1;}fseek(filePointer, 7, SEEK_SET); // 移动到文件第8个字符的位置char ch = fgetc(filePointer);printf("随机读取的字符:%c\n", ch);fclose(filePointer);return 0;
}

请添加图片描述

stdin、stdout、stderr

  • C默认打开的三个输入输出流是:stdinstdoutstderr
  • 仔细观察发现,这三个流的类型都是FILE*, fopen返回值类型,文件指针
  • 这三个流通常在程序开始运行时就已经打开,并且不需要使用fopen等函数手动打开。它们分别用于标准输入、标准输出和标准错误输出。
  1. stdin(标准输入流):

    • stdin代表标准输入流,通常与键盘输入相关联。
    • 对应的文件指针是FILE* stdin
    • 你可以使用scanf等函数从stdin中读取输入数据。
  2. stdout(标准输出流):

    • stdout代表标准输出流,通常与屏幕输出相关联。
    • 对应的文件指针是FILE* stdout
    • 你可以使用printf等函数将输出写入到stdout中。
  3. stderr(标准错误输出流):

    • stderr代表标准错误输出流,通常也与屏幕输出相关联。
    • 对应的文件指针是FILE* stderr
    • stdout相比,stderr通常用于输出错误消息,以便在程序发生错误时将错误信息与正常输出区分开。

这些标准流的使用使得C程序能够在不同环境中运行,而不用关心具体的输入和输出设备。在程序中,你可以直接使用这些流,而无需显式打开或关闭它们。例如,可以通过fprintf将输出写入到文件,而不仅仅是屏幕,或者通过fscanf从文件而不是键盘读取输入。


二、承上启下

  • 上面的fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc)。
  • 而, open close read write lseek 都属于系统提供的接口,称之为系统调用接口
  • 回忆一下我们讲【Linux】从冯诺依曼体系结构到操作系统 时,画的一张图!请添加图片描述

系统调用接口和库函数的关系,就是库函数封装了系统调用接口。
所以可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发。
如何封装?
fopen函数在上层为用户申请FILE结构体变量,并返回该结构体的地址(FILE*),在底层通过系统接口open打开对应的文件,得到文件描述符fd,并把fd填充到FILE结构体当中的_fileno变量中,至此便完成了文件的打开操作。


三、Linux系统的文件I/O

系统调用接口介绍

先介绍一个小技巧

关于Linux常用的传参方式:函数传入标志位的小技巧


C语言常通过一个整形来传递选项,但是当选项较多时,每一个选项都用一个整形太浪费空间,所以有人想出了办法 – 使用一个比特位来传递一个选项,这样一个整形就可以传递32种选项,大大节省了空间,具体案例如下:

#include <stdio.h>#define Print1 1      // 0001
#define Print2 (1<<1) // 0010
#define Print3 (1<<2) // 0100
#define Print4 (1<<3) // 1000void Print(int flags)
{if(flags&Print1) printf("hello 1\n");if(flags&Print2) printf("hello 2\n");if(flags&Print3) printf("hello 3\n");if(flags&Print4) printf("hello 4\n");
}int main()
{Print(Print1);Print(Print1|Print2);Print(Print1|Print2|Print3);Print(Print3|Print4);Print(Print4);return 0;
}

请添加图片描述

如上,我们将宏与比特位对应,然后在 Print 函数中编写每一个宏对应的功能,之后我们就可以在其他函数中通过调用 Func 函数并传递对应的选项来达到我们想要的效果,并且我们可以通过按位或来实现同时传递几个选项。

open()

  • 系统调用open:用于打开或创建一个文件。open函数是一个系统调用,用于打开文件或创建新文件,返回值是一个文件描述符,后续的文件操作可以使用这个文件描述符。请添加图片描述

  • pathname: 要打开或创建的目标文件

  • flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“按位或”运算,构成flags。

  • 常用的flags的可选参数:

    文件打开方式含义如果指定文件不存在
    O_RDONLY以只读形式打开出错
    O_WRONLY以只写形式打开出错
    O_RDWR以读写形式打开出错
    O_APPEND向文本文件尾添加数据出错
    O_CREAT如果文件不存在,创建新文件建立一个新的文件
    O_TRUNC打开文件时清空文件中之前的数据出错

close()

  • 系统调用close:关闭一个文件请添加图片描述

read()

  • read:从文件中读数据 请添加图片描述

  • 返回值
    如果成功,则返回读取的字节数(0表示文件结束),并将文件位置提前该字节数。如果这个数字小于请求的字节数,则不会报错;例如,发生这种情况可能是因为现在实际可用的字节数减少了(可能是因为接近文件末尾,或者因为我们正在从管道或终端读取数据),或者因为read()被信号中断。发生错误时,返回-1,并适当地设置errno。在这种情况下,文件位置(如果有的话)是否改变是未指定的。

下面用read.c来测试read()系统调用:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>#define FILE_NAME "file1.txt"int main() {int fd = open(FILE_NAME, O_RDONLY);if(fd == -1) {perror("open");return 1;}char buf[1024];//C语言字符串以'\0'结尾,所以留一个位置来放置int ret = read(fd, buf, sizeof(buf) - 1);//read读到文件末尾返回0while(ret != 0) {buf[ret] = '\0';printf("%s", buf);ret = read(fd, buf, sizeof(buf) - 1);}close(fd);
}

现象:
请添加图片描述

write()

  • write:向文件中写数据请添加图片描述

下面用write.c来测试write()系统调用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>#define FILE_NAME1 "file1.txt"  //已存在
#define FILE_NAME2 "file2.txt"  //不存在int main() {//以只写形式打开,并清空文件中之前的数据int fd1 = open(FILE_NAME1, O_WRONLY | O_TRUNC); //创建文件并以只写形式打开,并指定文件的默认权限为0666(还受umask的影响)//同时,我们可以通过umask接口手动设置当前进程的文件掩码,而不使用从父进程继承过来的umaskumask(0000); int fd2 = open(FILE_NAME2, O_WRONLY | O_CREAT | O_TRUNC, 0666);//错误处理if(fd1 == -1 || fd2 == -1) {perror("open");return 1;}const char* buf1 = "hello file1\n";const char* buf2 = "hello file2\n";int cnt = 5;while(cnt--) {//注意:这里strlen求得的长度不用加1,因为字符串以'\0'结尾只是C语言的特性,而文件中并不这样规定write(fd1, buf1, strlen(buf1));write(fd2, buf2, strlen(buf2));}close(fd1);close(fd2);
}

现象:
请添加图片描述

[!Attention] 上面的文件操作的三个细节:

  1. 如果在向文件中写入数据时没有指定O_TRUNC选项,而是直接写入数据,新数据会从文件的当前位置开始写入,而不会影响文件中原有的数据。如果新数据的长度小于文件当前的大小,那么文件的尾部会保留原有的数据,就比如先写入五行 hello world,再写入五行 hello:请添加图片描述

  2. 创建 file2.txt 时我们通过 umask 系统调用将 umask 由默认的 0002 设置为了 0000(第一个0代表八进制),然后将 open() 系统调用的最后一个参数 mode 设置为 0666,所以 file2 的最终权限为 文件的默认权限 & ~umask0666 & ~0000 亦即 0666:请添加图片描述

  3. 在C语言中,字符串是以'\0'(空字符或Null字符)结尾的字符数组。但是,在文件中存储字符串时,并不要求在文件中以'\0'结尾。文件系统仅是按照写入的字节数来存储数据,而不关心字符串的结尾字符。因此,当你使用write函数将字符串写入文件时,不需要把字符串结尾的'\0'字符写入文件,只需写入字符串本身即可。
    如果在写入文件时将'\0'字符写入:
    请添加图片描述

  • 可能会导致一些乱码的问题:
    请添加图片描述

  • 所以说write函数的第三个参数 count 应该设置为 strlen(str),表示写入字符串的长度,而不包括字符串结尾的'\0'字符。


lseek()

lseek(“lseek"代表"long seek”)是Linux系统调用之一,用于在文件中移动文件指针的位置。它是对文件进行随机访问的关键系统调用之一。lseek可以用于设置文件偏移量,以便在文件中执行读取或写入操作。

函数原型如下:

请添加图片描述

  • fd 是文件描述符,表示要操作的文件。
  • offset 是文件偏移量,可以为正数、负数或零,用于指定相对于whence参数的偏移位置。
  • whence 指定了偏移量的基准位置,可以是以下值之一:
    • SEEK_SET:相对于文件的起始位置进行偏移。
    • SEEK_CUR:相对于当前文件指针的位置进行偏移。
    • SEEK_END:相对于文件的末尾位置进行偏移。

lseek函数的返回值是新的文件偏移量,如果调用出现错误,则返回 -1

使用示例:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main() {int fd = open("example.txt", O_RDWR);if (fd == -1) {perror("open");return 1;}// 使用 lseek 将文件指针移动到文件末尾off_t end_position = lseek(fd, 0, SEEK_END);if (end_position == -1) {perror("lseek");close(fd);return 1;}printf("当前文件大小:%lld 字节\n", (long long)end_position);// 使用 lseek 将文件指针移动到文件开头off_t start_position = lseek(fd, 0, SEEK_SET);if (start_position == -1) {perror("lseek");close(fd);return 1;}printf("文件指针已重置到文件开头\n");close(fd);return 0;
}

在上述示例中,lseek函数用于将文件指针移动到文件的末尾,获取文件的大小,然后将文件指针重新设置到文件开头。这演示了lseek在文件中移动文件指针的基本用法。

相关文章:

【Linux】从C语言文件操作 到Linux文件IO | 文件系统调用

文章目录 前言一、C语言文件I/O复习文件操作&#xff1a;打开和关闭文件操作&#xff1a;顺序读写文件操作&#xff1a;随机读写stdin、stdout、stderr 二、承上启下三、Linux系统的文件I/O系统调用接口介绍open()close()read()write()lseek() Linux文件相关重点 复习C文件IO相…...

mask transformer相关论文阅读

前面讲了mask-transformer对医学图像分割任务是非常适用的。本文就是总结一些近期看过的mask-transformer方面的论文。 因为不知道mask transformer是什么就看了一些论文。后来得出结论&#xff0c;应该就是生成mask的transformer就是mask transformer。 相关论文&#xff1a; …...

springboot+vue3支付宝接口案例-第二节-准备后端数据接口

springbootvue3支付宝接口案例-第二节-准备后端数据接口&#xff01;今天经过2个小时的折腾。准备好了我们这次测试支付宝线上支付接口的后端业务数据接口。下面为大家分享一下&#xff0c;期间发生遇到了一些弯路。 首先&#xff0c;我们本次后端接口使用的持久层框架是JPA。这…...

贪吃蛇游戏设计文档(基于C语言)

1. 引言 本设计文档旨在详细阐述一款2D贪吃蛇游戏的设计思路、功能模块划分以及具体实现要点。通过严谨的需求分析与清晰的架构设计&#xff0c;确保游戏开发过程有序进行&#xff0c;并最终打造出一款用户友好、稳定流畅的经典贪吃蛇游戏。 2. 需求分析 2.1 核心元素 - 蛇&…...

在Windows上安装与配置Apache服务并结合内网穿透工具实现公网远程访问本地内网服务

文章目录 前言1.Apache服务安装配置1.1 进入官网下载安装包1.2 Apache服务配置 2.安装cpolar内网穿透2.1 注册cpolar账号2.2 下载cpolar客户端 3. 获取远程桌面公网地址3.1 登录cpolar web ui管理界面3.2 创建公网地址 4. 固定公网地址 前言 Apache作为全球使用较高的Web服务器…...

幻兽帕鲁服务器出租,腾讯云PK阿里云怎么收费?

幻兽帕鲁服务器价格多少钱&#xff1f;4核16G服务器Palworld官方推荐配置&#xff0c;阿里云4核16G服务器32元1个月、96元3个月&#xff0c;腾讯云换手帕服务器服务器4核16G14M带宽66元一个月、277元3个月&#xff0c;8核32G22M配置115元1个月、345元3个月&#xff0c;16核64G3…...

day05休息,day06 有效的字母异位词、两个数组的交集、快乐数、两数之和

题目链接&#xff1a;有效的字母异位词、两个数组的交集、快乐数、两数之和 有效的字母异位词 时间复杂度: O(n) 空间复杂度: O(S), S为字符集大小&#xff0c;这里为26 Go func isAnagram(s string, t string) bool {// s和t的长度一定是相等的if len(s) ! len(t) {return…...

star原则

"STAR" 原则通常用于回答面试或描述工作经验等场景中&#xff0c;以清晰、有条理地传达信息。"STAR" 是 Situation&#xff08;情境&#xff09;、Task&#xff08;任务&#xff09;、Action&#xff08;行动&#xff09;、Result&#xff08;结果&#xf…...

蓝桥杯---九数组分数

1,2,3 ... 9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码。 注意,只能填写缺少的部分,不要重复抄写已有代码。不要填写任何多余的文字。 代码 public class _05九数组分数 {public static void test(int[] x){int a …...

将 Amazon Bedrock 与 Elasticsearch 和 Langchain 结合使用

Amazon Bedrock 是一项完全托管的服务&#xff0c;通过单一 API 提供来自 AI21 Labs、Anthropic、Cohere、Meta、Stability AI 和 Amazon 等领先 AI 公司的高性能基础模型 (FMs) 选择&#xff0c;以及广泛的 构建生成式 AI 应用程序所需的功能&#xff0c;简化开发&#xff0c;…...

###C语言程序设计-----C语言学习(6)#

前言&#xff1a;感谢老铁的浏览&#xff0c;希望老铁可以一键三连加个关注&#xff0c;您的支持和鼓励是我前进的动力&#xff0c;后续会分享更多学习编程的内容。 一. 主干知识的学习 1. while语句 除了for语句以外&#xff0c;while语句也用于实现循环&#xff0c;而且它…...

Hadoop3.x源码解析

文章目录 一、RPC通信原理解析1、概要2、代码demo 二、NameNode启动源码解析1、概述2、启动9870端口服务3、加载镜像文件和编辑日志4、初始化NN的RPC服务端5、NN启动资源检查6、NN对心跳超时判断7、安全模式 三、DataNode启动源码解析1、概述2、初始化DataXceiverServer3、初始…...

基于vue实现待办清单案例

一、需求 新增内容&#xff1b; 删除内容&#xff1b; 统计操作&#xff1b; 清空数据。 示例图&#xff1a; 二、代码演示 1、基础准备 index.css代码 html, body {margin: 0;padding: 0; } body {background: #fff ; } button {margin: 0;padding: 0;border: 0;backgr…...

应急响应-流量分析

在应急响应中&#xff0c;有时需要用到流量分析工具&#xff0c;。当需要看到内部流量的具体情况时&#xff0c;就需要我们对网络通信进行抓包&#xff0c;并对数据包进行过滤分析&#xff0c;最常用的工具是Wireshark。 Wireshark是一个网络封包分析软件。网络封包分析软件的…...

计算机网络·网络层

网络层 网络层提供的两种服务 争论&#xff1a; 网络层应该向运输层提供怎样的服务&#xff1f;面向连接还是无连接&#xff1f; 在计算机通信中&#xff0c;可靠交付应当由谁来负责&#xff1f;是网络还是端系统&#xff1f; 2 种观点&#xff1a; 面向连接的可靠交付。 无连…...

2024/1/28周报

文章目录 摘要Abstract文献阅读题目引言方法The ARIMA modelTime delay neural network (TDNN) modelLSTM and DLSTM model 评估准则实验数据描述实验结果 深度学习AttentionAttention思想公式步骤 Attention代码实现注意力机制seq2seq解码器Model验证 总结 摘要 本周阅读了一…...

Vue3中的ref和shallowRef、reactive和shallowReactive

一&#xff1a;ref、reactive简介 ref和reactive是Vue3中定义响应式数据的一种方式。ref通常用来定义基础类型数据。reactive通常用来定义复杂类型数据。 二、shallowRef、shallowReactive简介 shallowRef和shallowReactive是Vue3中定义浅层次响应式数据的方式 三、Api使用对比…...

go包与依赖管理

包&#xff08;package&#xff09; 包介绍 Go语言中支持模块化的开发理念&#xff0c;在Go语言中使用包&#xff08;package&#xff09;来支持代码模块化和代码复用。一个包是由一个或多个Go源码文件&#xff08;.go结尾的文件&#xff09;组成&#xff0c;是一种高级的代码…...

C++文件操作基础 读写文本、二进制文件 输入输出流 文件位置指针以及随机存取 文件缓冲区以及流状态

一、写入文本文件 文本文件一般以行的形式组织数据。 包含头文件&#xff1a;#include <fstream> 类&#xff1a;ofstream&#xff08;output file stream&#xff09; ofstream 打开文件的模式&#xff08;方式&#xff09;&#xff1a;类内open()成员函数参数2.参数1是…...

nginx部署前端(vue)项目及配置修改

目录 一、前端应用打包 二、部署前端应用 1、上传前端文件夹 2、修改nginx配置文件 3、重启nginx 三、查看效果 nginx安装参考&#xff1a;linux安装nginx-CSDN博客 一、前端应用打包 打包命令 npm run build 打包成功如下&#xff0c;会在项目路径下生成dist文件夹 二…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...