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

【Linux】文件操作的艺术——从基础到精通

🎬 个人主页:谁在夜里看海.

📖 个人专栏:《C++系列》《Linux系列》《算法系列》

⛰️ 道阻且长,行则将至


目录

📚前言:一切皆文件 

📚一、C语言的文件接口

📖1.文件打开

🔖语法

🔖本质

🔖示例

📖2.文件读取

🔖语法

🔖示例

📖3.文件写入

🔖语法

🔖示例

📖4.文件关闭

🔖语法

🔖作用

📖5.默认流指针

📚二、系统调用接口

📖1.文件打开

🔖语法

🔖示例

📖2.文件读取

🔖语法

🔖示例

📖3.文件写入

🔖语法

🔖示例

📖4.文件关闭

🔖语法

📚三、底层调用&上层封装

📖1.底层调用

📖2.上层封装

🔖3.示例

✅4.总结 

📚四、文件描述符fd

📖1.工作原理

🔖示例

📖2.分配原则

📚五、重定向

📖1.常见的重定向

📖2.本质

📖3.dup2系统调用

🔖语法 

🔖示例

📚六、总结


📚前言:一切皆文件 

在正式开始文件操作的介绍之前,我们先来解决一个问题,什么是文件?

我们常见的文件有:文本文件(如.txt,.cpp),二进制文件(如编译后的可执行文件),图像文件等等,我们和这些文件打交道,无非就是对文件写入和对文件读取,然而我们是怎么实现对文件的写入和读取的呢?其实操作系统为我们提供了这一切,我们告诉系统要访问哪个文件,调用系统提供的方法,就实现了对文件的操作

但文件的概念并不仅仅局限于磁盘上的存储内容,在操作系统中,几乎所有资源都可以通过类似“文件”的方式来进行访问和操作。无论是硬盘上的数据,还是连接计算机的外设设备,操作系统都通过类似文件的机制来统一管理他们。这是操作系统设计的一个重要思想——一切皆文件

在这个框架下,设备(如键盘、鼠标、网络接口、内存等)不再是与文件不同的资源,而是被抽象为一种特殊类型的文件,通过统一的系统调用接口,我们可以像操作普通文件那样,操作这些设备,这种设计方式使得我们能够以一种一致的方式访问硬件资源。

下面我们来介绍操作系统具体是如何对文件进行操作,以及如何以“文件”的方式管理各种设备的。

📚一、C语言的文件接口

任何对文件的操作都可以看成对数据的访问、读取和写入,系统为我们提供了这些操作的接口,下面我们就来看看C语言下的文件接口:

📖1.文件打开

🔖语法

C语言提供了标准库函数 fopen() 用于打开文件:

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

① 参数1:filename,表示文件名,指定要打开的文件路径,可以是绝对路径也可以是相对路径

② 参数2:mode,文件打开模式,指定打开文件的方式(文件操作的权限),常见的有:

     "r",只读方式打开文件,文件必须存在

     "w",只写方式打开文件,文件不存在则创建,存在则清空文件

     "a",追加模式,文件不存在则创建,存在则数据追加到文件末尾

     "rb",以二进制模式读取文件

     "rw",以二进制模式写入文件

③ 返回值类型:FILE*,文件指针,用于标记当前打开的文件

🔖本质

fopen文件访问其实是做了以下工作:

1. 定位当前文件

