Linux下文件操作相关接口

news/2025/1/9 15:51:39 标签: linux, 运维, 服务器, c语言, c++, 后端

文章目录

    • 一 文件是什么
        • 普通数据文件
    • 二 文件是谁打开的
      • 进程
      • 用户
    • 三 进程打开文件的相关的接口
      • c语言标准库相关文件接口
        • 1. `fopen` 函数
        • 2. `fread` 函数
        • 3. `fwrite` 函数
        • 4. `fclose` 函数
        • 5. `fseek` 函数
      • linux系统调用接口
        • 1. `open` 系统调用
        • 2. `creat` 系统调用
        • 3. `read` 系统调用
        • 4. `write` 系统调用
        • 5. `close` 系统调用
      • 系统调用接口和C标准库接口的关系:
        • 联系
        • 区别
      • 四 进程和文件的关系
        • task_struct 结构体
        • files_struct 结构体
        • 进程与文件关系的整体体现

在 Linux 系统中 “一切皆文件”
它意味着系统中的各种资源,无论是普通的文本文件、二进制文件这样的常规数据存储形式,还是硬件设备(如硬盘、键盘、鼠标、打印机等)、系统中的各种进程、网络套接字、管道等,都可以被抽象地看作是文件,并通过统一的文件操作接口(如 open、read、write、close 等函数)来进行访问和管理

在这里插入图片描述

一 文件是什么

普通数据文件
  • 文本文件
    由一系列可被人类直接阅读的字符按照特定编码(如ASCII码、UTF-8等)组成,像 .txt 文件、程序源代码文件(如 .c.java 等)、配置文件(如 .conf.ini 等)都属于此类。可以使用文本编辑器(如 Vimgedit 等)打开查看并编辑其内容,在存储上是以字符对应的编码字节依次排列存储在磁盘等介质上。
  • 二进制文件
    以二进制编码形式存储数据,内容无法直接通过文本形式读懂,像可执行程序(无扩展名或者有特定扩展名的可执行文件,如 .out 等)、图像文件(如 .jpg.png 等)、音频文件(如 .mp3.wav 等)、视频文件(如 .mp4.avi 等)都属于二进制文件。它们需要借助相应的软件来解析和处理,例如通过图像查看器查看图像文件内容,利用音频播放器播放音频文件等,其在磁盘上是按照相应的二进制数据格式规范进行存储,存储结构相对复杂,与具体的文件类型所要求的编码格式紧密相关。
    在这里插入图片描述

二 文件是谁打开的

在Linux系统中,文件通常由以下几种主体来打开:

进程

  • 原理
    进程是正在运行的程序的实例,当一个进程需要访问文件中的数据,或者要向文件写入数据等操作时,它会通过系统调用(如 open 系统调用)来打开文件。在执行 open 调用时,进程需要指定文件名以及打开的模式(例如只读模式 O_RDONLY、只写模式 O_WRONLY、读写模式 O_RDWR 等,还可以结合一些其他标志位来指定更详细的打开特性,比如是否创建新文件、是否追加数据等)。内核收到进程的 open 请求后,会根据指定的信息查找对应的文件(如果存在),进行权限验证等一系列操作,若一切顺利则返回一个文件描述符(一个非负整数)给进程,之后进程就可以凭借这个文件描述符通过其他系统调用(如 readwriteclose 等)来对文件进行读写操作以及最终关闭文件的操作。
  • 示例
    比如一个简单的C语言程序,要读取一个文本文件中的内容,代码示例如下:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    char buffer[100];
    // 使用open系统调用打开文件,这里假设文件名为test.txt,以只读模式打开
    fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
        perror("open error");
        return 1;
    }
    // 使用read系统调用读取文件内容到buffer中
    ssize_t bytesRead = read(fd, buffer, sizeof(buffer));
    if (bytesRead == -1) {
        perror("read error");
        close(fd);
        return 1;
    }
    // 对读取到的内容可以进行相应处理,这里简单打印出来
    buffer[bytesRead] = '\0';
    printf("Read content: %s", buffer);
    // 使用close系统调用关闭文件
    close(fd);
    return 0;
}

