深入C语言文件操作:从库函数到系统调用

news2025/2/27 14:25:16

引言

文件操作是编程中不可或缺的一部分,尤其在C语言中,文件操作不仅是处理数据的基本手段,也是连接程序与外部世界的重要桥梁。C语言提供了丰富的库函数来处理文件,如 fopenfclosefreadfwrite 等。然而,这些库函数实际上是基于操作系统提供的系统调用构建的。理解库函数和系统调用之间的关系,不仅有助于编写高效的代码,还能帮助我们更好地理解底层操作系统的机制。

本文将深入探讨C语言文件操作中的库函数和系统调用,解释它们的工作原理、区别和联系,并通过实际示例展示如何使用这些函数。
在这里插入图片描述

C标准库函数与系统调用概述

6.1 C标准库函数

C标准库函数是ANSI C标准中定义的一组函数,它们提供了一种跨平台的方式来处理文件操作。这些函数通常在 stdio.h 头文件中声明,并且在大多数操作系统中都有实现。常见的文件操作库函数包括:

  • fopen:打开文件。
  • fclose:关闭文件。
  • fread:从文件中读取数据。
  • fwrite:向文件中写入数据。
  • fgetc:从文件中读取一个字符。
  • fputc:向文件中写入一个字符。
  • fgets:从文件中读取一行。
  • fputs:向文件中写入一行。
  • fseek:移动文件指针。
  • ftell:获取文件指针的当前位置。
  • rewind:将文件指针重置到文件开头。

6.2 系统调用

系统调用是操作系统提供给用户程序的一组接口,用于请求操作系统执行特定的低级操作。系统调用通常在内核态执行,提供了对硬件设备的直接访问。常见的文件操作系统调用包括:

  • open:打开文件。
  • close:关闭文件。
  • read:从文件中读取数据。
  • write:向文件中写入数据。
  • lseek:移动文件指针。
  • ioctl:控制设备。

库函数与系统调用的区别

6.3 工作空间不同

  • 库函数:运行在用户态,通常包含在标准库中,如 glibc
  • 系统调用:运行在内核态,由操作系统内核提供。

6.4 缓冲机制不同

  • 库函数:通常使用缓冲机制来提高性能。例如,freadfwrite 会先将数据读取到内存缓冲区,然后再批量处理。
  • 系统调用:不使用缓冲机制,每次调用都会直接与文件系统交互。

6.5 可移植性不同

  • 库函数:具有良好的可移植性,可以在不同的操作系统上使用相同的接口。
  • 系统调用:依赖于特定的操作系统,不同操作系统的系统调用接口可能不同。

6.6 性能差异

  • 库函数:由于使用了缓冲机制,减少了用户态和内核态之间的切换次数,通常性能更高。
  • 系统调用:每次调用都会导致用户态和内核态之间的切换,性能较低。

库函数与系统调用的联系

尽管库函数和系统调用在许多方面有所不同,但它们之间存在着密切的联系。实际上,许多库函数最终会调用系统调用来完成实际的文件操作。

6.7 fopenopen

fopen 函数用于打开文件,并返回一个指向 FILE 结构的指针。fopen 实际上调用了 open 系统调用。

示例代码:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main() {
    // 使用 fopen 打开文件
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
        return 1;
    }

    // 使用 open 系统调用打开文件
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return 1;
    }

    fclose(file);
    close(fd);
    return 0;
}

6.8 freadread

fread 函数用于从文件中读取数据,并返回实际读取的数据项数。fread 实际上调用了 read 系统调用。

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main() {
    // 使用 fopen 打开文件
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
        return 1;
    }

    // 使用 open 系统调用打开文件
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return 1;
    }

    char buffer[100];
    size_t bytes_read;

    // 使用 fread 读取文件
    bytes_read = fread(buffer, 1, sizeof(buffer), file);
    if (ferror(file)) {
        fprintf(stderr, "读取文件失败: %s\n", strerror(errno));
        fclose(file);
        close(fd);
        return 1;
    }
    buffer[bytes_read] = '\0';
    printf("fread: %s\n", buffer);

    // 使用 read 系统调用读取文件
    bytes_read = read(fd, buffer, sizeof(buffer));
    if (bytes_read == -1) {
        perror("读取文件失败");
        close(fd);
        return 1;
    }
    buffer[bytes_read] = '\0';
    printf("read: %s\n", buffer);

    fclose(file);
    close(fd);
    return 0;
}