我们打开一个文件的本质其实是向系统申请指定文件的描述符(FILE*指针),通过这个描述符系统就能定位文件,才能完成后续的读写操作。所以对文件操作之前一定要先打开文件(其实就是获取文件描述符

在C语言中,文件描述符以指针的形式存在,FILE * 是一个指向文件对象的指针,它是一个结构体,内部包含了文件操作的状态(如文件位置、访问模式等)。

2.设置文件访问模式

打开文件时,需要指定文件的“访问模式”(如读取、写入、追加等),这告诉操作系统你希望如何使用文件:是否允许读取文件内容,是否可以修改文件,文件是否追加数据,如果文件不存在是否需要创建。

3.定位文件指针

当文件被打开时,操作系统会初始化一个文件指针指示文件中当前可以进行读写操作的位置。在文件读取或写入时,文件指针会根据操作而前进或后退。例如,当你读一个文件时,文件指针会向前移动,直到读到文件的末尾(EOF)。当你写一个文件时,文件指针通常会向文件的结尾移动,或者在追加模式下继续从文件的末尾写入。 

🔖示例
    FILE *fp = fopen("myfile", "w");if(!fp){printf("fopen error!\n"); // 访问失败返回空指针}

这里以"w"只写的方式打开"myfile"文件(文件不存在则创建,存在则清空),并返回一个文件指针, 如果该文件没有写权限时,打开失败,返回空指针。

📖2.文件读取

🔖语法

C语言提供了标准库函数 fread() 用于读取文件数据到缓冲区中:

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

① 参数1:ptr,指向存储读取数据的缓冲区的指针,读取的数据会存放到该缓冲区

② 参数2:size,读取的单个数据元素的大小(单位为字节)

③ 参数3:count,读取的元素个数

④ 参数4:stream,文件指针(FILE *,就是前面 fopen 的返回值) 

⑤ 返回值类型:size_t,返回成功读取的元素个数(count)

🔖示例
#include <stdio.h>
#include <stdlib.h>int main() {FILE *fp = fopen("numbers.dat", "rb");if (fp == NULL) {perror("Error opening file");return 1;}int numbers[100];size_t elementsRead = fread(numbers, sizeof(int), 100, fp);if (elementsRead != 100) {if (feof(fp)) {printf("Reached end of file.\n");} else {perror("Error reading file");}}for (size_t i = 0; i < elementsRead; i++) {printf("%d ", numbers[i]);}printf("\n");fclose(fp);return 0;
}

fread() 这里用于读取 numbers.dat 文件的100个整数,如果文件中少于100个整数,fread() 会读取到文件结束,并返回实际读取的文件个数。

使用 feof() 检查文件是否到达文件末尾,到达返回1,否则返回0。

📖3.文件写入

C语言提供了标准库函数 fwrite() 用于文件写入,与 fread() 相对应:

🔖语法
ssize_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);

① 参数1:ptr,指向写入数据指针,可以是数组、结构体、字符串等

② 参数2:size,写入的单个数据元素的大小(单位为字节)

③ 参数3:count,写入的元素个数

④ 参数4:stream,文件指针(FILE *,就是前面 fopen 的返回值) 

⑤ 返回值类型:size_t,返回成功写入的元素个数(count)

可以看出 fwrite() 和 fread() 的函数构造是一样的。

🔖示例
#include <stdio.h>
#include <stdlib.h>int main() {FILE *fp = fopen("numbers.dat", "wb");if (fp == NULL) {perror("Error opening file");return 1;}int numbers[] = {1, 2, 3, 4, 5};size_t elementsWritten = fwrite(numbers, sizeof(int), 5, fp);if (elementsWritten != 5) {perror("Error writing file");}fclose(fp);return 0;
}

fwrite() 将整数数组 numbers 中的5个整数写入文件 number.dat,如果写入的元素个数小于预期,程序会打印错误信息

❗️注意:

写入文件时必须使用 "wb" 或 "w" 模式打开文件;使用 "wb" 或 "w" 打开文件时,会清空文件的现有内容(如果文件已经存在)。如果你希望追加数据,而不是覆盖原文件,可以使用 "a" 或 "ab"模式打开文件。

📖4.文件关闭

fclose() 函数用于关闭 fopen() 打开的文件,并释放文件的资源。关闭文件后,不能再通过该文件指针访问文件内容:

🔖语法
#include <stdio.h>int fclose(FILE *stream);

① 参数:stream,指向FILE对象的指针,表示要关闭的文件

② 返回值类型:int,关闭成功返回0,失败返回 EOF,可以通过 perror() 获取错误信息。

🔖作用

1.冲刷缓冲区:如果文件是以写方式打开的,fclose() 会保证缓冲区的数据被刷新到磁盘,如果有任何未写入的数据,都会被写入目标文件。

2.释放资源:关闭文件后,操作系统会释放与该文件相关的资源(例如文件描述符)。这对于防止资源泄漏非常重要。

3.文件指针失效:文件关闭后,文件指针不再有效。若再次访问该指针,将导致未定义行为。

📖5.默认流指针

fopen()返回的文件指针我们又称之为文件流指针,因为文件本质上是一个数据流,它可以从文件中读取数据,也可以向文件中写入数据。在这种抽象下,文件操作就像处理一个数据流,而文件流指针则是指向这个流的一个句柄。