在这个示例中,就是由 main 这个进程通过 open 系统调用打开名为 test.txt 的文件,后续进行读取和关闭等操作。

用户

  • 命令行交互场景下
    当用户在终端输入命令来操作文件时,实际上也是间接通过相关进程来打开文件的。例如,用户输入 cat test.txt 命令(cat 命令用于查看文件内容),此时系统会启动一个新的进程来执行 cat 命令,这个进程内部会调用 open 等相关系统调用去打开 test.txt 文件,然后读取并输出文件内容到终端,最后关闭文件。同样,像用户使用 vim 编辑器打开一个文件进行编辑时,vim 程序启动相应的进程,该进程会打开指定的文件,让用户可以在编辑器界面中对文件内容进行修改等操作,完成编辑后关闭文件。
  • 图形界面环境下
    在Linux的图形界面中,当用户通过文件管理器(如 Nautilus 等)双击打开一个文件时,文件管理器背后对应的进程会根据文件类型调用相应的程序来打开文件。比如双击打开一个 .jpg 图像文件,文件管理器会启动一个图像查看程序对应的进程(如 eog 等),这个图像查看程序的进程会打开该图像文件进行显示,完成查看后关闭文件。

在这里插入图片描述

三 进程打开文件的相关的接口

c语言标准库相关文件接口

1. fopen 函数
  • 功能
    用于打开一个文件,并返回一个指向该文件的文件指针(FILE * 类型),后续可通过这个指针来调用其他函数对文件进行读写等操作。它相较于前面提到的系统调用层面的 open 接口,在使用上更加方便、灵活,提供了一种更符合C语言风格的文件操作方式。
  • 头文件及原型
    <stdio.h> 头文件中定义,原型如下:
FILE *fopen(const char *filename, const char *mode);

其中,filename 是要打开的文件的名称(可以是相对路径或绝对路径),mode 是打开文件的模式字符串,常见的模式有:
- "r":以只读方式打开文件,文件必须存在,用于读取文件内容。
- "w":以只写方式打开文件,如果文件存在则清空文件内容,如果文件不存在则创建新文件,用于写入数据。
- "a":以追加方式打开文件,如果文件存在,则新写入的数据将追加到文件末尾,若文件不存在则创建新文件,常用于在已有文件后添加新内容。
- "r+":以读写方式打开文件,文件必须存在,可同时进行读取和写入操作。
- "w+":以读写方式打开文件,若文件存在则清空内容后可读写,若不存在则创建新文件,可先写入再读取或者反之。
- "a+":以读写方式打开文件,若文件存在则可在末尾追加内容并读取,若不存在则创建新文件,允许边追加边读取。

  • 示例代码
#include <stdio.h>

int main() {
    FILE *fp;
    // 以只读方式打开名为test.txt的文件
    fp = fopen("test.txt", "r");
    if (fp == NULL) {
        perror("fopen error");
        return 1;
    }
    // 后续可以使用fread、fwrite等函数对文件进行读写操作,这里暂不展示
    // 使用fclose函数关闭文件
    fclose(fp);
    return 0;
}
2. fread 函数
  • 功能
    从指定的文件指针所指向的文件中读取数据到给定的缓冲区中,常用于读取二进制文件或者文本文件中的数据块。
  • 头文件及原型
    <stdio.h> 头文件中定义,原型如下:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

其中,ptr 是指向接收数据的缓冲区的指针(通常是一个数组等);size 是每个数据元素的大小(单位为字节);nmemb 是要读取的数据元素的数量;stream 就是通过 fopen 打开文件所获得的文件指针。函数返回实际读取的数据元素数量,如果返回值小于 nmemb,可能表示读到文件末尾或者出现了读取错误等情况。

  • 示例代码