6.9 fwritewrite

fwrite 函数用于向文件中写入数据,并返回实际写入的数据项数。fwrite 实际上调用了 write 系统调用。

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main() {
    // 使用 fopen 打开文件
    FILE *file = fopen("example.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
        return 1;
    }

    // 使用 open 系统调用打开文件
    int fd = open("example.txt", O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        perror("打开文件失败");
        return 1;
    }

    char *message = "Hello, World!\n";

    // 使用 fwrite 写入文件
    if (fwrite(message, 1, strlen(message), file) != strlen(message)) {
        if (ferror(file)) {
            fprintf(stderr, "写入文件失败: %s\n", strerror(errno));
            fclose(file);
            close(fd);
            return 1;
        }
    }

    // 使用 write 系统调用写入文件
    if (write(fd, message, strlen(message)) == -1) {
        perror("写入文件失败");
        close(fd);
        return 1;
    }

    fclose(file);
    close(fd);
    return 0;
}

6.10 fcloseclose

fclose 函数用于关闭文件,并刷新缓冲区。fclose 实际上调用了 close 系统调用。

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main() {
    // 使用 fopen 打开文件
    FILE *file = fopen("example.txt", "w");
    if (file == NULL) {
        fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
        return 1;
    }

    // 使用 open 系统调用打开文件
    int fd = open("example.txt", O_WRONLY | O_CREAT, 0644);
    if (fd == -1) {
        perror("打开文件失败");
        return 1;
    }

    char *message = "Hello, World!\n";

    // 使用 fwrite 写入文件
    if (fwrite(message, 1, strlen(message), file) != strlen(message)) {
        if (ferror(file)) {
            fprintf(stderr, "写入文件失败: %s\n", strerror(errno));
            fclose(file);
            close(fd);
            return 1;
        }
    }

    // 使用 write 系统调用写入文件
    if (write(fd, message, strlen(message)) == -1) {
        perror("写入文件失败");
        close(fd);
        return 1;
    }

    // 使用 fclose 关闭文件
    if (fclose(file) != 0) {
        fprintf(stderr, "关闭文件失败: %s\n", strerror(errno));
        close(fd);
        return 1;
    }

    // 使用 close 系统调用关闭文件
    if (close(fd) == -1) {
        perror("关闭文件失败");
        return 1;
    }

    return 0;
}

文件描述符与缓冲区

6.11 文件描述符

文件描述符(File Descriptor,FD)是一个用于引用打开文件和其他类型的I/O资源的整数。每个进程都有自己的文件描述符表,用于跟踪进程打开的所有文件和I/O资源。

  • 唯一标识:文件描述符为每个打开的文件或I/O资源提供了一个唯一的标识符,通常是一个非负整数。
  • 文件描述符表:每个进程都有自己的文件描述符表,这是一个内核数据结构,用于跟踪进程打开的所有文件和I/O资源。
  • 系统调用:文件描述符通常通过系统调用如 openreadwriteclose 等进行操作。open 调用返回一个新的文件描述符,readwrite 使用文件描述符来读取或写入数据,而 close 用于释放文件描述符。
  • 标准流:Linux为标准输入(stdin)、标准输出(stdout)和标准错误(stderr)分别分配了文件描述符0、1和2。
  • 缓冲机制:Linux内核可能会对通过文件描述符进行的I/O操作使用缓冲机制,以提高性能和减少实际的磁盘I/O操作。
  • 错误处理:当系统调用失败时,会返回-1,并且全局变量 errno 被设置为表示错误的特定值。
  • 多路复用:文件描述符可以用于I/O多路复用机制,如 selectpollepoll,允许进程同时监控多个文件描述符上的I/O状态。
  • 继承性:当创建新进程时,子进程会继承父进程的文件描述符表中的文件描述符,除非它们在子进程中被显式地关闭。
  • 重定向:文件描述符可以通过 dupdup2 等函数进行重定向,允许将一个文件描述符的引用复制到另一个文件描述符上。
  • 文件锁:文件描述符可以用于对文件加锁,以控制对文件的并发访问。

6.12 缓冲区机制