在C语言中,有三个默认的文件流指针,分别指向标准输入、标准输出和标准错误输出,使得我们无需显式地打开文件即可进行常见的文件操作:

stdin 是标准输入流,指向键盘输入,可以使用 scanf() 从标准输入读取数据,也可以通过这个流指针,将键盘输入的数据存储到磁盘文件中;

stdout 是标准输流,指向终端或控制台,可以使用 printf() 将数据输出到标准输出,也可以通过流指针将磁盘文件内容输出到标准输出中;

#include <stdio.h>#include <string.h>int main(){const char *msg = "hello fwrite\n";fwrite(msg, strlen(msg), 1, stdout);printf("hello printf\n");fprintf(stdout, "hello fprintf\n");return 0;}

stderror 是标准错误流,用于输出错误信息。也指向终端或控制台。

📚二、系统调用接口

在操作系统中,文件操作不仅仅是通过标准库函数如 fopen(), fread(), fwrite(), 和 fclose() 实现的,还可以通过系统调用接口直接进行。系统调用提供了低级别、直接的操作系统资源访问方式,包括对文件的操作。这些系统调用通常用于底层编程,它们绕过标准库函数,直接与操作系统内核交互

📖1.文件打开

在 Linux 系统中,文件的打开操作是通过系统调用 open() 完成的。open() 函数会返回一个文件描述符(而不是 FILE* 指针),这是操作文件的基础:

🔖语法
int open(const char *pathname, int flags, mode_t mode);

① 参数1:pathname,文件路径,指定要打开的文件。

② 参数2:flags,指定文件的打开模式,如:

     O_RDONLY:只读模式

     O_WRONLY:只写模式

     O_RDWR:读写模式

     O_CREAT:如果文件不存在则创建

     O_APPEND:追加模式

③ 参数3:mode,文件的默认权限设置,仅在创建新文件时有效,通常为0644权限位:

     0表示当前数字为八进制,我们在设置权限时,要考虑三类用户:所有者所有组以及其他用户

     644表示所有者权限为可读可写不可执行,所有组和其他用户仅可读,不可写不可执行。

④ 返回值:int,打开成功时返回一个非负整数,表示文件描述符;打开失败返回-1。int类型的文件描述符和FILE*指针作用一样,都可以指向文件,前者可以看作数组下标,后者作为指针指向

🔖示例
#include <fcntl.h>
#include <unistd.h>int main()
{    int fd1 = open("myfile_1", O_RDONLY); // mode可缺省int fd2 = open("myfile_2", O_WRONLY, 0664);
}

📖2.文件读取

系统调用 read() 用于从已打开的文件描述符中读取数据:

🔖语法
ssize_t read(int fd, void *buf, size_t count);

① 参数1:fd,文件描述符,通过 open() 获取。

② 参数2:buf,缓冲区,存储读取的数据。

③ 参数3:要读取的字节数。

④ 返回值:ssize_t,成功时,返回实际读取的字节数;失败时,返回 -1(所以这里不能使用size_t作为返回值,而是ssize_t)