#include <stdio.h>

int main() {
    FILE *fp;
    char buffer[100];
    // 以只读方式打开名为test.txt的文件
    fp = fopen("test.txt", "r");
    if (fp == NULL) {
        perror("fopen error");
        return 1;
    }
    // 从文件中读取数据,每次读取1个字节,最多读取100次(即最多读取100字节)
    size_t elementsRead = fread(buffer, 1, 100, fp);
    if (elementsRead < 100) {
        if (feof(fp)) {
            printf("Reached end of file.\n");
        } else {
            perror("fread error");
        }
    }
    buffer[elementsRead] = '\0';
    printf("Read content: %s", buffer);
    fclose(fp);
    return 0;
}
3. fwrite 函数
  • 功能
    向指定的文件指针所指向的文件中写入数据,常用于将数据保存到二进制文件或者向文本文件中添加内容等情况。
  • 头文件及原型
    <stdio.h> 头文件中,原型如下:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

其中,ptr 是指向要写入数据的缓冲区的指针(例如包含要写入数据的数组等);size 是每个数据元素的大小(单位为字节);nmemb 是要写入的数据元素的数量;stream 是文件指针。函数返回实际写入的数据元素数量,如果返回值小于 nmemb,可能表示出现写入错误等情况。

  • 示例代码
#include <stdio.h>

int main() {
    FILE *fp;
    char data[] = "Hello, World!";
    // 以只写方式打开名为test.txt的文件
    fp = fopen("test.txt", "w");
    if (fp == NULL) {
        perror("fopen error");
        return 1;
    }
    // 向文件中写入数据,每次写入1个字节,写入数据元素个数为数据长度
    size_t elementsWritten = fwrite(data, 1, sizeof(data), fp);
    if (elementsWritten < sizeof(data)) {
        perror("fwrite error");
    } else {
        printf("Written %zu bytes to the file.\n", elementsWritten);
    }
    fclose(fp);
    return 0;
}
4. fclose 函数
  • 功能
    关闭由 fopen 函数打开的文件,释放相关的文件资源,避免出现文件资源泄露等问题。
  • 头文件及原型
    <stdio.h> 头文件中定义,原型为:
int fclose(FILE *fp);

其中,fp 是要关闭的文件的文件指针,返回值为0表示关闭成功,返回非零值表示关闭出现错误,不过通常返回 EOF(在 <stdio.h> 中定义,值通常为 -1)来表示关闭失败的情况。

  • 示例代码
    在前面 fopenfreadfwrite 等函数使用示例中,最后都需要使用 fclose 函数来关闭文件,如:
FILE *fp;
// 打开文件等操作......
// 关闭文件
fclose(fp);
5. fseek 函数
  • 功能
    用于移动文件指针到指定的位置,以便从新的位置开始进行读写操作,可以实现对文件的随机读写。通过指定偏移量和相对位置(如相对于文件开头、当前位置、文件末尾等)来精准定位文件指针。
  • 头文件及原型
    <stdio.h> 头文件中定义,原型如下:
int fseek(FILE *stream, long offset, int whence);

其中,stream 是文件指针;offset 是要移动的偏移量(以字节为单位),正数表示向文件末尾方向移动,负数表示向文件开头方向移动;whence 规定了偏移量的相对位置,有以下几种取值:
- SEEK_SET:表示相对于文件开头定位,此时 offset 就是绝对的偏移量,从文件开头开始计算移动的距离。
- SEEK_CUR:表示相对于文件当前位置定位,移动后的位置是在当前文件指针位置基础上加上 offset 的值。
- SEEK_END:表示相对于文件末尾定位,移动后的位置是在文件末尾基础上加上 offset 的值(通常 offset 为负数用于从文件末尾往前移动)。
返回值为0表示移动成功,返回非零值表示移动失败。

  • 示例代码
#include <stdio.h>

