【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()这些系统调用直接与操作系统内核进行交互,提供了更精细的控制。

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


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

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 声音:数字音频、语音识别、TTS 简介与使用示例

在现代 AI 技术的推动下&#xff0c;声音处理领域取得了巨大进展。从语音识别&#xff08;ASR&#xff09;到文本转语音&#xff08;TTS&#xff09;&#xff0c;再到个性化声音克隆&#xff0c;这些技术已经深入到我们的日常生活中&#xff1a;语音助手、自动字幕生成、语音导…

IDEA连接Apifox客户端

IDEA连接Apifox客户端 一、下载Apifox安装包二、IDEA配置三、配置Apifox和IDEA项目同步 一、下载Apifox安装包 Apifox官网&#xff0c;根据自己的操作系统下载对应的Apifox安装包&#xff0c;我是windows系统所以下载的是windows版。 下载 默认仅为我安装&#xff0c;点击下一…

Vue3 脚手架扩展

当 yarn dev 运行成功后&#xff0c;我们继续添加扩展 首先我们要安装一些依赖 其中的vue-router和vuex安装最新版的就行&#xff0c;因为项目是vue3 element-plus和less&#xff0c;less-loader最好按照我这个版本来下载 element-plus是一个vue常用的ui组件库 element-plus/…

STM32 ADC模数转换器原理及单通道多通道测量电压模板代码

ADC简介&#xff1a; &#xff08;主要用来测电压&#xff09; 1us转换时间&#xff08;最大支持1MHZ的信号转换&#xff09; 12位&#xff08;0~4095&#xff09;就是分辨率 通过ADC0809外挂芯片来理解STM32中的ADC&#xff1a; 地址锁存和译码是用来选择通路的&#xff0c;…

Android矩阵Matrix实现Glide图像fitCenter转换为centerCrop,Kotlin

Android矩阵Matrix实现Glide图像fitCenter转换为centerCrop&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.a…

电子电气架构 -- 新的架构带来的软件革命

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 所谓鸡汤&#xff0c;要么蛊惑你认命&#xff0c;要么怂恿你拼命&#xff0c;但都是回避问题的根源&…

后端 Java发送邮件 JavaMail 模版 20241128测试可用

配置授权码 依赖 <dependency><groupId>javax.mail</groupId><artifactId>javax.mail-api</artifactId><version>1.5.5</version> </dependency> <dependency><groupId>com.sun.mail</groupId><artifa…

【零基础学习UDS诊断测试】——0x10测试用例设计

从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者,时光不负有心人。 目录 1.概述 2.三个会话介绍 3.会话切换逻辑 4.会话响应格式 5.解析测试点 5.1. 0x10 5.1.1 具体用例设计 5.1.1.1 NRC否定响应码 6.详细用例展示 1.概述 主要基于诊断调查表介…

【Robocasa】Code Review

文章目录 OverviewalgoInitializationImportant Class MethodsTrain LoopTest Time ConfigsdemoConfig FactoryConfig StructureConfig Locking默认锁定状态配置修改的上下文管理器 dataset示例数据集对象参数说明 model基础模块EncoderCoreVisualCoreScanCore随机化器 (Random…

阅读笔记--知识蒸馏

1.一些基本概念 教师模型&#xff08;Teacher Model&#xff09;&#xff1a;预训练复杂神经网络&#xff0c;高精度&#xff0c;计算存储开销大。学生模型&#xff08;Student Model&#xff09;&#xff1a;简单参数少推理快的模型&#xff0c;目标从教师模型获取知识&#…

【Maven Helper】分析依赖冲突案例

目录 Maven Helper实际案例java文件pom.xml文件运行抛出异常分析 参考资料 《咏鹅》骆宾王 鹅&#xff0c;鹅&#xff0c;鹅&#xff0c;曲项向天歌。 白毛浮绿水&#xff0c;红掌拨清波。 骆宾王是在自己7岁的时候就写下了这首杂言 Maven Helper A must have plugin for wor…

一些基于宏基因组的巨型病毒研究

Introduction 上次已经介绍了巨型病毒的一些基本内容&#xff0c;也讲到了不依赖培养的方法是从环境样本中发现巨型病毒基因组成的不可或缺的工具。可以通过基因组解析宏基因组学来从环境序列数据中获取 NCLDV 基因组并进行深入研究如功能基因&#xff0c;宿主&#xff0c;进化…

李宏毅深度强化学习入门笔记:Actor-Critic

李宏毅-深度强化学习-入门笔记&#xff1a;Actor-Critic 一、深度强化学习简介二、Policy-based 方法&#xff08;一&#xff09;学习一个 Actor&#xff08;二&#xff09;Deep Learning 的 3 个步骤1. 确定 Function&#xff1a;作为 Actor 的神经网络2. 确定 Actor 的好坏3.…

基于Java Springboot成人教育APP且微信小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信…

知乎启用AutoMQ替换Kafka,开辟成本优化与运维提效新纪元

作者&#xff1a;知乎在线架构组 王金龙 关于知乎 知乎公司&#xff0c;成立于 2010 年 8 月 10 日&#xff0c;于 2011 年 1 月 26 日正式上线&#xff0c;是中文互联网的高质量问答社区和创作者聚集的原创内容平台。 知乎起步于问答&#xff0c;而超越了问答。知乎以「生…

mysql数据库varchar截断问题

用了这么多年mysql数据库&#xff0c;才发现varchar是可以截断的&#xff0c;而且是在我们线上数据库。个人觉得dba的这个设置是非常有问题的&#xff0c;用户往数据库里存东西&#xff0c;就是为了以后用的&#xff0c;截断了存放&#xff0c;数据不完整&#xff0c;就用不了了…

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

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

MySQL底层概述—9.ACID与事务

大纲 1.ACID之原子性 2.ACID之持久性 3.ACID之隔离性 4.ACID之一致性 5.ACID的关系 6.事务控制演进之排队 7.事务控制演进之排它锁 8.事务控制演进之读写锁 9.事务控制演进之MVCC 10.事务隔离级别之隔离级别的类型 11.事务隔离级别之和锁的关系 12.事务隔离级别之隔…

基于 SpringBoot 的新冠密接者跟踪系统:如何实现高效信息推送功能

第2章 程序开发技术 2.1 Mysql数据库 为了更容易理解Mysql数据库&#xff0c;接下来就对其具备的主要特征进行描述。 &#xff08;1&#xff09;首选Mysql数据库也是为了节省开发资金&#xff0c;因为网络上对Mysql的源码都已进行了公开展示&#xff0c;开发者根据程序开发需要…

手撸了一个文件传输工具

在日常的开发与运维中&#xff0c;文件传输工具是不可或缺的利器。无论是跨服务器传递配置文件&#xff0c;还是快速从一台机器下载日志文件&#xff0c;一个高效、可靠且简单的文件传输工具能够显著提高工作效率。今天&#xff0c;我想分享我自己手撸一个文件传输工具的全过程…