🔖示例
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main(){int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}const char *msg = "hello bit!\n";char buf[1024];while(1){ssize_t s = read(fd, buf, strlen(msg));//类比writeif(s > 0){printf("%s", buf);}else{break;}}close(fd);return 0;}

📖3.文件写入

系统调用 write() 用于将数据写入文件:

🔖语法
ssize_t write(int fd, const void *buf, size_t count);
🔖示例
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main(){umask(0);int fd = open("myfile", O_WRONLY|O_CREAT, 0644);if(fd < 0){perror("open");return 1;}int count = 5;const char *msg = "hello bit!\n";int len = strlen(msg);while(count--)write(fd, msg, len);close(fd);return 0;}

✅umask()是Linux中设置权限掩码的系统调用,用于控制文件创建的默认权限,调用 umask(0) 将文件创建掩码设置为 0,意味着没有权限被去除,系统会允许最大权限的创建。

如果调用 umask(002),则创建的文件会去掉 2 (即 0002),那么文件权限将变成 664,目录权限将变成 775,即去除其他用户的写权限。

📖4.文件关闭

系统调用 close() 用于关闭打开的文件描述符,释放相关资源:

🔖语法
int close(int fd);

① 参数:fd,文件描述符,通过 open() 获取。

② 返回值:int,成功时,返回 0;失败时,返回 -1 。

作用与fclose相同,也是冲刷缓冲区以及释放资源

📚三、底层调用&上层封装

❓C语言标准库函数与系统调用函数都可以实现对文件的访问操作,那么它们之间有什么关联呢?

C语言标准库函数是对系统调用的上层封装

📖1.底层调用

底层调用即系统调用,是操作系统提供的接口,允许用户程序与操作系统内核进行交互。当程序需要进行文件操作时,实际上是通过调用操作系统内核提供的系统调用接口完成的,常见的系统调用接口有 open(), write(), read(), close() 等,这些系统调用直接与操作系统的文件系统进行交互

📖2.上层封装

C语言标准库函数 fopen(), fread(), fwrite(), fclose() 是对操作系统提供的系统调用的封装,它们提供了更高层次的接口,使得使用者不需要直接与操作系统底层交互,能够更便捷地进行文件操作。标准库函数内部实现了文件描述符的管理、缓冲区的操作等,屏蔽了底层的细节。

🔖3.示例

open() 是一个系统调用,直接与操作系统交互,返回一个文件描述符。这个文件描述符可以用于进一步的 read()write() 等操作。其实现较为底层,涉及操作系统的文件系统和内存管理。

fopen() 是 C 语言标准库函数,它的内部实现使用了 open() 系统调用来打开文件。除了 open()fopen() 还管理了缓冲区的初始化等工作,简化了文件操作过程。fopen() 返回的是一个文件指针(FILE*),它在标准库内部使用该指针来进行文件操作,而不是直接暴露文件描述符。

✅4.总结 

特性系统调用 open() / read() / write()系统调用 open() / read() / write()
功能直接与操作系统交互,底层文件操作提供高层接口,封装底层系统调用
返回值文件描述符(int)文件指针(FILE*
管理缓冲区不负责缓冲区管理自动管理文件缓冲区(提高效率)
使用难度较低层,涉及操作系统管理较高层,易于使用,屏蔽底层细节
适用场景需要精细控制文件操作的底层程序一般的文件操作,简洁高效的接口

📚四、文件描述符fd

文件描述符(File Descriptor,简称fd)是操作系统用来表示已打开文件的整数。它是系统用来跟踪打开文件的标识符,与标准流、系统调用的接口密切相关。

📖1.工作原理

每当程序调用 open() 函数打开一个文件,操作系统会为该文件分配一个文件描述符。文件描述符是一个非负整数,用于在后续的系统调用中标识该文件。

操作系统通常会为每个进程维护一个文件描述符表,其中每个文件描述符对应一个打开的文件或设备。在 Linux 系统中,文件描述符通常从 0 开始分配。0、1、2 是系统默认的标准输入、标准输出和标准错误输出流,而其他文件描述符则用于指向程序显式打开的文件。

 

🔖示例
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("example.txt", O_RDONLY);if (fd == -1) {perror("Error opening file");return 1;}// 使用文件描述符fd读取文件内容char buffer[100];ssize_t bytesRead = read(fd, buffer, sizeof(buffer));if (bytesRead > 0) {write(1, buffer, bytesRead);  // 输出到标准输出}close(fd);  // 关闭文件描述符return 0;
}

在这个例子中,程序通过 open() 获取文件描述符 fd,然后用 read() 读取文件内容,最后用 close() 关闭文件描述符。文件描述符 fd 在操作系统内部对应于打开的文件或设备,操作系统会根据它来执行读取操作。

📖2.分配原则

文件描述符的分配原则是怎么样的呢?来看看下面这段代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(){int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);close(fd);return 0;}

此时fd是3,如果我将0或者2关闭呢:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(){close(0);//close(2);int fd = open("myfile", O_RDONLY);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);close(fd);return 0;}

发现此时fd为0(或者2),由此可以得到文件描述符fd的分配原则:

在files_struct数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。 

📚五、重定向

重定向(Redirection)是操作系统提供的一种机制,允许将程序的输入和输出从默认设备(通常是终端或控制台)重定向到其他设备或文件。重定向通常通过操作系统提供的文件描述符来实现。

例如还是上面那段代码,我们关闭1:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>int main(){close(1);int fd = open("myfile", O_WRONLY|O_CREAT, 00644);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);fflush(stdout);close(fd);exit(0);}

