【APUE】标准I/O库

news2025/1/19 11:26:48

目录

1、简介

2、FILE对象

3、打开和关闭文件

3.1 fopen

3.2 fclose

4、输入输出流

4.1 fgetc

4.2 fputc

4.3 fgets

4.4 fputs

4.5 fread

4.6 fwrite

4.7 printf 族函数

4.8 scanf 族函数

5、文件指针操作

5.1 fseek

5.2 ftell

5.3 rewind 

6、缓冲相关

6.1 fflush

6.2 setvbuf  

7、补充

7.1 getline

7.2 临时文件 


1、简介

I/O : input and output,是一切实现的基础

IO分为标准IO(stdio)和系统调用IO(sysio)

  • 系统调用IO根据操作系统的实现方式而定,不同OS有着不同的系统调用IO
  • 标准IO对不同OS下的系统调用IO进行了封装,从而提供了一套不同OS下相同IO实现库函数
系统调用IO与标准IO示意图

2、FILE对象

FILE对象通常是一个结构体,包含了标准I/O库为管理该流需要的所需要的所有信息

FILE类型贯穿始终,可以理解为FILE就代表流

一个进程默认打开了三个流,分别是标准输入 stdin、标准输出 stdout 和标准错误 stderr

一个进程默认打开1024个流,可通过如下命令查看LINUX控制shell程序的资源:

3、打开和关闭文件

3.1 fopen

FILE *fopen(const char *pathname, const char *mode);
// The fopen() function opens the file whose name is the string pointed to by pathname and associates a stream with it.
  • pathname — 字符串,表示要打开的文件名称
  • mode — 字符串,表示文件的访问模式,该指针指向以下面字符开头的字符串:
mode描述(man手册的直接翻译)
"r"为读取而打开文本文件。流定位到文件开头
"r+"为读写而打开。流定位到文件开头
"w"将文件截断至0长,或为写入而创建文本文件。流定位到文件开头
"w+"为读写而打开。文件不存在则创建,否则截断。流定位到文件开头
"a"为追加(在文件尾写)而打开。文件不存在则创建。流定位到文件末尾
"a+"为读和追加而打开。文件不存在则创建。读取文件的初始位置是文件的开头,但输出总是追加到文件的结尾

只有模式 "r" 和 "r+" 要求文件必须存在,其他模式都可以创建文件;

mode也可以包含字母 b,放在最后或者中间,表示二进制流。例如 "rb"、"r+b";

打开成功返回一个 FILE 指针,否则返回 NULL 并设置全局变量 errno 来标识错误。该全局变量在头文件 errno.h 中声明:(只展示部分)

#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */

为了通过全局变量 errno 的值得到对应的错误提示信息,可以利用C标准中定义的如下两个函数

#include <stdio.h>
void perror(const char *s);
// 在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用“某些”函数出错时,该函数已经重新设置了errno的值
// perror函数只是将你输入的一些信息和errno所对应的错误一起输出
#include <string.h>
char *strerror(int errnuum);
// 搜索错误号errnum,并返回一个指向错误消息字符串的指针

代码示例:


fopen函数解析:

由函数原型可知,fopen函数返回的是一个FILE类型的指针,FILE是一个结构体,由typedef进行了重命名,而指针实际上是指向结构体的指针

关键问题:指针指向的哪个区?也就是说FILE结构体放在内存的哪一块?是堆,是栈,还是静态区?

换句话说,在fopen函数内部,FILE对象是如何创建的?

如果创建在栈区,当程序退出这个块时,释放刚才为变量tmp分配的栈内存,因此,会返回一个被释放的内存地址,错误

FILE *fopen(const char *pathname, const char *mode)
{
    FILE tmp;

    // 给结构体成员赋值初始化
    tmp.xxx = xxx;
    tmp.yyy = yyy;
    ...

    return &tmp;
}