缓冲区机制是C标准库中用于提高I/O性能的一种技术。缓冲区可以减少用户态和内核态之间的切换次数,从而提高性能。

  • 全缓冲:对于文件,通常是全缓冲的。这意味着数据会先写入缓冲区,当缓冲区满或文件关闭时,数据才会被写入文件。
  • 行缓冲:对于终端输入输出,通常是行缓冲的。这意味着数据会在遇到换行符时被写入文件。
  • 无缓冲:对于标准错误输出,通常是无缓冲的。这意味着数据会立即被写入文件。

实际应用案例

6.13 文件拷贝示例

下面是一个使用库函数和系统调用实现文件拷贝的示例。该示例展示了如何结合使用库函数和系统调用来完成文件操作。

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int copy_file(const char *src_path, const char *dst_path) {
    // 使用 fopen 打开源文件
    FILE *src_file = fopen(src_path, "rb");
    if (src_file == NULL) {
        fprintf(stderr, "打开源文件失败: %s\n", strerror(errno));
        return 1;
    }

    // 使用 open 系统调用打开目标文件
    int dst_fd = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (dst_fd == -1) {
        fprintf(stderr, "打开目标文件失败: %s\n", strerror(errno));
        fclose(src_file);
        return 1;
    }

    char buffer[1024];
    size_t bytes_read;

    while ((bytes_read = fread(buffer, 1, sizeof(buffer), src_file)) > 0) {
        if (ferror(src_file)) {
            fprintf(stderr, "读取源文件失败: %s\n", strerror(errno));
            fclose(src_file);
            close(dst_fd);
            return 1;
        }

        if (write(dst_fd, buffer, bytes_read) == -1) {
            perror("写入目标文件失败");
            fclose(src_file);
            close(dst_fd);
            return 1;
        }
    }

    if (ferror(src_file)) {
        fprintf(stderr, "读取源文件失败: %s\n", strerror(errno));
        fclose(src_file);
        close(dst_fd);
        return 1;
    }

    if (fclose(src_file) != 0) {
        fprintf(stderr, "关闭源文件失败: %s\n", strerror(errno));
        close(dst_fd);
        return 1;
    }

    if (close(dst_fd) == -1) {
        perror("关闭目标文件失败");
        return 1;
    }

    return 0;
}

int main() {
    const char *src_path = "source.txt";
    const char *dst_path = "destination.txt";

    if (copy_file(src_path, dst_path) == 0) {
        printf("文件复制成功\n");
    } else {
        printf("文件复制失败\n");
    }

    return 0;
}

文件操作的底层原理

6.14 文件描述符与文件信息区

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字、文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名 FILE

每当打开一个文件的时候,系统会根据文件的情况自动创建一个 FILE 结构的变量,并填充其中的信息,使用者不必关心细节。一般都是通过一个 FILE 的指针来维护这个 FILE 结构的变量,这样使用起来更加方便。

6.15 文件指针的位置

文件指针可以指向文件的任意位置,通常用来记录下一次读取或写入的位置。可以通过一些函数来移动文件指针的位置,如 fseek 函数和 rewind 函数。可以通过一些函数来获取当前文件指针的位置,如 ftell 函数。

6.16 文件的打开和关闭

在使用文件之前应该打开文件,使用完之后应该关闭文件。ANSI C 规定使用 fopen 来打开文件,用 fclose 来关闭文件。

文件打开方式 mode 参数说明:

  • "r":只读模式,打开一个已经存在的文本文件,用于输入。
  • "w":只写模式,打开一个文本文件用于输出,如果文件已存在则清空原有内容,如果文件不存在则创建新文件。
  • "a":追加模式,打开一个文本文件用于在文件尾部追加数据,如果文件不存在则创建新文件。
  • "rb":只读模式,打开一个二进制文件用于输入。
  • "wb":只写模式,打开一个二进制文件用于输出,如果文件已存在则清空原有内容,如果文件不存在则创建新文件。
  • "ab":追加模式,打开一个二进制文件用于在文件尾部追加数据,如果文件不存在则创建新文件。
  • "r+":读写模式,打开一个文本文件用于读写,文件必须已存在。
  • "w+":读写模式,打开一个文本文件用于读写,如果文件已存在则清空原有内容,如果文件不存在则创建新文件。
  • "a+":读写模式,打开一个文本文件用于读写,文件不存在则创建新文件,所有写入操作都追加到文件尾部。
  • "rb+":读写模式,打开一个二进制文件用于读写,文件必须已存在。
  • "wb+":读写模式,打开一个二进制文件用于读写,如果文件已存在则清空原有内容,如果文件不存在则创建新文件。
  • "ab+":读写模式,打开一个二进制文件用于读写,文件不存在则创建新文件,所有写入操作都追加到文件尾部。