此时我们发现,本应该输出到显示器上的内容输出到了文件myfile中,其中fd=1,这种现象叫做输出重定向。常见的重定向有:>, >>, <:

📖1.常见的重定向

🔖> (输出重定向):

功能: 将命令的标准输出重定向到一个文件中。如果目标文件已经存在,则会覆盖文件内容。

echo "Hello, World!" > output.txt

这会将 "Hello, World!" 输出到 output.txt 文件中,覆盖文件原有内容。

🔖>> (追加输出重定向):

功能: 将命令的标准输出追加到文件末尾。如果目标文件不存在,则会创建文件。

echo "New line of text" >> output.txt

这会将 "New line of text" 追加到 output.txt 文件的末尾。

🔖< (输入重定向):

功能: 将文件的内容作为标准输入传递给命令。

sort < input.txt

这会将 input.txt 文件的内容传递给 sort 命令进行排序。

这三种重定向符号是最常见的,用于控制数据流向文件或从文件读取数据。在复杂的脚本或命令行操作中,它们非常有用,能够帮助用户将输出存储到文件中或从文件中读取数据。

📖2.本质

重定向的本质是改变数据流的方向,每个文件描述符(如 0, 1, 2)都关联一个 file_struct(文件结构体)。当进行重定向操作时,操作系统需要首先清空当前文件描述符的相关信息,然后修改文件描述符的指向,例如将2重定向到1时: 

① 清除 2 指向的文件结构体内容;

② 修改 2 的指向,使其指向 1 所指向的文件结构体内容。

📖3.dup2系统调用

dup2 是一个用于文件描述符复制的系统调用,它的作用是将一个现有的文件描述符复制到另一个文件描述符上,替换掉目标文件描述符原有的内容。

🔖语法 
int dup2(int oldfd, int newfd);

① oldfd:源文件描述符,表示要复制的现有文件描述符;

② newfd:目标文件描述符,表示复制到该文件描述符。如果该文件描述符已经打开,则它会被关闭,然后复制 oldfd 的内容。

🔖示例
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>int main()
{int fd = open("./tmp.txt", O_RDWR|O_CREAT, 0664);if (fd < 0)return -1;dup2(fd, 1);printf("i like linux!\n");return 0;
}

这里我们将标准输出重定向到文件tmp.txt中,执行结果:

📚六、总结

在 C 语言中,标准库函数提供了较高层次的抽象,使得文件操作变得简便易用。我们通过 fopen() 打开文件,利用 fread()fwrite() 进行读写操作,并通过 fclose() 关闭文件。这些操作的实现背后,实际上是依赖于操作系统提供的低级系统调用,如 open()read()write()close()这些系统调用直接与操作系统内核进行交互,提供了更精细的控制。

通过对比系统调用与标准库函数的使用场景,我们可以更清楚地理解它们各自的优势和适用范围。标准库函数封装了底层细节,适合一般的文件操作,而系统调用则提供了更低层次、更精细的操作,适合需要高性能和底层控制的场景。


以上就是【文件操作的艺术——从基础到精通】的全部内容,欢迎指正~ 

码文不易,还请多多关注支持,这是我持续创作的最大动力!  

相关文章:

【Linux】文件操作的艺术——从基础到精通

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da;前言&#xff1a;一切皆文件 &#x1f4da;一、C语言的文件接口 &#x1f4d6;1.文件打…...

java中的运算符

大家好&#xff0c;今天来看看java中运算符的一些知识点&#xff0c;理解好运算符是我们在写代码的一大重点&#xff0c;那么我们就来看看吧。 运算符:对操作数进行操作时的符号.,不同运算筹操作的含义不同. 一、算术算片. 1、基本四则运算符:加减乘除模(一*/%) 注意:都是二元…...

全面解析 C++ STL 中的 set 和 map

C 标准模板库&#xff08;STL&#xff09;中的关联式容器以其强大的功能和高效性成为开发者解决复杂数据组织问题的重要工具。其中&#xff0c;set 和 map 是最常用的两类关联容器。本篇博客将从基本特性、底层实现、用法详解、高级案例以及性能优化等多个角度&#xff0c;详细…...

css:怎么设置div背景图的透明度为0.6不影响内部元素