int main() {
    FILE *fp;
    char buffer[100];
    // 以只读方式打开名为test.txt的文件
    fp = fopen("test.txt", "r");
    if (fp == NULL) {
        perror("fopen error");
        return 1;
    }
    // 先读取部分文件内容
    fread(buffer, 1, 50, fp);
    // 将文件指针移动到文件开头后20字节的位置
    if (fseek(fp, 20, SEEK_SET) == 0) {
        // 从新位置再读取部分内容
        fread(buffer, 1, 30, fp);
        buffer[30] = '\0';
        printf("Read content from new position: %s", buffer);
    } else {
        perror("fseek error");
    }
    fclose(fp);
    return 0;
}

linux_230">linux系统调用接口

1. open 系统调用
  • 功能:用于打开或创建一个文件,并返回对应的文件描述符,后续进程便可基于这个文件描述符对文件进行读写等操作。
  • 头文件及原型
    它位于 <fcntl.h> 头文件中,原型如下:
#include <fcntl.h>

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

其中,pathname 是要打开或创建的文件的路径名(可以是相对路径也可以是绝对路径);flags 是一组控制文件打开方式的标志位,常用的标志位如下:
- O_RDONLY:以只读方式打开文件,进程只能从文件中读取数据。
- O_WRONLY:以只写方式打开文件,进程只能向文件写入数据。
- O_RDWR:以读写方式打开文件,进程既能读取又能写入文件数据。
- O_CREAT:如果文件不存在,则创建该文件。需要和 mode 参数一起使用(当使用第二个函数原型时)来指定创建文件时的初始权限。
- O_APPEND:以追加方式打开文件,每次写入操作都会将数据追加到文件末尾,而不会覆盖已有内容。
- O_TRUNC:如果文件已经存在,并且以可写方式打开(如 O_WRONLYO_RDWR 且配合 O_CREAT 等情况),则会截断文件,即将文件长度设置为0,清除原有内容。
mode(仅在使用第二个函数原型且带 O_CREAT 标志时需要)用于指定创建文件时的权限模式,例如 S_IRUSR(文件所有者可读权限)、S_IWUSR(文件所有者可写权限)、S_IXUSR(文件所有者可执行权限)等权限宏可以组合使用,常见的组合如 0644(表示所有者可读可写,同组用户和其他用户可读)等。

  • 示例代码
    以下是一个简单的C语言代码示例,展示如何使用 open 系统调用打开文件:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    // 尝试打开名为test.txt的文件,以只读方式打开
    fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
        perror("open error");
        return 1;
    }
    // 这里可以继续使用read等系统调用读取文件内容等操作,后续再关闭文件
    close(fd);
    return 0;
}
2. creat 系统调用
  • 功能:专门用于创建一个新文件,如果文件已经存在,则会截断它(将文件内容清空),并返回对应的文件描述符。实际上,在现代Linux编程中,使用 open 系统调用结合 O_CREATO_TRUNC 标志位基本可以替代 creat 的功能,但它依然存在于系统中供一些旧代码或特定场景使用。
  • 头文件及原型
    位于 <fcntl.h> 头文件中,原型为:
#include <fcntl.h>

int creat(const char *pathname, mode_t mode);

其中参数含义和 open 系统调用中相关参数类似,pathname 是文件路径名,mode 用于指定创建文件的初始权限。

  • 示例代码
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    // 创建一个名为new_file.txt的新文件,初始权限设置为0644(所有者可读可写,同组用户和其他用户可读)
    fd = creat("new_file.txt", 0644);
    if (fd == -1) {
        perror("creat error");
        return 1;
    }
    close(fd);
    return 0;
}
3. read 系统调用
  • 功能:从已打开的文件中读取数据到指定的缓冲区中,返回实际读取到的字节数。
  • 头文件及原型
    位于 <unistd.h> 头文件中,原型如下:
#include <unistd.h>

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