如果创建在静态区,假如多次调用 fopen 函数,也只能存在一个FILE实例(因为只有这一个内存区供指针指向),最后一次的FILE结构体内容会把前一次的结果覆盖掉,错误

FILE *fopen(const char *pathname, const char *mode)
{
    static FILE tmp;
    
    // 给结构体成员赋值初始化
    tmp.xxx = xxx;
    tmp.yyy = yyy;
    ...
    
    return &tmp;
}

创建在堆区,这是正确的,此时 tmp 具有动态存储期,从调用 malloc 分配内存到调用 free 释放内存为止,而 free 就在 fclose 函数中被调用

FILE *fopen(const char *pathname, const char *mode)
{
    FILE * tmp = malloc(sizeof(FILE));
    
    // 给结构体成员赋值初始化
    tmp->xxx = xxx;
    tmp->yyy = yyy;
    ...

    return tmp;
}

3.2 fclose

int fclose(FILE *stream);
// The fclose() function flushes the stream pointed to by stream (writing any buffered output data using fflush(3)) and closes the underlying file descriptor.
  • stream — 这是指向 FILE 对象的指针,该 FILE 对象指定了要被关闭的流
  • 如果流成功关闭,则该方法返回零。如果失败,则返回 EOF

一般来说,fopen 和 fclose 一一对应,fopen 中为 FILE 对象分配动态内存,fclose 中利用 free 释放所分配的动态内存

代码示例:

4、输入输出流

下面仅给出部分字符和字符串的输入输出流操作,详细见 man 手册

  • man 3 fgetc
  • man 3 fputc
  • man 3 fread
  • man 3 fwrite

4.1 fgetc

int fgetc(FILE *stream);
// fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, 
// or EOF on end of file or error.

功能:从指定流中获取下一个字符 

还有几个类似功能的:

int getc(FILE *stream);

int getchar(void);

getchar 等同于 getc(stdin);

getc 和 fgetc 使用方式完全相同,fgetc 通过函数实现,而 getc 通过宏定义实现;

fgetc 中的 f 代表的是 function 的意思,而不是 file 的意思;

宏只占用编译时间,不占用调用时间,而函数相反,因此内核的实现通常使用宏来定义函数,因为调用函数的时间通常长于调用宏;

4.2 fputc

int fputc(int c, FILE *stream);
// fputc() writes the character c, cast to an unsigned char, to stream.

功能:将指定字符写入指定流 

还有几个类似功能的:

int putc(int c, FILE *stream);

int putchar(int c);

putchar 等同于 putc(c, stdout);

putc 和 fputc 使用方式完全相同,fputc 通过函数实现,而 putc 通过宏定义实现;

fputc 中的 f 代表的是 function 的意思,而不是 file 的意思;

宏只占用编译时间,不占用调用时间,而函数相反,因此内核的实现通常使用宏来定义函数,因为调用函数的时间通常长于调用宏;

代码示例:实现一个拷贝文件的功能

将文件 src 拷贝为 dest 

./mycpy src dest

实现代码如下:

使用方法:

diff 对两个文件内容进行对比,如果两个文件完全相同,则什么也不输出

4.3 fgets

char *fgets(char *s, int size, FILE *stream);
// fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.
// Reading stops after an EOF or a newline. 
// If a newline is read, it is stored into the buffer. 
// A terminating null byte ('\0') is stored after the last character in the buffer.

功能:从指定流中读取批量字符

  • s:指向一个 buffer 缓冲,用于储存从指定流中读取到的字符
  • size:用于限制每次读取的字符个数最多 size - 1 个
  • stream:指定流

fgets 读取结束的条件,满足其一即可:

  • 读到 size-1 个字符时停止
  • 读到换行符 '\n' 时停止,换行符会被存进缓冲
  • 读到文件末尾 EOF

读取结束后,会往读取进 buffer 的最后一个字符后,再添加一个 '\0' ;

如果成功读取到字符,返回 s;

如果发生错误或者什么字符也没读取到,返回 NULL;