目录 1.前言 2.解决思路 3.具体实例 4.另外一种实例 5.总结 1.前言 div背景图为project-bg.png&#xff0c;设置div透明度为0.6&#xff1b;div内的名称、数值受透明度影响颜色显示不正常&#xff1b;怎么设置背景图的透明度为0.6不影响内部元素&#xff1b; 2.解决思路 …...

Kubernetes ConfigMaps

文章目录 简介创建ConfigMaps通过命令行使用字面值创建 ConfigMap。从文件创建ConfigMaps从多个文件创建 ConfigMap从目录创建 ConfigMap使用 YAML 创建 ConfigMap 使用ConfigMaps使用 ConfigMaps作为环境变量使用 ConfigMap 作为卷挂载使用 ConfigMap 中的特定的key ConfigMap…...

前端热门面试题目[一](HTML、CSS、Javascript、Node、Vue、React)

如何设计一个前端页面&#xff0c;实现PC端访问展示Web应用&#xff0c;移动端访问展示H5应用&#xff1f; 为了实现这一功能&#xff0c;通常需要使用响应式设计或者服务器端检测用户设备并返回相应的页面。以下是一些实现方法&#xff1a; 响应式设计&#xff1a;通过CSS媒…...

Swift 宏(Macro)入门趣谈(五)

概述 苹果在去年 WWDC 23 中就为 Swift 语言新增了“其利断金”的重要小伙伴 Swift 宏&#xff08;Swift Macro&#xff09;。为此&#xff0c;苹果特地用 2 段视频&#xff08;入门和进阶&#xff09;颇为隆重的介绍了它。 那么到底 Swift 宏是什么&#xff1f;有什么用&…...

ES6 Set、Map、WeakSet、WeakMap 四者辨析与实战应用详解

在 ES6 中,Set 和 Map 是两种非常重要的新增数据结构,它们都具有独特的特性和用途,能够帮助开发者更高效地处理和管理数据。除此之外,WeakSet 和 WeakMap 作为这两种数据结构的变种,也具有一些特殊的功能。下面我会从 Set 数据结构、Map 数据结构、WeakSet 和 WeakMap 对比…...

【数据结构】哈希表实现

前言 在本篇博客中&#xff0c;作者将会带领你使用C语言来实现一个哈希表。 一.什么是哈希表 在实现哈希表之前&#xff0c;我们先来学习一下什么是哈希表。 在传统的数据结构中&#xff0c;例如数组&#xff0c;链表和二叉平衡树等数据结构&#xff0c;这些数据结构的元素关键…...

Verilog的线与类型与实例化模块

1、线与类型 在Verilog中&#xff0c;线与&#xff08;wire-AND&#xff09;类型通常用于描述多个信号进行逻辑与&#xff08;AND&#xff09;操作的电路行为。虽然Verilog本身没有直接定义一种名为“线与”的数据类型&#xff0c;但可以通过使用wire类型结合特定的逻辑操作来…...

芯片测试-RF中的S参数,return loss, VSWR,反射系数,插入损耗,隔离度等

RF中的S参数&#xff0c;return loss, VSWR&#xff0c;反射系数&#xff0c;插入损耗&#xff0c;隔离度 &#x1f4a2;S参数&#x1f4a2;&#x1f4a2;S11与return loss&#xff0c;VSWR&#xff0c;反射系数&#x1f4a2;&#x1f4a2;S21&#xff0c;插入损耗和增益&#…...

强化学习的几个主要方法(策略梯度、PPO、REINFORCE实现等)(上)

本笔记有大量参考蘑菇书EasyRL https://datawhalechina.github.io/easy-rl/#/ 包括其配图和部分文本。 1. 基本概念 1.1 基本流程 强化学习是一种学习框架&#xff0c;其中智能体&#xff08;Agent&#xff09; 通过与 环境&#xff08;Environment&#xff09; 的交互&#…...

Git远程仓库操作

文章目录 远程仓库连接Gitee克隆代码 多人协同问题说明 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Git专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月1日13点10分 远程仓库 Git 是分布式版本控制系统&#xff0c;同一个 Git …...

GAGAvatar: Generalizable and Animatable Gaussian Head Avatar 学习笔记

1 Overall GAGAvatar&#xff08;Generalizable and Animatable Gaussian Avatar&#xff09;&#xff0c;一种面向单张图片驱动的可动画化头部头像重建的方法&#xff0c;解决了现有方法在渲染效率和泛化能力上的局限。 旋转参数 现有方法的局限性&#xff1a; 基于NeRF的方…...