6.17 文件的读写操作

文件的读写操作可以通过一系列函数来完成,如 freadfwritefgetcfputcfgetsfputs 等。这些函数通常使用缓冲机制来提高性能。

6.18 文件定位

文件定位可以通过 fseek 函数来实现,该函数允许移动文件指针到文件中的任意位置。ftell 函数可以获取文件指针的当前位置。

fseek 函数参数说明:

  • stream:指向 FILE 结构的指针。
  • offset:偏移量,可以是正数或负数。
  • whence:定位基准点,可以是 SEEK_SET(文件开头)、SEEK_CUR(当前文件位置)或 SEEK_END(文件末尾)。

示例代码:

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

int main() {
    // 打开文件
    FILE *file = fopen("example.txt", "r+");
    if (file == NULL) {
        fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
        return 1;
    }

    // 移动文件指针到文件开头
    if (fseek(file, 0, SEEK_SET) != 0) {
        fprintf(stderr, "移动文件指针失败: %s\n", strerror(errno));
        fclose(file);
        return 1;
    }

    // 获取文件指针的当前位置
    long position = ftell(file);
    if (position == -1) {
        fprintf(stderr, "获取文件指针位置失败: %s\n", strerror(errno));
        fclose(file);
        return 1;
    }
    printf("文件指针位置: %ld\n", position);

    // 移动文件指针到文件末尾
    if (fseek(file, 0, SEEK_END) != 0) {
        fprintf(stderr, "移动文件指针失败: %s\n", strerror(errno));
        fclose(file);
        return 1;
    }

    // 获取文件指针的当前位置
    position = ftell(file);
    if (position == -1) {
        fprintf(stderr, "获取文件指针位置失败: %s\n", strerror(errno));
        fclose(file);
        return 1;
    }
    printf("文件指针位置: %ld\n", position);

    fclose(file);
    return 0;
}

6.19 文件错误处理

在进行文件操作时,必须注意处理可能出现的错误。可以使用 ferrorclearerr 函数来帮助诊断和清除错误状态。

示例代码:

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

int main() {
    // 打开文件
    FILE *file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
        return 1;
    }

    char buffer[100];
    size_t bytes_read;

    // 读取文件
    bytes_read = fread(buffer, 1, sizeof(buffer), file);
    if (ferror(file)) {
        fprintf(stderr, "读取文件失败: %s\n", strerror(errno));
        fclose(file);
        return 1;
    }

    // 清除错误状态
    clearerr(file);

    fclose(file);
    return 0;
}

文件映射

文件映射是一种高效的数据处理方法,它将文件内容直接映射到进程的虚拟地址空间,使得对文件的操作就像对内存的操作一样简单。文件映射通常通过 mmap 函数来实现。

6.20 使用 mmap 进行文件映射

mmap 函数可以将文件或其他对象映射到内存,映射的内存区域可以直接被读写。

示例代码:

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main() {
    // 打开文件
    int fd = open("largefile.dat", O_RDONLY);
    if (fd == -1) {
        perror("打开文件失败");
        return 1;
    }

    // 获取文件大小
    struct stat st;
    if (fstat(fd, &st) == -1) {
        perror("获取文件大小失败");
        close(fd);
        return 1;
    }

    // 映射文件到内存
    void *addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (addr == MAP_FAILED) {
        perror("映射文件失败");
        close(fd);
        return 1;
    }

    // 处理映射内存
    // ...

    // 解映射内存
    if (munmap(addr, st.st_size) == -1) {
        perror("解映射内存失败");
        close(fd);
        return 1;
    }

    // 关闭文件
    if (close(fd) == -1) {
        perror("关闭文件失败");
        return 1;
    }

    return 0;
}

总结