任何一个非空文件,末尾都有一个换行符 '\n'

#define SIZE 5
char buf[SIZE]; // 栈上的动态内存
fgets(buf, SIZE, stream);

如果stream = "abcde"
则buf = "abcd\0"(读到size-1),文件指针指向e

如果stream = "ab"
则buf = "ab\n\0"(读到换行符),文件指针指向EOF

极端的情况:
如果stream = "abcd"
则需要fgets读取两次才能读完
第一次读取的为"abcd\0"(读到SIZE-1),指针指向'\n'
第二次读取的为"\n\0"(读到换行符),指针指向EOF

4.4 fputs

int fputs(const char *s, FILE *stream);
// fputs() writes the string s to stream, without its terminating null byte ('\0').

功能:将批量字符(即字符串)写入流

写入流的不包括末尾空字符 '\0'

4.5 fread

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
// The  function fread() reads nmemb items of data, 
// each size bytes long, 
// from the stream pointed to by stream, 
// storing them at the location given by ptr.
  • stream — 这是指向 FILE 对象的指针,表示从该文件对象读取;
  • nmemb — 待读取元素的个数;
  • size — 读取的每个元素的大小,以字节为单位;
  • ptr — 将读取到的元素放进 ptr 所指的位置;

函数返回成功读取的元素的数目,如果出错或者达到 EOF,则返回值可能少于 nmemb

示例:

fread(buf, size, nmemb, fp);

// 情况1:数据量足够
// 情况2:文件只有5个字节

// 读10个对象,每个对象1个字节
fread(buf, 1, 10, fp);

// 情况1:
// 第一次读:返回10(读到10个对象),读到10个字节
// 情况2:
// 第一次读:返回5(读到5个对象),读到5个字节

//--------------------------------

// 读1个对象,每个对象10个字节
fread(buf, 10, 1, fp);

// 情况1:
// 第一次读:返回1(读到1个对象),也读到10个字节
// 情况2:
// 第一次读:返回0(读不到1个对象,因为1个对象要10字节,而文件只有5个字节)

 因此建议单字节读取

4.6 fwrite

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
// The function fwrite() writes nmemb items of data, 
// each size bytes long, 
// to the stream pointed to by stream, 
// obtaining them from the location given by ptr.
  • ptr — 从 ptr 所指的内存空间获取待写入元素;
  • nmemb — 写入元素的个数;
  • size — 写入的每个元素的大小,以字节为单位;
  • stream —  这是指向 FILE 对象的指针,表示将元素写入到 stream 输出流;

函数返回成功写入的元素的数目。如果该数字与 nmemb 参数不同,则会显示一个错误。

代码示例:用 fread 和 fwrite 代替 fgtec 和 fputc:

4.7 printf 族函数

#include <stdio.h>

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);    // write at most size bytes (including the terminating null byte ('\0')) to str
  • printf:发送格式化输出到标准输出流 stdout;
  • fprintf:发送格式化输出到流 stream 中。可以实现格式化输出的重定向;
  • sprintf:发送格式化输出到 str 所指内存。它能够将多种数据类型(整型、字符型)的数据综合为字符串类型;
  • snprintf:发送格式化输出到 str 所指内存。它能够将多种数据类型(整型、字符型)的数据综合为字符串类型,最多发送 size 个字符(包括末尾的 '\0')

辅助函数:将字符串初始部分转化为整数

#include <stdlib.h>

// convert a string to an integer

int atoi(const char *nptr);    // The atoi() function converts the initial portion of the string pointed to by nptr to int.
long atol(const char *nptr);
long long atoll(const char *nptr);

4.8 scanf 族函数

#include <stdio.h>

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

功能:按照格式说明符读取并解析输入对应位置的信息并存储于可变参数列表中对应的指针所指位置 

三者区别: 

The scanf() function reads input from the standard input stream stdin, fscanf() reads input  from the  stream pointer stream, and sscanf() reads its input from the character string pointed to by str. 