什么是VISUAL STUDIO CODE (V S CODE)

Visual Studio Code&#xff08;简称VS Code&#xff09;是由微软开发的一个免费的、开源的源代码编辑器。它是一个轻量级但功能强大的工具&#xff0c;支持多种编程语言和框架&#xff0c;广泛用于开发各种应用程序&#xff0c;尤其是Web开发。VS Code具备以下特点&#xff1a…...

2024年09月中国电子学会青少年软件编程(Python)等级考试试卷(三级)答案 + 解析

青少年软件编程(Python)等级考试试卷(三级) 分数:100 题数:38 一、单选题(共25题,共50分) 1. 以下表达式的值为True的是?( ) A. all( ,1,2,3) B. any([]) C. bool(abc) D. divmod(6,0)...

C++初阶——动态内存管理

目录 1、C/C内存区域划分 2、C动态内存管理&#xff1a;malloc/calloc/realloc/free 3、C动态内存管理&#xff1a;new/delete 3.1 new/delete内置类型 3.2 new/delete自定义类型 4、operator new与operator delete函数 5、new和delete的实现原理 5.1 内置类型 5.2 自定…...

如何查看阿里云ddos供给量

要查看阿里云上的 DDoS 攻击量&#xff0c;你可以通过阿里云的 云盾 DDoS 防护 服务来进行监控和查看攻击数据。阿里云提供了详细的流量监控、攻击日志以及攻击趋势分析工具&#xff0c;帮助用户实时了解 DDoS 攻击的情况。以下是九河云总结的查看 DDoS 攻击量的步骤&#xff1…...

MySQL中的事务隔离全详解

第一部分&#xff1a;MySQL事务的特性与并行事务引发的问题 1. 什么是事务及其四大特性&#xff08;ACID&#xff09;&#xff1f; 事务&#xff08;Transaction&#xff09;是数据库操作的基本单位&#xff0c;它将一组操作组合在一起&#xff0c;以确保这些操作作为一个整体…...

异常--C++

文章目录 一、异常的概念及使用1、异常的概念2、异常的抛出和捕获3、栈展开4、查找匹配的处理代码5、异常重新抛出6、异常安全问题7、异常规范 二、标准库的异常 一、异常的概念及使用 1、异常的概念 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并…...

SeggisV1.0 遥感影像分割软件【源代码】讲解

在此基础上进行二次开发&#xff0c;开发自己的软件&#xff0c;例如&#xff1a;【1】无人机及个人私有影像识别【2】离线使用【3】变化监测模型集成【4】个人私有分割模型集成等等&#xff0c;不管是您用来个人学习还是公司研发需求&#xff0c;都相当合适&#xff0c;包您满…...

锁-读写锁-Swift

实现一 pthread_mutex_t&#xff1a; ReadWriteLock/Sources/ReadWriteLock at main SomeRandomiOSDev/ReadWriteLock GitHub https://swiftpackageindex.com/reers/reerkit/1.0.39/documentation/reerkit/readwritelock/ // // Copyright © 2022 reers. // // Pe…...

Kafka如何保证消息可靠?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka如何保证消息可靠&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka如何保证消息可靠&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka通过多种机制来确保消息的可靠性&#xff0c;主要包…...

5.10【机器学习】

如果FLAG的画&#xff0c;就是已经有模型了&#xff0c;不然就新建一个模型&#xff0c;通过TORCH方法 在训练的时候&#xff0c;如果TRAIN的话就是训练&#xff0c;不然就是预测 forward前向预测出来一个结果&#xff0c;就是1234 在train方法里&#xff0c;进行多轮迭代&am…...

[白月黑羽]关于仿写股票数据软件题目的解答

原题&#xff1a; 对应问题视频&#xff1a; 实现的效果 不同点 实现的作品和原题要求的不同点 题目要求爬虫获取数据&#xff0c;作品中是调库获取所有股票历史数据实时数据使用爬虫的方式爬取指定股票的数据&#xff0c;需要实时更新&#xff0c;我做了修改&#xff0c;改…...

详解LZ4文件解压缩问题