本文详细介绍了C语言文件操作中的库函数和系统调用,解释了它们的工作原理、区别和联系,并通过实际示例展示了如何使用这些函数。通过本文的学习,读者应能全面理解C语言文件操作的底层机制,为编写高效、可靠的程序提供有力支持。

希望本文能够帮助读者深入理解和应用C语言中的文件操作技术。如果您有任何进一步的问题或建议,请随时留言交流。

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

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

相关文章

【HarmonyOS NEXT】ArkTs数据类型解析与使用

1. 背景 为什么设计ArkTS&#xff1f; 1.1 其它语言有版权【Java&#xff1f;Kotlin&#xff1f;】以及历史问题【Java内存&#xff1f;】 1.2 生态&#xff0c;可复用前端生态的三方库&#xff0c;兼容JS/TS语言生态ArkTs解决了JS/TS中的哪些问题&#xff1f; 2.1 **程序健壮性…

H5 scss 移动端的样式适配

在移动端样式的scss文件中&#xff0c;出现了这些变量 env() 与 constant() 设置安全区域&#xff0c;是css里IOS11新增的属性&#xff0c;webkit的css函数&#xff0c;用于设定安全区域与边界的距离&#xff0c;有4个预定义变量&#xff1a; safe-area-inset-left: 安全区域距…

YOLOv5与ViT目标检测中的热力图应用教程

文章目录 前言一、热力图介绍1、热力图应用说明2、热力图代码整体思路3、实验效果二、heatmap类解读三、GradCAM、GradCAMPlusPlus, GradCAM, XGradCAM, EigenCAM, HiResCAM, LayerCAM等类源码解读1、GradCAM类源码2、BaseCAM类源码解读1、BaseCAM源码2、forward函数源码解读ou…

组织病理学图像的再识别|文献速递-生成式模型与transformer在医学影像中的应用

Title 题目 Re-identification from histopathology images 组织病理学图像的再识别 01 文献速递介绍 在光学显微镜下评估苏木精和伊红&#xff08;H&E&#xff09;染色切片是肿瘤病理诊断的标准程序。随着全切片扫描仪的出现&#xff0c;能够将玻璃切片数字化为所谓的…

如何用重构解锁高效 Vue 开发之路

文章目录 摘要引言什么是代码重构为什么要减少重复逻辑Vue 示例代码问题场景初始代码的痛点重构后的通用组件 TaskList.vue详细说明 重用通用组件详细说明 模拟数据与运行结果 QA环节总结参考资料 摘要 代码重构是改善代码质量的重要手段&#xff0c;特别是在减少重复逻辑方面…

用户发送请求后服务端i/o工作过程

华子目录 服务端i/o介绍磁盘i/o机械磁盘的寻道时间、旋转延迟和数据传输时间常见的机械磁盘平均寻道时间值常见磁盘的平均延迟时间每秒最大IOPS的计算方法 网络i/o网络I/O处理过程磁盘和网络i/o 一次完整的请求在内部的执行过程 服务端i/o介绍 i/o在计算机中指Input/Output&am…

QT c++ 测控系统 一套报警规则(上)

本文适用于pc based的测控系统的上位机&#xff0c;定义了一套报警规则。 由5个部分组成&#xff1a;自定义4布尔类、在全局文件定义工位错误结构体和结构体变量&#xff0c;其它地方给此变量的当前值成员赋值&#xff0c;报警线程类、数据库保存类、弹框类。 1.自定义4布尔类…

概率论得学习和整理24:EXCEL的各种图形,统计图形

目录 0 EXCEL的各种图形&#xff0c;统计图形 1 统计图形 / 直方图 / 其实叫 频度图 hist最合适(用原始数据直接作图) 1.1 什么是频度图 1.2 如何创建频度图&#xff0c;一般是只选中1列数据&#xff08;1个数组&#xff09; 1.3 如何修改频度图的宽度 1.4 hist图的一个特…

项目二十三:电阻测量(需要简单的外围检测电路,将电阻转换为电压)测量100,1k,4.7k,10k,20k的电阻阻值,由数码管显示。要求测试误差 <10%

资料查找&#xff1a; 01 方案选择 使用单片机测量电阻有多种方法&#xff0c;以下是一些常见的方法及其原理&#xff1a; 串联分压法&#xff08;ADC&#xff09; 原理&#xff1a;根据串联电路的分压原理&#xff0c;通过测量已知电阻和待测电阻上的电压&#xff0c;计算出…