其中,fd 是之前通过 open 等系统调用打开文件所获得的文件描述符;buf 是指向接收数据的缓冲区的指针(通常是一个字符数组等);count 是期望读取的字节数,但实际读取的字节数可能小于这个值,比如读到文件末尾等情况时,返回值为0,表示已读到文件末尾,如果返回 -1,则表示读取过程出现错误。

  • 示例代码
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    char buffer[100];
    ssize_t bytesRead;
    // 打开名为test.txt的文件,以只读方式打开
    fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
        perror("open error");
        return 1;
    }
    // 从文件中读取数据到buffer中,最多读取100字节
    bytesRead = read(fd, buffer, sizeof(buffer));
    if (bytesRead == -1) {
        perror("read error");
        close(fd);
        return 1;
    }
    buffer[bytesRead] = '\0';
    printf("Read content: %s", buffer);
    close(fd);
    return 0;
}
4. write 系统调用
  • 功能:向已打开的文件中写入数据,返回实际写入文件的字节数。
  • 头文件及原型
    位于 <unistd.h> 头文件中,原型如下:
#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

其中,fd 是文件描述符,buf 是指向要写入数据的缓冲区的指针(例如包含要写入的字符数组等),count 是期望写入的字节数,实际写入字节数可能小于 count,比如磁盘空间不足等情况,返回 -1 表示写入过程出现错误。

  • 示例代码
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd;
    char data[] = "Hello, World!";
    // 打开名为test.txt的文件,以只写方式打开
    fd = open("test.txt", O_WRONLY);
    if (fd == -1) {
        perror("open error");
        return 1;
    }
    // 向文件中写入数据
    ssize_t bytesWritten = write(fd, data, sizeof(data));
    if (bytesWritten == -1) {
        perror("write error");
        close(fd);
        return 1;
    }
    printf("Written %zd bytes to the file.", bytesWritten);
    close(fd);
    return 0;
}
5. close 系统调用
  • 功能:关闭之前由进程打开的文件,释放相关的系统资源,如文件描述符等。
  • 头文件及原型
    位于 <unistd.h> 头文件中,原型为:
#include <unistd.h>

int close(int fd);

其中,fd 是要关闭的文件的文件描述符,返回值为0表示关闭成功,返回 -1 表示关闭过程出现错误。

  • 示例代码
    通常在使用 open 等系统调用打开文件并完成相应读写操作后,就需要使用 close 来关闭文件,示例代码可参考前面 openreadwrite 等系统调用示例中都包含的关闭文件操作部分,如:
int fd;
// 打开文件等操作......
// 关闭文件
close(fd);

系统调用接口和C标准库接口的关系:

联系
  • 基于实现:C标准库中的许多接口(如文件操作相关的 fopenfread 等)底层基于系统调用接口(如 openread 等)实现,对其进行封装和优化,使其更易用。
  • 功能目的:都旨在方便程序员操作文件及其他系统资源,只是所处层次不同,常相互协作来完成复杂功能。
区别
  • 抽象层次:系统调用接口接近底层,与内核直接交互,需关注更多细节;C标准库接口抽象程度更高,使用更简便,隐藏了底层机制。
  • 可移植性:系统调用接口因操作系统差异导致可移植性差;C标准库接口基于C语言标准,在不同平台使用方式较一致,可移植性较好。
  • 功能覆盖范围:系统调用接口涵盖操作系统内核全方位功能;C标准库接口侧重常用功能封装,范围相对窄些。
  • 错误处理方式:系统调用接口返回特定错误码,需结合特定函数分析错误;C标准库接口多通过返回特殊值及全局变量辅助判断错误,更简化统一。
    在这里插入图片描述

四 进程和文件的关系

在Linux操作系统中,task_structfile_struct 这两个结构体对于理解进程和文件之间的关系起着关键作用,以下是对它们的详细介绍:

task_struct 结构体
  • 含义与作用
    task_struct 是Linux内核中用于描述进程的核心结构体,它包含了进程运行过程中几乎所有的相关信息,相当于进程在内核中的“身份证”,从进程的基本属性(如进程标识符PID、进程的状态等)到资源使用情况(如内存使用情况、打开的文件描述符数量等),再到进程调度相关的信息(如优先级、调度策略等)都涵盖其中。可以说,内核通过对众多 task_struct 结构体的管理来掌控系统中所有进程的运行。
  • 与文件相关的体现
    task_struct 结构体中,有一个成员指针指向 files_struct 结构体(通常表示为 files 成员),这建立起了进程与文件之间的一种间接关联。通过这个指针,进程可以访问到其对应的 files_struct,进而知晓自身打开了哪些文件以及相关的文件描述符等信息,它是连接进程与文件操作具体情况的一个重要纽带。
    task_struct
files_struct 结构体
  • 含义与作用
    files_struct 主要用于管理进程所打开的文件相关信息,是对进程打开文件情况的一种集中描述。它包含了诸如文件描述符数组(用于存放进程打开文件后获取的文件描述符)、文件打开计数(记录每个文件被打开的次数,便于内核进行资源管理和共享控制等操作)等重要信息,是内核在处理进程文件操作时经常会涉及到的一个关键数据结构。
  • 内部结构与文件关联细节
    • 文件描述符数组:在 files_struct 中有一个数组(通常命名类似 fd_array 等)存放struct file 结构体的指针,进程每通过系统调用(如 open 等)打开一个文件,内核就会在这个数组中分配一个空闲的位置(即一个有效的文件描述符,通常是一个较小的非负整数)来存放该文件对应的相关信息,后续进程就可以凭借这个文件描述符来对文件进行读写等操作(通过 readwrite 等系统调用)。而且不同的进程可以通过各自的 files_struct 中的文件描述符数组来独立地打开和操作同一个文件,内核会根据文件打开计数等机制来协调资源共享和访问控制等事宜。
      fd_arry
      数组元素为file*的指针,指向file结构体
      file结构体如下
      file

    • 文件打开计数:对于每个被打开的文件,files_struct 会记录其被打开的次数,这很重要。例如,当一个进程多次打开同一个文件时,打开计数会相应增加;而当进程关闭该文件(通过 close 系统调用)时,打开计数会减少,只有当打开计数降为0时,内核才会真正释放该文件相关的一些底层资源(如内核缓冲区等),这种机制有助于合理地管理文件资源,避免资源的过早释放或错误释放等问题。

进程与文件关系的整体体现
  • 文件打开过程关联
    进程在启动时默认会打开三个标准流文件,它们分别是标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr),当一个进程想要打开一个文件时,它会通过系统调用(如 open)向内核发起请求,内核在执行 open 操作时,一方面会根据请求查找对应的文件(验证文件是否存在、权限是否匹配等),另一方面会在该进程对应的 files_struct 的文件描述符数组中找到一个空闲位置分配给这个新打开的文件,并返回对应的文件描述符给进程。这个过程中,task_struct 通过指向 files_struct 的指针,使得进程能够“知晓”自己新打开了哪个文件以及后续如何操作它。
  • 文件读写与共享体现
    在文件读写阶段,进程凭借从 files_struct 中获取的文件描述符,通过 readwrite 等系统调用对文件进行读写操作。而且多个进程可以通过各自的 files_struct 中的文件描述符同时打开和读写同一个文件,这就涉及到文件资源的共享。例如,不同的进程可能同时读取一个配置文件,或者一个进程写入、另一个进程读取同一个数据文件等情况,内核借助 files_struct 中的文件打开计数等机制来确保文件数据的一致性以及合理地分配文件读写的权限等资源,而这一切操作的源头都是基于各个进程对应的 task_struct 结构体所关联的 files_struct 来实现的。
  • 文件关闭及资源释放关联
    当进程完成对文件的使用,通过 close 系统调用关闭文件时,内核会根据 files_struct 中记录的文件打开计数来进行相应处理。如果关闭操作使得文件打开计数减为0,那么内核会释放该文件对应的一些资源(如释放相关的内核缓冲区、更新文件的元数据等),并且在 files_struct 中标记该文件描述符对应的位置为空闲状态,以便后续进程打开其他文件时可以再次使用这个位置。整个过程都是围绕着 task_struct 所关联的 files_struct 来有序进行的,确保了文件资源的合理回收和再利用。