详解LZ4文件解压缩问题 一、LZ4文件解压缩方法1. 使用LZ4命令行工具2. 使用Python库3. 使用第三方工具4. 在线解压工具 二、常见问题及解决方法1. 解压显示文件损坏2. 解压后文件大小异常 三、总结 LZ4是一种快速的压缩算法&#xff0c;广泛应用于需要实时压缩和解压缩大文件的…...

vue项目中单独文件的js不存在this.$store?.state怎么办

在Vue项目中&#xff0c;如果你在单独的文件&#xff08;比如插件、工具函数等&#xff09;中遇到this.$store不存在的情况&#xff0c;这通常是因为this上下文不指向Vue实例&#xff0c;或者Vuex store没有被正确地注入到Vue实例中。以下是几种可能的解决方案&#xff1a; 确保…...

Github提交Pull Request教程 Git基础扫盲(零基础易懂)

1 PR是什么&#xff1f; PR&#xff0c;全称Pull Request&#xff08;拉取请求&#xff09;&#xff0c;是一种非常重要的协作机制&#xff0c;它是 Git 和 GitHub 等代码托管平台中常见的功能&#xff0c;被广泛用于参与社区贡献&#xff0c;从而促进项目的发展。 PR的整个过…...

Java函数式编程【二】【Stream的装饰】【中间操作】【map映射器】【摊平映射器flatMap】

一、Java的Stream流式编程中的中间操作 Java的Stream流式编程中&#xff0c;中间操作是对数据流进行处理的一种方式&#xff0c;这些操作通常返回流对象本身&#xff0c;以便可以链接更多的操作。以下是一些常见的中间操作&#xff1a; filter(Predicate predicate) - 用于通过…...

树莓派明明安装了opencv和numpy,却找不到

当然不止树莓派&#xff0c;配置python环境都可能存在这个问题 可能是因为安装的 numpy 或者 opencv 版本与 Python 的包路径不匹配。下面是问题的常见原因及解决方法&#xff1a;【方法一和二优先考虑】 原因分析 多版本 Python 环境冲突&#xff1a; 树莓派上可能有多个版本…...

wordpress插件样式/种子搜索引擎

10月26日&#xff0c;锐捷网络在京发布最新网络威胁治理解决方案&#xff0c;并正式推出大数据安全平台RG-BDS。作为中国数据通信解决方案领导品牌&#xff0c;锐捷网络近年来在深入扎根行业的基础上&#xff0c;陆续推出了大量贴近用户应用场景的解决方案&#xff0c;以及可支…...

旅游网页设计成品免费下载/优化网站排名

最近在项目中需要Postgresql在新增数据后返回自增的ID&#xff0c;特此记录便于日后查阅。 <insert id"copyMainGroup" parameterType"com.openailab.oascloud.common.model.tcm.TrainingGroupBO"><selectKey resultType"java.lang.Integer…...

新开传奇网站180火龙/免费申请网站

给定一个 nnnnnn 的 010101 矩阵。 你可以选择若干列&#xff08;也可以不选&#xff09;&#xff0c;并将这些列上的所有元素进行变换&#xff08;111 变 000&#xff0c;000 变 111&#xff09;。 你的目标是使得矩阵中有尽可能多的行满足&#xff1a;一行中的所有元素都为…...

微3g网站/关键词排名网络推广

[ 用大白话讲解复杂的技术 ]这是我的第41篇原创文章作者 l 会点代码的大叔(CodeDaShu)今天&#xff0c;我们来聊聊 Java 的注解。01注解的概念Annotation(注解)&#xff1a;先看看官方给出的概念&#xff0c;注解是 Java 提供的一种对元程序中元素关联信息和元数据的途径和方法…...

chatgpt 网址/广州seo优化推广

0. 简述 Flask-WTF 提供 FileField 来处理文件上传&#xff0c;它在表单提交后&#xff0c;自动从 flask.request.files 中抽取数据。FileField 的 data 属性是一个 Werkzeug FileStorage 实例。 1. 表单文件forms.py class UploadForm(FlaskForm):"""用户上传…...

网站创建app/百度竞价广告怎么投放

0.随笔摘要&#xff1a; MongoDB 安装配置MongoDB 权限控制MongoDB 注意事项 authentication failed1.MongoDB 下载安装配置 MongoDB官网 https://www.mongodb.com/ 下载安装包&#xff0c; 直接next next安装即可&#xff0c;可自行选择安装路径。 在MongoDB安装路劲的bi…...