5、文件指针操作

5.1 fseek

#include <stdio.h>

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

// The  fseek() function sets the file position indicator for the stream pointed to by stream.

功能:设置文件位置指针指向

  • stream — 这是指向 FILE 对象的指针,该 FILE 对象标识了流
  • offset — 这是相对 whence 的偏移量,以字节为单位
  • whence — 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:
常量描述
SEEK_SET文件的开头
SEEK_CUR文件位置指针当前所在位置
SEEK_END文件的末尾EOF,即文件中最后一个字符的下一个位置

如果成功,则该函数返回零,否则返回非零值

文件位置指针是什么?

  • 文件位置指针用来指示文件中的某个位置,因此在程序中进行读写操作时,位置指针也会随着文件的读写操作而改变
  • 在进行读写操作时,位置指针会自动更新到下一个读写的位置。 例如,当进行读操作时,位置指针会自动更新到下一个可读的位置;当进行写操作时,位置指针会自动更新到下一个可写的位置

5.2 ftell

long ftell(FILE *stream);

功能: 返回文件位置指针所指位置(从文件起始位置开始,并以字节为单位度量,相对起始位置的偏移)

5.3 rewind 

void rewind(FILE *stream);

功能:设置文件位置指针的位置为给定流 stream 的文件的开头 

使用时功能等同于:

(void) fseek(stream, 0L, SEEK_SET)

fseek 和 ftell 函数功能详解:

fseek 和 ftell 中偏移offset的修饰类型是 long,因此只能对2G左右大小的文件进行操作,否则会超出long的范围

fseeko 和 ftello 则将偏移的修饰类型使用typedef定义为offset_t,具体类型交由系统决定,因此不存在文件大小的限制。但是这两个函数不是C标准库函数,而是隶属于POSIX标准(POSIX是标准C库的超集,或者说,C库是普通话,而POSIX是方言)

代码示例:求文件的有效字节数

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char **argv){

    FILE *fp;
    if(argc < 2) {
        fprintf(stderr, "Usage...\n");
        exit(1);
    }

    fp = fopen(argv[1], "r");
    if(fp == NULL) {
        perror("fopen()");
        exit(1);
    }
	// 将指针定位在文件末尾
    fseek(fp, 0, SEEK_END);

    printf("%ld\n", ftell(fp));

    exit(0);
}

6、缓冲相关

先看一个现象

 

发现 while 循环前的那行字符串并没有显示! 

原因:对于标准输出,输出缓冲区刷新的时机:

  • 输出缓冲区满
  • 或者遇到换行符\n
  • 强制刷新,或者进程结束

因此,上述 while 循环前的那行只是进入输出缓冲区了,并没有冲洗

标准 I/O 提供缓冲的目的是为了减少使用系统调用 read 和 write 的次数,增加程序的吞吐量

6.1 fflush

#include <stdio.h>

int fflush(FILE *stream);

功能:冲洗缓冲区

  • 如果参数为 stream 为 NULL,则冲洗所有的已打开的流
  • 如果成功,该函数返回零值。如果发生错误,则返回 EOF,且设置错误标识符(即 feof)

术语冲洗(flush)说明标准I/O缓冲区的写操作。缓冲区可由标准I/O例程自动地冲洗(例如, 当填满一个缓冲区时),或者可以调用函数 fflush 冲洗一个流。值得注意的是,在UNIX环境中,flush有两种意思。在标准I/O库方面,flush(冲洗)意味着将缓冲区中的内容写到磁盘上(该缓冲区可能只是部分填满的)。在终端驱动程序方面,flush(刷清)表示丢弃已存储在缓冲区中的数据。

可行的一些修改方式:

  • 标准输出遇到换行符 '\n' 自动冲洗

 

  • 通过 fflush 手动冲洗 stdout

即可得到期望的输出