Linux中 vim 常用命令大全详细讲解

文章目录 前言一、Vim 基本操作 &#x1f579;️1.1 打开或创建1.2 退出编辑1.3 模式切换 二、Vim 光标移动命令 ↕️2.1 基本移动2.2 行内移动2.3. 单词移动2.4. 页面移动2.5. 行跳转 三、Vim 文本编辑命令 &#x1f4cb;3.1 插入和删除3.2 复制、剪切与粘贴3.3 替换与修改 四…

ARM架构服务器国产麒麟V10安装nginx

目前ARM架构服务器越来越多的出现在我们的工作中&#xff0c;尤其大数据时代的需要&#xff0c;服务器操作系统linux国产化进程的推进。本人已经编写了很多ARM架构下安装java环境&#xff0c;安装mysql&#xff0c;安装redis等等的文档。现在我们演示一下国产麒麟V10安装nginx-…

【SQL】语句练习

1. 更新 1.1单表更新 例1: 所有薪水低于30000的员工薪水增加10% SQL命令&#xff1a; update employee set salarysalary*1.1 where salary < 30000; 1.2多表更新 例1: 将下图两表张三的语文成绩从95修改为80 SQL命令&#xff1a; update exam set score80 where subjec…

【开源】使用环信UIKit for uniapp 做一个IM即时聊天应用

环信单群聊 UIKit 是基于环信即时通讯云 IM SDK 开发的一款即时通讯 UI 组件库&#xff0c;提供各种组件实现会话列表、聊天界面、联系人列表及后续界面等功能&#xff0c;帮助开发者根据实际业务需求快速搭建包含 UI 界面的即时通讯应用。 本文教大家使用环信 uniapp UIKit 快…

用 Python Turtle 绘制经典杰瑞鼠:捕捉卡通世界中的小聪明

用 Python Turtle 绘制经典杰瑞鼠&#xff1a;捕捉卡通世界中的小聪明 &#x1f438; 前言 &#x1f438;&#x1f41e;往期绘画>>点击进所有绘画&#x1f41e;&#x1f40b; 效果图 &#x1f40b;&#x1f409; 代码 &#x1f409; &#x1f438; 前言 &#x1f438; 杰…

Excel拆分脚本

Excel拆分 工作表按行拆分为工作薄 工作表按行拆分为工作薄 打开要拆分的Excel文件&#xff0c;使用快捷键&#xff08;AltF11&#xff09;打开脚本界面&#xff0c;选择要拆分的sheet&#xff0c;打开Module&#xff0c;在Module中输入脚本代码&#xff0c;然后运行脚本 Su…

ModStartCMS v9.1.0 数据Grid样式优化,富文本格式刷支持,精简代码

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…

2024年12月16日Github流行趋势

项目名称&#xff1a;PDFMathTranslate 项目维护者&#xff1a;Byaidu reycn hellofinch Wybxc YadominJinta项目介绍&#xff1a;基于 AI 完整保留排版的 PDF 文档全文双语翻译&#xff0c;支持 Google/DeepL/Ollama/OpenAI 等服务&#xff0c;提供 CLI/GUI/Docker。项目star数…

3-机器人视觉-机器人抓取与操作

文章目录 3机器人视觉目录 1. 传感器和标定摄像头模型Intrinsic MatrixExtrinsic Matrix 标定内参标定手眼标定和外参标定 力传感器&其它传感器其它传感器 2. 神经网络和图像处理2D特征处理常见架构 训练流程推理流程部署流程2D 图像任务3D Point Cloud FeaturePointNet Ap…

Java String详解(二)

上一篇博客&#xff1a;Java String详解&#xff08;一&#xff09; 写在前面&#xff1a;大家好&#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正&#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是&#xff1a;https://ac-fun.blo…

Qt之点击鼠标右键创建菜单栏使用(六)

Qt开发 系列文章 - menu&#xff08;六&#xff09; 目录 前言 一、示例演示 二、菜单栏 1.MenuBar 2.Menu 总结 前言 QMainWindow是一个为用户提供主窗口程序的类&#xff0c;包含一个菜单栏&#xff08;menubar&#xff09;、多个工具栏(toolbars)、一个状态栏(status…