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

重定向与缓冲区

4种重定向

我们有如下的代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define FILE_NAME "log.txt"int main()
{close(1); // 关闭标准输出int fd = open(FILE_NAME, O_CREAT | O_WRONLY | O_TRUNC, 0666);if (fd < 0){perror("open");return 1;}printf("fd:%d\n", fd);printf("stdout->fd: %d\n", stdout->_fileno);fflush(stdout);close(fd);return 0;
}

运行上面的代码之后,我们发现结果如下:
在这里插入图片描述

在这里插入图片描述

在上面的代码执行之前,文件描述符是这样的:
在这里插入图片描述

上面的代码执行时:

在这里插入图片描述

然后创建了一个 log.txt 出来,根据文件 fd的分配规则[[文件 fd#📌 fd 的分配规则]]:寻找最小的,没有被使用的数组下标分配给指定的打开文件,这里由于 1 首先被关闭了,所以 1 就是那个最小的没有被使用的数组下标了,它被分配给了 log.txt

在这里插入图片描述

好了,这里在说明一下:printf函数是向屏幕上打印的,Linux 下一切皆是文件,也就是说,printf 是向显示器文件里写入内容的。printf 是根据 stdout 来向显示器文件里写入内容的,而stdout这个里面有一个fileno,这个 fileno 的值是等于 1 的,这里也就可解释为什么 printflog.txt 里打印内容了,因为此时 log.txt的文件描述符是:1

综上所诉,重定向的本质就是修改特定文件的数组下标的内容。

fflush(stdout)是什么?

上面的代码,如果我们不加 fflush会有什么结果?我们可以试一试。

如果不加fflush 我们会发现,屏幕上不会打印任何内容,log.txt里也没有内容写入。

这个和我们的一个概念有关:用户级缓冲区,语言中提供的缓冲区

在这里插入图片描述

在这里插入图片描述

输入重定向

我们事先将log.txt中的内容修改成123 456,然后再运行下面的程序:

  #include<stdio.h>    #include<sys/types.h>    #include<sys/stat.h>    #include<fcntl.h>    #include<string.h>    #include<unistd.h>    #define LOG "log.txt"    int main()    { close(0); int fd = open(LOG, O_RDONLY);int a, b;scanf("%d %d", &a, &b);printf("a = %d, b = %d\n", a, b);return 0;}

原理:
因为我们一开始执行了close(0)关闭文件描述符1对应的文件,其实也就是我们的stdin,那么我们再打开log.txt文件,根据文件描述符的规则:分配的是当前最小的没有被占用的文件描述符!那么我们的log.txt就顺理成章的拿到了fd = 0;这时候printf函数内部肯定是封装了操作系统接口read的,read只会根据文件描述符来区分文件,所以它默认的就是向文件描述符为0的文件中读取,所以就读取到了log.txt中的123 和 456!

输出重定向

 #include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<string.h>#include<unistd.h>#define LOG "log.txt"int main(){int fd1 = open(LOG, O_CREAT | O_WRONLY | O_TRUNC, 0666);printf("hello \n");    printf("hello \n");    printf("hello \n");    printf("hello \n");    printf("hello \n");    return 0;    }  

运行结果:
我们发现printf函数运行的结果没有出现在屏幕上,而是出现在log.txt文件中。
原理:
因为我们一开始执行了close(1)关闭文件描述符1对应的文件,其实也就是我们的stdout,那么我们再打开log.txt文件,根据文件描述符的规则:分配的是当前最小的没有被占用的文件描述符。那么我们的log.txt就顺理成章的拿到了fd = 1;这时候printf函数内部肯定是封装了操作系统接口write的,write只会根据文件描述符来区分文件,所以它默认的就是向文件描述符为1的文件中写入,所以就写入到了log.txt中

追加重定向

我们只需要修改输出重定向中的代码:在open函数的参数中添加上追加的参数即可

  #include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<string.h>#include<unistd.h>#define LOG "log.txt"int main(){int fd1 = open(LOG, O_CREAT | O_WRONLY | O_APPEND, 0666);  printf("hello \n");    printf("hello \n");    printf("hello \n");    printf("hello \n");    printf("hello \n");                            return 0;    }  

运行上面的代码,我们可以知道,内容是追加输出到文件中的。这就叫做我们的追加重定向。

重定向基本原理

根据上面的例子,我们可以知道,上层的fd 不变,底层fd指向的内容在改变,从而导致了我们输入输出的地方的改变,这就是重定向的基本原理

但是,问题来了,你看上面的代码,我们为了实现重定向,还要先close()还要指定文件的打开方式,这样也太麻烦了,有没有简单一点的方法,害,还真有!!


我们的想法是,直接把 3 号数组下标对应的内容直接拷贝到 1 号里面,

然后我们把之前的 3 号关掉,这样就重定向了呀,本来 1 是指向标准输出的,现在指向了 log.txt了

在这里插入图片描述

上面的操作其实就是文件描述符表级别的数组内容的拷贝,而且,我们也有这样的接口可以实现上面的功能:dup2

int dup2(int oldfd, int newfd);
dup2(要拷贝的,目的地) 

这个时候出现了 2 个问题
一个上面图所示:


这个时候我们有 2 个文件描述符指向log.txt,即使一个正常使用,一个关了,这个时候也会出问题,所以我们如何在有多个指针指向log.txt的时候保证它能够正常工作呢?

所以这个时候我们要引出引用计数的概念:

atomic_long_t f_count;

f_count就是用来计数的,有几个指针指向它,f_count就是 几

以下代码我们什么也没有干,只是将文件打开后,关闭了而已。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define FILE_NAME "log.txt"int main()
{// 打开了int fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0){perror("open");return 1;}// 打印printf("hello printf\n");fprintf(stdout, "hello fprintf\n");// 关闭close(fd);return 0;
}

💥 怕你忘记,这里写一下 open 函数里面的参数的意思:
打开文件的标志:

  • O_WRONLY:以只写模式打开文件。如果文件已存在,可以写入数据;如果文件不存在,打开操作将失败。
  • O_CREAT:如果文件不存在,则创建它。通常与 O_WRONLYO_RDWR 一起使用。
  • O_TRUNC:如果文件已存在,并且以写模式打开,则将文件长度截断为 0。这意味着文件中的原有内容将被删除。

文件权限:

  • 0666:这是一个八进制数,表示文件的权限。八进制数 0666 对应的权限是:
    • 6(即 110 二进制)表示读写权限。
    • 第一个 6 表示文件所有者(owner)的权限。
    • 第二个 6 表示文件所属组(group)的权限。
    • 第三个 6 表示其他用户(others)的权限。
      因此,0666 表示文件所有者、所属组和其他用户都有读写权限。

运行上面的程序,我们可以看到:

好了,基于上面的程序,我们要完成输出重定向:
我们只需要在上面的程序中加入dup2就行了,用 dup2 就可以解决多个指针同时指向 log.txt 还能让它正常工作的问题

dup2(fd, 1); 

完整代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define FILE_NAME "log.txt"int main()
{int fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0){perror("open");return 1;}dup2(fd, 1); // <-----------------------------------------------------printf("hello printf\n");fprintf(stdout, "hello fprintf\n");close(fd);return 0;
}

运行之后,就没有向屏幕中输出了,而是向 log.txt这个文件中输入,因为我们改了输出的文件

文件描述符2 是干什么的?

我们知道,文件描述符 2 对应的是标准错误,标准错误是干什么的,为什么要存在标准错误呢?而且标准错误也是指向的显示器

假设我们有如下程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define FILE_NAME "log.txt"int main()
{fprintf(stdout, "hello stdout\n"); //标准输出fprintf(stderr, "hello stderr\n"); // 标准错误return 0;
}

运行结果如下:

这个时候,我们做一个实验,我们重定向一下,把内容输出到 log.txt中:

我们发现结果很神奇:1. stderr 还是往显示器上打印的 2. stdout 的确是往 log.txt 中打印的

为啥?❓
因为,我们重定向的时候仅仅只是将标准输出重定向了,并没有将标准错误重定向。

那我们非要将标准错误也重定向到log.txt中咋办?

我们可以这样写:

./myfile > log.txt 2>&1

image.png

还有一件事,其实:./myfile > log.txt 是一种简写,完整的写法是:./myfile 1 > log.txt

这样一来,我岂不是可以这样操作:

./myflie 1>log001.txt 2>log002.txt

就是把这个内容,一个放进 1 号里,一个放进 2 号里

回到正题,那为什么要有标准错误呢?

在我们写程序的时候,遇到报错是在正常不过的了,但是如果这个程序也有普通的打印任务,比如:要在屏幕上打印一个hello word,这个时候,我们可以将hello word 作为普通输出打印进 log001.txt中,将这个程序的错误输出放入log002.txt 中,这就是标准错误存在的意义。

📌缓冲区

🎹预备知识

什么是缓冲区?

其实就是一部分的内存

这一部分的内存是由谁提供的?

比如,我们自己写代码的时候定义的char bufer 或是 char 数组[ ] ,其实这就是我们自己定义的用户缓冲区。如果这个缓冲区是由c语言提供的,这就叫做c标准库提供的缓冲区 ,如果是操作系统提供的,那么就叫做操作系统缓冲区。我们可以简单的理解为都是malloc 出来的。

为什么要有缓冲区?

我们有这样的一段代码样例:
printf("hello linux");
sleep(3);
在sleep期间,屏幕上是不会打印 hello linux 的,但是c语言是从上往下执行的,所以当在执行sleep(3) 的时候,printf 语句是肯定已经执行过了,这个时候 hello linux 就存在于缓冲区里。

缓冲区的优点:

缓冲区的作用是提高使用者的效率
因为有缓冲区的存在,我们可以积累一部分在统一发送
提高发送的效率

缓冲区因为能够暂存数据,必定要有一定的刷新方式:

  1. 无缓冲(立即刷新)
  2. 行缓冲(行刷新)
  3. 全缓冲(缓冲区满了再刷新)

上面的刷新方式是一般的情况,以下是特殊情况下的刷新方式:

  1. 强制刷新
  2. 进程退出的时候,一般要进行刷新缓冲区

一般对于显示器,我们采用的刷新策略是:行刷新(行缓冲)
对于磁盘上的文件,我们采取的刷新策略是:全缓冲(缓冲区满再刷新)

🎹介绍一个样例

现在,我们要准备以下几个文件:

​k``makefile``:
```makefile
myfile:myfile.cgcc -o $@ $^ 
.PHONY:clean
clean:rm -rf myfile

myfile.c:

 #include <stdio.h>
#include <unistd.h>
kude <string.h>
#include <unistd.h>int {fpkmain()
{fprintf(stdout,"C:hello fprintf\n");pputs("C: hello fputs\n",stdout); ckrintf("C: hello printf\n");fputs("C: hello fputs\n",stdout); const char *str = "system call: hello wirte\n";write(1,str,strlen(str));return 0;
}

运行的操作:
image.png

上面,我们写了 4 个向显示器打印的语句。

接下来,我们输出重定向到log.txt 中;
ik'kmage.png

上面的操作做完之后,现在 我们来开始试验,现在,我们在myfile.c 中加上一行代码;

#include <stdio.h>
#include <string.h>
#i
inknclude <unistd.h>int main()
{fprintf(stdout,"C:hello fprintf\n");printf("C: hello printf\n");fputs("C: hello fputs\n",stdout); const char *str = "system call: hello wirte\n";write(1,str,strlen(str));fork(); // <---------------------------------------- 注意fork的位置return 0;
}

加上这一句fork(); 之后,我们在把之前的执行流程重新走一遍看看有什么不同。
!k
image.png

当我们直接向显示器打印的时候,缓冲区采取的刷新方式是:行刷新,而且上面的代码中,我们每一个打印的字符的后面都是有\n 的,这说明 fork() 执行之前,上面的那些打印的语句都被刷新过了也包括 system call ,所以是一样的

\n 是换行,显示器是行刷新,所以有\n 就会进行行刷新

image.png

观察上面打印的结果,我么发现,只有C语言的接口被打印了2次,而系统调用接口只被打印了1次

这样的结果一定与我们在代码中添加的fork() 有关

问题是,我们的fork() 是放在代码的最后的呀,如果你这个fork()放在的是代码的最前面,这都好解释,因为,fork之后创建子进程,父子进程代码共享,会打印2次,你这里的fork 是放在代码最后的呀,fork() 之后啥都没有了;它咋还打印了呢?

当我们使用./myfile > log.txt输出重定向 本质是向磁盘上的文件 进行写入(不再是显示器了),而磁盘上文件默认的刷新策略是:全缓冲刷新 (缓冲区满了再刷新),全缓冲就意味着缓冲区变大,上面我们打印的语句不足以把缓冲区填满,这就意味着,fork() 执行的时候,数据依旧在缓冲区中。

我们发现,系统调用在上面进行的操作过程中都只打印了一次,这说明我们目前系统调用和缓冲区是没有关系的,是和 C 语言有关的(通过我们上面的操作推出),这就说明,我们日常用的最多的缓冲区是c/c++ 提供的语言级别的缓冲区

C/C++ 提供的缓冲区,里面一定保存的是用户的数据,那这些数据属不属于当前进程在运行时自己的数据呢?

属于

如果我们把数据交给了操作系统,那么这个数据就属于操作系统了,而不属于这个进程了

当进程退出的时候一般要进行刷新缓冲区,即使你的缓冲区没有满足刷新的条件,也是会强制刷新的,因为进程退出了。

image.png

所以当代码执行到fork()的时候 ,之后已经没有代码了,父进程已经执行结束了,要退了,所以,根据进程退出会强制刷新缓冲区,这个时候的缓冲区会被刷新。这个时候缓冲区里面存着的是前4条我们对应的语句:
image.png

问题:这里的刷新缓冲区是指的是“清空” 或是 “写入” 的操作吗?

没错,指的就是清空或者是写入的操作

当我们这里fork() 的时候,父进程要先退出了,所以要刷新缓冲区了,所以就要对缓冲区进行一种类似清空或写入的操作了,根据我们之前的所学的知识,父子进程数据是共享的,当其中一方发生数据改变时,就会发生写时拷贝,所以这个时候数据就会变成 2 份。所以log.txt 中会打印 2 份结果
我们观察一下向log.txt输出的结果
image.png

write 接口的结果只打印了一次,说明,write 系统调用接口没有使用C语言的缓冲区,它是直接把数据写入到了操作系统中了,这个时候依照我们上面所说的,这个时候的数据是属于操作系统了,不属于进程了,所以你会发现一个小细节:wirte 系统调用的打印的语句是出现在log.txt的第一行的,尽管它的代码语句是写在最后的。

image.png

观察我们之前学的一些输入输出的函数,我们可以看到都有FILE* 这样一个指针,其中FILE是一个结构体,在任何情况下,当我们输入输出的时候,都要有一个FILE 因为FILE 这个结构体里面为我们提供了一段缓冲区。

本章图集:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

相关文章:

重定向与缓冲区

4种重定向 我们有如下的代码&#xff1a; #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h>#define FILE_NAME "log.txt"int main() {close(1)…...

练习题 - Django 4.x File 文件上传使用示例和配置方法

在现代的 web 应用开发中,文件上传是一个常见的功能,无论是用户上传头像、上传文档,还是其他类型的文件,处理文件上传都是开发者必须掌握的技能之一。Django 作为一个流行的 Python web 框架,提供了便捷的文件上传功能和配置方法。学习如何在 Django 中实现文件上传,不仅…...

[VSCode] vscode下载安装及安装中文插件详解(附下载链接)

VSCode 是一款由微软开发且跨平台的免费源代码编辑器&#xff1b;该软件支持语法高亮、代码自动补全、代码重构、查看定义功能&#xff0c;并且内置了命令行工具和Git版本控制系统。 下载链接&#xff1a;https://pan.quark.cn/s/3a90aef4b645 提取码&#xff1a;NFy5 通过上面…...

JVM常见知识点

在《深入理解Java虚拟机》一书中&#xff0c;介绍了JVM的相关特性。 1、JVM的内存区域划分 在真实的操作系统中&#xff0c;对于地址空间进行了分区域的设计&#xff0c;由于JVM是仿照真实的机器进行设计的&#xff0c;那么也进行了分区域的设计。核心区域有四个&#xff0c;…...

深入探索 Vue 3 Markdown 编辑器:高级功能与实现

目录 1. 为什么选择 Markdown 编辑器&#xff1f;2. 选择合适的 Markdown 编辑器3. 安装与基本配置安装 配置 Markdown 编辑器代码说明 4. 高级功能实现4.1 实时预览与双向绑定4.2 插入图片和图像上传安装图像上传插件配置图像上传插件 4.3 数学公式支持安装 KaTeX配置 KaTeX 插…...

vscode无法格式化go代码的问题

CTRLshiftp 点击Go:Install/Update Tools 点击全选&#xff0c;OK&#xff01;...

《Java程序设计》课程考核试卷

一、单项选择题&#xff08;本大题共10个小题&#xff0c;每小题2分&#xff0c;共20分&#xff09; 1.下列用来编译Java源文件为字节码文件的工具是&#xff08; &#xff09;。 A.java B.javadoc C.jar D.javac 2…...

one-hot (独热编码)

一、目的 假设我们现在需要对猫、 狗、 人这三个类别进行分类。 若以 0 代表猫&#xff0c; 以 1 代表狗&#xff0c; 以 2 代表人&#xff0c;会发现那么猫和狗之间距离为 1&#xff0c; 狗和人之间距离为 1&#xff0c; 而猫和人之间距离为 2。 假设真实标签是猫&#xff0…...

寒假1.23

题解 web&#xff1a;[极客大挑战 2019]Secret File&#xff08;文件包含漏洞&#xff09; 打开链接是一个普通的文字界面 查看一下源代码 发现一个链接&#xff0c;点进去看看 再点一次看看&#xff0c;没什么用 仔细看&#xff0c;有一个问题&#xff0c;当点击./action.ph…...

unity 粒子系统设置触发

1、勾选Triggers选项 2、将作为触发器的物体拉入队列当中&#xff0c;物体上必须挂载collider 3、将想要触发的方式&#xff08;Inide、Outside、Enter和Exit&#xff09;选择为”Callback“&#xff0c;其他默认为”Ignore“ 4、Collider Query Mode 设置为All&#xff1a…...

【C++】类和对象(五)

1、初始化列表 作用&#xff1a;C提供了初始化列表语法&#xff0c;用来初始化属性。 语法&#xff1a; 构造函数&#xff08;&#xff09;&#xff1a;属性1&#xff08;值1&#xff09;&#xff0c;属性2&#xff08;值2&#xff09;...{}示例&#xff1a; #include<i…...

超分辨率体积重建实现术前前列腺MRI和大病理切片组织病理学图像的3D配准

摘要: 磁共振成像(MRI)在前列腺癌诊断和治疗中的应用正在迅速增加。然而,在MRI上识别癌症的存在和范围仍然具有挑战性,导致即使是专家放射科医生在检测结果上也存在高度变异性。提高MRI上的癌症检测能力对于减少这种变异性并最大化MRI的临床效用至关重要。迄今为止,这种改…...

第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)

1.并发编程的三个重要特性 并发编程有三个至关重要的特性&#xff0c;分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中&#xff0c;要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断&#xff0c;要么所有的操作都不执行…...

[STM32 标准库]定时器输出PWM配置流程 PWM模式解析

前言&#xff1a; 本文内容基本来自江协&#xff0c;整理起来方便日后开发使用。MCU&#xff1a;STM32F103C8T6。 一、配置流程 1、开启GPIO&#xff0c;TIM的时钟 /*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟RCC_APB2PeriphClockC…...

web3py+flask+ganache的智能合约教育平台

最近在学习web3的接口文档&#xff0c;使用web3pyflaskganache写了一个简易的智能合约教育平台&#xff0c;语言用的是python&#xff0c;ganche直接使用的本地区块链网络&#xff0c;用web3py进行交互。 代码逻辑不难&#xff0c;可以私信或者到我的闲鱼号夏沫mds获取我的代码…...

< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机

原因&#xff1a; &#xff1c; OS 有关 &#xff1e; 阿里云&#xff1a;轻量应用服务器 的使用 &#xff1a;从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作&#xff1a; 查看进程&#x…...

【技术】TensorRT 10.7 安装指南(Ubuntu22.04)

原文链接&#xff1a;https://mengwoods.github.io/post/tech/008-tensorrt-installation/ 本文安装的版本如下&#xff1a; Ubuntu 22.04 Nvidia Driver 538.78 CUDA 12.2 cuDNN 8.9.7 TensorRT 10.7 安装前的准备&#xff08;可选&#xff09; 在安装新版本之前&#xf…...

Linux 权限管理

hello&#xff01;这里是敲代码的小董&#xff0c;很荣幸您阅读此文&#xff0c;本文只是自己在学习Linux过程中的笔记&#xff0c;如有不足&#xff0c;期待您的评论指点和关注&#xff0c;欢迎欢迎~~ ✨✨个人主页&#xff1a;敲代码的小董 &#x1f497;&#x1f497;系列专…...

8.2 从看图识字到智能解读:GPT-4 with Vision 开启多模态 AI 新纪元

从看图识字到智能解读:GPT-4 with Vision 开启多模态 AI 新纪元 引言:AI 的多模态跃迁 随着人工智能技术的快速发展,我们正迈入一个新的智能交互时代。传统的 AI 模型主要聚焦于文本处理,而多模态 AI 模型如 GPT-4 with Vision(GPT-4V) 则能够同时处理图像和文本。GPT-4…...

差分轮算法-两个轮子计算速度的方法-阿克曼四轮小车计算方法

四轮驱小车的话&#xff1a; 转向角度计算方法&#xff1a;float turning_angle z_angular / x_linear; // 转向角度&#xff0c;单位为弧度 速度的话直接用线速度 两轮驱动小车&#xff1a; 计算公式&#xff1a; leftSpeed x_linear - z_angular * ORIGINBOT_WHEEL_TRACK /…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

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

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

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...