标准I/O缓冲的分类(即除了手动 fflush 以外,不同类的缓冲有不同的默认冲洗(标准IO指写入磁盘)时机):

  • 全缓冲(块缓冲):在全缓冲的情况下,在填满标准I/O缓冲区后,才进行冲洗
  • 行缓冲:行缓冲指的是当遇到换行符时,或者缓冲区已经满了(一般1024字节),执行冲洗
  • 无缓冲:不会填缓冲区,可以理解为立即冲洗

不同的标准I/O有默认的缓冲类别 

  • 磁盘上的文件默认是全缓冲的
  • 标准输入和标准输入默认是行缓冲的
  • 一般指向终端设备的流默认是行缓冲,而指向文件时,则默认是全缓冲
  • 为了立即显示错误信息,标准错误默认是无缓冲的

关于缓冲这段的 man 手册:

6.2 setvbuf  

int setvbuf(FILE *stream, char *buf, int mode, size_t size);
// The setvbuf() function may be used on any open stream to change its buffer

功能: 用于改变流的缓冲类别(即改变流在不调用 fflush 的情况下的冲洗时机)

  • stream — 这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流
  • buf — 这是用户指定的用于存缓冲内容的位置。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲空间
  • size — the buf argument should point to a buffer at least size bytes long
  • mode — 这指定了文件缓冲的类别:
mode描述
_IOFBF全缓冲
_IOLBF行缓冲
_IONBF无缓冲

7、补充

7.1 getline

之前介绍的函数,都不能获得完整的一整行(有缓冲区大小的限制),而下面介绍的getline函数则可以动态分配内存,当装不下完整一行时,又会申请额外的内存来存储

getline会生成一个包含一串从输入流读入的字符的字符串,直到以下情况发生会导致生成的此字符串结束:

  • 到文件结束
  • 遇到函数的定界符
  • 输入达到最大限度
#define _GNU_SOURCE // 通常将这种宏写在makefile中,现在的编译器没有了该宏,直接使用即可
#include <stdio.h>
ssize_t getline(char **lineptr, size_t *n, FILE *stream);

功能:用于从流中读取完整的行 

要理解这些参数的含义,必须要知道 getline 的工作原理

这样再对照 getline 的声明,就知道各种参数和返回值的含义了

ssize_t getline(char **lineptr, size_t *n, FILE *stream);
  • lineptr:用于存放开辟空间的首地址,*lineptr 指向所开辟空间
  • n:用于存放开辟空间的字节数,*n 为开辟空间的字节数
  • 返回值为读取到的字符数,读取失败返回 -1 

注意 man 手册中的一句特殊的使用要求:

If *lineptr is set to NULL and *n is set 0 before the call, then getline() will allocate a buffer for storing the line.  This buffer should be freed by the user program even if getline() failed.

使用示例:

注意区分开辟空间的字节数和读取到的字符数! 

7.2 临时文件 

临时文件产生的问题:

  • 如何命名不冲突
  • 如何保证及时销毁

tmpnam:生成并返回一个有效的临时文件名,该文件名之前是不存在的。如果 str 为空,则只会返回临时文件名。

存在并发问题,可能会产生两个或多个名字相同的临时文件

可能两个不同进程运行该函数时,检查文件名后,生成文件名前发生了进程切换

#include <stdio.h>
char *tmpnam(char *s);
  • s — 这是一个指向字符数组的指针,其中,临时文件名将被存储为 C 字符串
  • 返回一个指向 C 字符串的指针,该字符串存储了临时文件名。如果 s 是一个空指针,则该指针指向一个内部缓冲区,缓冲区在下一次调用函数时被覆盖
  • 如果 s 不是一个空指针,则返回 s。如果函数未能成功创建可用的文件名,则返回一个空指针

另一个函数:

tmpfile:以二进制更新模式(wb+)创建临时文件。被创建的临时文件会在流关闭的时候或者在程序终止的时候自动删除。