总图

在这里插入图片描述

在这里插入图片描述


http://www.niftyadmin.cn/n/5817690.html

相关文章

汽车免拆诊断 | 2017 款东风风神 AX7 车热机后怠速不稳

故障现象 一辆2017款东风风神AX7车&#xff0c;搭载DFMA14T发动机&#xff0c;累计行驶里程约为13.7万km。该车冷起动后怠速运转正常&#xff0c;热机后怠速运转不稳&#xff0c;组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断  用故障检测仪检测&#xff0c;发动机控…

Windows使用AutoHotKey解决鼠标键连击现象(解决鼠标连击、单击变双击的故障)

注&#xff1a;罗技鼠标&#xff0c;使用久了之后会出现连击现象&#xff0c;如果刚好过保了&#xff0c;可以考虑使用软件方案解决连击现象&#xff1a; 以下是示例AutoHotKey脚本&#xff0c;实现了调用XButton1用于关闭窗口&#xff08;以及WinW&#xff0c;XButton2也导向…

前端金额运算精度丢失问题及解决方案

前言 前端开发中难免会遇到价格和金额计算的需求&#xff0c;这类需求所要计算的数值大多数情况下是要求精确到小数点后的多少位。但是因为JS语言本身的缺陷&#xff0c;在处理浮点数的运算时会出现一些奇怪的问题&#xff0c;导致计算不精确。 本文尝试从现象入手&#xff0…

C# 中await和async的用法(一)

在 C# 中&#xff0c;await 关键字用于异步编程&#xff0c;配合 async 方法一起使用。await 允许你等待异步操作完成&#xff0c;而不会阻塞当前线程。简而言之&#xff0c;await 会暂停当前方法的执行&#xff0c;直到任务完成&#xff0c;然后继续执行。 1. await与async的关…

Clojure语言的数据库编程

Clojure语言的数据库编程 引言 在当今社会&#xff0c;数据的处理和管理已经成为一个不可或缺的部分。无论是互联网应用、企业系统还是移动应用&#xff0c;都需要与数据库进行频繁的交互。因此&#xff0c;选择一种合适的编程语言和相应的库来进行数据库编程显得尤为重要。C…

易支付二次元网站源码及部署教程

易支付二次元网站源码及部署教程 引言 在当今数字化时代&#xff0c;二次元文化逐渐成为年轻人生活中不可或缺的一部分。为了满足这一庞大用户群体的需求&#xff0c;搭建一个二次元主题网站显得尤为重要。本文将为您详细介绍易支付二次元网站源码的特点及其部署教程&#xf…

左神算法基础巩固--2

文章目录 稳定性选择排序冒泡排序插入排序归并排序快速排序堆排序 哈希表链表解题 稳定性 稳定性是指算法在排序过程中保持相等元素之间相对顺序的特性。具体来说&#xff0c;如果一个排序算法是稳定的&#xff0c;那么对于任意两个相等的元素&#xff0c;在排序前它们的相对顺…

leetcode 458. 可怜的小猪

题目&#xff1a;458. 可怜的小猪 - 力扣&#xff08;LeetCode&#xff09; 数学问题。 尝试次数 times minutesToTest / minutesToDie 每只猪可以承载的数据量 bit times 1 答案 ret 就是 bit ^ ret > buckets 时&#xff0c;ret 的最小值。 特殊的&#xff0c;注意…