该文件没有名字(匿名文件),函数只返回指向FILE的指针,因此不存在命名冲突的问题,同时会自动删除,因此可以及时销毁。

#include <stdio.h>
FILE *tmpfile(void);
  • 如果成功,该函数返回一个指向被创建的临时文件的流指针。如果文件未被创建,则返回 NULL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/997417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安装samba服务器

1.实验目的 &#xff08;1&#xff09;了解SMB和NETBIOS的基本原理 &#xff08;2&#xff09;掌握Windows和Linux之间&#xff0c;Linux系统之间文件共享的基本方法。 2.实验内容 &#xff08;1&#xff09;安装samba服务器。 &#xff08;2&#xff09;配置samba服务器的…

Visual Studio 线性表的链式存储节点输出引发异常:读取访问权限冲突

问题&#xff1a; 写了一个线性表的链式存储想要输出&#xff0c;能够输出&#xff0c;但是会报错&#xff1a;读取访问权限冲突 分析&#xff1a; 当我们输出到最后倒数第二个节点时&#xff0c;p指向倒数第二个节点并输出&#xff1b; 下一轮循环&#xff1a;p指向倒数第二…

Helm Kubernetes Offline Deploy Rancher v2.7.5 Demo (helm 离线部署 rancher 实践)

文章目录 1. 简介2. 预备条件3. 选择 SSL 配置4. 离线安装的 Helm Chart 选项5. 下载介质6. 生成证书7. 镜像入库8. 安装 rancher9. 配置 nodeport10. 配置 ingress11. 界面访问11.1 首页预览11.2 查看集群信息11.3 查看项目空间11.4 查看节点信息 1. 简介 Rancher 是一个开源…

17-数据结构-查找-(顺序、折半、分块)

简介&#xff1a;查找&#xff0c;顾名思义&#xff0c;是我们处理数据时常用的操作之一。大概就是我们从表格中去搜索我们想要的东西&#xff0c;这个表格&#xff0c;就是所谓的查找表&#xff08;存储数据的表&#xff09;。而我们怎么设计查找&#xff0c;才可以让计算机更…

lv4 嵌入式开发-4 标准IO的读写(二进制方式)

目录 1 标准I/O – 按对象读写 2 标准I/O – 小结 3 标准I/O – 思考和练习 文本文件和二进制的区别&#xff1a; 存储的格式不同&#xff1a;文本文件只能存储文本。除了文本都是二进制文件。 补充计算机内码概念&#xff1a;文本符号在计算机内部的编码&#xff08;计算…

2023/09/10

文章目录 1. 使用Vue单页面全局变量注意事项2. 伪元素和伪类3. Vue3中定义数组通常使用ref4. Vue Router的 $router 和 $route5. Vue路由中的query和params的区别6. vue3defineExpose({})属性不能重命名&#xff0c;方法可以重命名7. 显卡共享内存的原理8. deltaY9. 快速生成方…

电池2RC模型 + 开路电压法 + 安时积分 + 电池精度测试 + HPPC脉冲

电池2RC模型 电池2RC模型是一种等效电路模型&#xff0c;用于描述电池的动态特性。该模型将电池视为一个理想电容器和一个理想电阻的并联&#xff0c;其中理想电容器代表电池的化学反应&#xff0c;理想电阻代表电池的内阻。该模型适用于描述电池的充电和放电过程。 开路电压…

Java中如何判断字符串输入[hello,world]是不是字符串数组参数

Java中如何判断字符串输入[hello,world]是不是字符串数组参数&#xff1f; 在Java中&#xff0c;可以使用正则表达式来判断一个字符串是否符合字符串数组的参数格式。你可以使用matches()方法和对应的正则表达式进行判断。 以下是一个示例代码&#xff1a; public static bo…

SpringCloudGateway网关实战(二)

SpringCloudGateway网关实战&#xff08;二&#xff09; 本文我们在前文的基础上&#xff0c;开始讲gateway过滤器的部分内容。gateway的过滤器分为内置过滤器Filter和全局过滤器GlobalFilter。本章节先讲内置过滤器Filter。 需要先声明一下内置过滤器和全局过滤器之间的区别…

mysql文档--innodb中的重头戏--事务隔离级别!!!!--举例学习--现象演示

阿丹&#xff1a; 先要说明一点就是在网上现在查找的mysql中的事务隔离级别其实都是在innodb中的事务隔离级别。因为在mysql的5.5.5版本后myisam被innodb打败&#xff0c;从此innodb成为了mysql中的默认存储引擎。所以在网上查找的事务隔离级别基本上都是innodb的。并且支持事务…

JavaScript基础10——获取数据类型、类型转换

哈喽&#xff0c;大家好&#xff0c;我是雷工。 现如今知识大爆炸&#xff0c;到处都有海量的知识&#xff0c;常常见了就收藏&#xff0c;把网盘塞得满满的&#xff0c;却从来没有看过。 收藏起来装到网盘里并没有什么软用&#xff0c;要把知识装到脑袋里才行。 从几分钟开始&…

【LeetCode-中等题】26. 删除有序数组中的重复项

文章目录 题目方法一&#xff1a;快慢指针 题目 方法一&#xff1a;快慢指针 class Solution { //快慢指针public int removeDuplicates(int[] nums) {int fast 1;int slow 0;while(fast < nums.length){if(nums[fast] nums[fast-1]) fast;//若当前元素和之前元素相同 则…

华为OD机试 - 战场索敌 - 深度优先搜索dfs算法(Java 2023 B卷 100分)

目录 一、题目描述二、输入描述三、输出描述四、深度优先搜索dfs五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明4、如果增加目标敌人数量K为55、来&#xff0c;上强度 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 一、题目描述 有一个大小是N*M…

ros_launch配置

创建launch文件批运行节点和包 将以下四条指令写入launch文件中 获取软件包的完整指令 rospackpkg&#xff1a;软件包名字 type&#xff1a;节点名字 四条指令转化成launch文件

无人机航线规划

无人机航线规划&#xff0c;对于无人机的任务执行有着至关重要的作用&#xff0c;无人机在从起点飞向目的点的过程中&#xff0c;如何规划出一条安全路径&#xff0c;并且保证该路径代价最优&#xff0c;是无人机航线规划的主要目的。其中路径最优的含义是&#xff0c;在无人机…

大数据-玩转数据-Flink 容错机制

一、概述 在分布式架构中&#xff0c;当某个节点出现故障&#xff0c;其他节点基本不受影响。在 Flink 中&#xff0c;有一套完整的容错机制&#xff0c;最重要就是检查点&#xff08;checkpoint&#xff09;。 二、检查点&#xff08;Checkpoint&#xff09; 在流处理中&am…

初识Nacos

前言 Nacos是一个用于微服务架构下的服务发现和配置管理以及服务管理的综合解决方案&#xff08;官网介绍&#xff09;&#xff0c;这里的服务发现其实就是注册中心&#xff0c;配置管理就是配置中心&#xff0c;而服务管理是二者的综合&#xff1b; Nacos特性 1.服务发现与…

《Go语言在微服务中的崛起:为什么Go是下一个后端之星?》

&#x1f337;&#x1f341; 博主猫头虎&#x1f405;&#x1f43e; 带您进入 Golang 语言的新世界✨✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f…

【JavaEE】_CSS常用属性值

目录 1. 字体属性 1.1 设置字体家族 font-family 1.2 设置字体大小 font-size 1.3 设置字体粗细 font-weight 1.4 设置字体倾斜 font-style 2. 文本属性 2.1 设置文本颜色 color 2.2 文本对齐 text-align 2.3 文本装饰 text-decoration 2.4 文本缩进 text-indent 2.…

车载软件架构——基础软件供应商开发工具链(二)

车载软件架构——基础软件供应商&开发工具链(二) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己…