《C语言深度解剖》(16):C语言的文件读写操作

news2024/10/7 18:23:39

🤡博客主页:醉竺

🥰本文专栏:《C语言深度解剖》

😻欢迎关注:感谢大家的点赞评论+关注,祝您学有所成!


✨✨💜💛想要学习更多C语言深度解剖点击专栏链接查看💛💜✨✨ 


目录

1. 为什么使用文件 

2. 文件概述

2.1 什么是流 

2.2 什么是文件 

2.3 文件名 

3. 文件的打开和关闭 

3.1 文件指针 

3.2 文件的打开和关闭 

4. 文件的顺序读写 

5.  文件的随机读写

5.1 fssek 

5.2 ftell

5.3 rewind 

6. 文本文件和二进制文件 

7. 文件读取结束的判定 

 7.1 文件的分类 

7.2 被错误使用的feof 

8. 文件缓冲区 


1. 为什么使用文件 

程序执行起来后,称之为进程,进程运行过程中的数据,均在内存中,当我们需要把运算后的数据存储下来时,就需要文件。 做到数据的持久化。

2. 文件概述

2.1 什么是流 

在C语言中,流是一个用于输入输出操作的抽象概念。它代表了一个数据的流动,从源头(比如键盘、文件、网络等)到目的地(比如屏幕、文件、网络等)。流可以看作是一个数据的序列,它按照一定的顺序被读取或写入。

C语言的标准库提供了一套文件输入输出函数,这些函数可以对流进行操作。在C中,所有的输入输出操作都是通过流来完成的。标准输入输出库 <stdio.h> 定义了流的概念,并提供了相关的函数。

以下是C语言中几个重要的流:

  • stdin - 标准输入流,通常指键盘输入。
  • stdout - 标准输出流,通常指屏幕输出。
  • stderr - 标准错误流,用于输出错误信息,通常也是输出到屏幕,但与stdout分离,以便于错误信息不会与普通输出混淆。

流在C语言中是通过文件指针来引用的,文件指针是一个指向FILE结构的指针,FILE结构包含了流的状态信息。例如,当你打开一个文件时,C语言的fopen函数会返回一个FILE指针,通过这个指针,你可以对文件进行读或写操作。

FILE* fp; // 声明一个文件指针
fp = fopen("example.txt", "r"); // 打开一个文件,返回一个指向该文件的流
if (fp == NULL) {
    // 错误处理
}
// ... 使用fp进行文件操作
fclose(fp); // 关闭流

2.2 什么是文件 

文件:文件指存储在外部介质(如磁盘磁带)上数据的集合。操作系统(windows,Linux, Mac 均是)是以文件为单位对数据进行管理的。 

在C语言中,所有的设备都被视为文件,它们的输入输出操作都可以通过文件流来进行。这使得C语言的输入输出模型非常统一和灵活。 

磁盘上的文件是文件。 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

  • 程序文件 

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境 后缀为.exe)。 

  • 数据文件 

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。 

本章讨论的是数据文件。 

在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理 的就是磁盘上文件。 

2.3 文件名 


3. 文件的打开和关闭 

3.1 文件指针 

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。 

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

打开文件后我们得到 FILE*类型的文件指针,通过该文件指针对文件进行操作,FILE 是 一个结构体类型,那么首先让我们来看下它里边都有什么呢?

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息, 使用者不必关心细节。 

一般都是通过一个 FILE 的指针来维护 FILE 结构的变量。

下面我们可以创建一个FILE*的指针变量: 

FILE* pf;//文件指针变量

定义 pf 是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。

比如: 

3.2 文件的打开和关闭 

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件

在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。 

ANSIC 规定使用fopen数来打开文件fclose来关闭文件。 

  • 当无法打开文件时,fopen函数会返回空指针。这可能是因为文件不存在,也可能是因为文件的位置不对,还可能是因为我们没有打开文件的权限。 
  • 函数 fclose()关闭给出的文件流, 释放已关联到流的所有缓冲区。fclose()执行成功 时返回 0,否则返回 EOF. 

打开方式如下:

实例代码: 

要区分标准的输入输出,和文件操作中的输入输出


4. 文件的顺序读写 

上述简单了解需要用的时候查看一下即可,下面我会为上述每个函数举一个例子:

  • fgetc 
int fgetc(FILE* stream);

在这个例子中,我们使用 fgetc 读取名为 “example.txt” 的文件,并将文件内容打印到标准输出。我们检查每次 fgetc 的调用是否返回 EOF 来判断是否到达文件末尾。同时,我们使用 ferror 函数来检查文件流是否发生了错误。最后,我们关闭文件流以释放资源。 

#include <stdio.h>

int main() {
    int ch;
    FILE* file = fopen("example.txt", "r"); // 打开文件进行读取

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 读取并打印文件内容,直到文件结束
    while ((ch = fgetc(file)) != EOF) {
        putchar(ch); // 将读取到的字符打印到标准输出
    }

    if (ferror(file)) {
        perror("Error reading file");
    }

    fclose(file); // 关闭文件
    return 0;
}
  • fputc 
int fputc(int ch, FILE* stream);

在这个例子中,我们使用 fputc 将字符 ‘A’、‘B’ 和 ‘C’ 写入名为 “output.txt” 的文件中。然后我们关闭文件流。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。

#include <stdio.h>

int main() {
    FILE* file = fopen("output.txt", "w"); // 打开文件进行写入

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 写入字符到文件
    fputc('A', file); // 写入字符 'A'
    fputc('B', file); // 写入字符 'B'
    fputc('C', file); // 写入字符 'C'

    if (fclose(file) != 0) { // 检查文件是否成功关闭
        perror("Error closing file");
    }

    return 0;
}
  • fputs
int fputs(const char* str, FILE* stream);

fputs 不会自动在字符串的末尾添加换行符(\n),如果需要添加换行符,必须在字符串中包含换行符或者在调用 fputs 后显式地写入换行符。
在这个例子中,我们使用 fputs 将字符串 “Hello, World!” 写入名为 “output.txt” 的文件中。然后我们写入一个换行符,并关闭文件流。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。 

#include <stdio.h>

int main() {
    FILE* file = fopen("output.txt", "w"); // 打开文件进行写入

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 写入字符串到文件
    fputs("Hello, World!", file); // 写入字符串 "Hello, World!"

    // 写入换行符
    fputc('\n', file);

    if (fclose(file) != 0) { // 检查文件是否成功关闭
        perror("Error closing file");
    }

    return 0;
}
  • fscanf
int fscanf(FILE* stream, const char* format, ...);

在这个例子中,我们使用 fscanf 从名为 “data.txt” 的文件中读取一个整数和一个浮点数。我们检查 fscanf 的返回值来确定是否成功读取了两个数据项。如果文件打开或读取过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。 

#include <stdio.h>

int main() {
    FILE* file = fopen("data.txt", "r"); // 假设文件包含整数和浮点数
    int num;
    float value;

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 从文件中读取整数和浮点数
    if (fscanf(file, "%d %f", &num, &value) == 2) {
        printf("Read: num = %d, value = %f\n", num, value);
    }
    else {
        printf("Failed to read data\n");
    }

    fclose(file); // 关闭文件
    return 0;
}
  • fprintf 
int fprintf(FILE* stream, const char* format, ...);

在这个例子中,我们使用 fprintf 将整数 42 和浮点数 3.14 写入名为 “output.txt” 的文件中,并且使用格式字符串来指定数据的输出格式。然后我们关闭文件流。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。 

#include <stdio.h>

int main() {
    FILE* file = fopen("output.txt", "w"); // 打开文件进行写入

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 写入格式化的数据到文件
    int num = 42;
    float value = 3.14f;
    fprintf(file, "The number is %d and the value is %f\n", num, value);

    if (fclose(file) != 0) { // 检查文件是否成功关闭
        perror("Error closing file");
    }

    return 0;
}
  • fread 
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
  • ptr:指向要读取数据的内存块的指针。
  • size:每个数据项的大小,以字节为单位。
  • nmemb:要读取的数据项的数量。
  • stream:指向 FILE 对象的指针,该对象标识了输入流。这个流可以是标准输入 stdin,也可以是已经打开的文件流。
  • 返回值:fread 返回实际读取的数据项的数量,这个数量可能小于 nmemb 指定的数量,如果到达文件末尾或发生读取错误,则返回值小于 nmemb。

在这个例子中,我们使用 fread 从名为 “data.bin” 的文件中读取5个整数。我们检查 fread 的返回值来确定是否成功读取了5个数据项。如果文件打开或读取过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。 

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

int main() {
    FILE* file = fopen("data.bin", "rb"); // 打开文件进行二进制读取
    int data[5]; // 假设文件包含5个整数

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 从文件中读取整数
    size_t num_read = fread(data, sizeof(int), 5, file);
    if (num_read != 5) {
        perror("Error reading data");
    }

    fclose(file); // 关闭文件

    // 打印读取到的整数
    for (size_t i = 0; i < num_read; i++) {
        printf("%d ", data[i]);
    }
    printf("\n");

    return 0;
}
  • fwrite 
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);

在这个例子中,我们使用 fwrite 将5个整数写入名为 “data.bin” 的文件中。我们检查 fwrite 的返回值来确定是否成功写入了5个数据项。如果文件打开或写入过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。 

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

int main() {
    FILE *file = fopen("data.bin", "wb"); // 打开文件进行二进制写入
    int data[5] = {1, 2, 3, 4, 5}; // 假设要写入5个整数

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 将整数写入文件
    size_t num_written = fwrite(data, sizeof(int), 5, file);
    if (num_written != 5) {
        perror("Error writing data");
    }

    fclose(file); // 关闭文件

    return 0;
}

对比一组函数: 

这两主要讲解一些 sscanf sprintf

  • sprintf
int sprintf(char *str, const char *format, ...);

在这个例子中,我们使用 sprintf 将整数 42 和浮点数 3.14 格式化为字符串,并写入 buffer 数组中。然后我们打印 buffer 数组中的内容。sprintf 函数返回写入的字符数,这个数可以帮助我们确定字符串的实际长度,并确保 buffer 数组有足够的空间来存储结果。 

#include <stdio.h>

int main() {
    char buffer[100]; // 假设buffer足够大以存储结果
    int num = 42;
    float value = 3.14f;

    // 使用sprintf格式化字符串并写入buffer
    sprintf(buffer, "The number is %d and the value is %f\n", num, value);

    // 打印buffer中的内容
    printf("%s", buffer);

    return 0;
}
  • sscanf
int sscanf(const char *str, const char *format, ...);

在这个例子中,我们使用 sscanf 从字符串 “42 3.14” 中解析一个整数和一个浮点数。我们检查 sscanf 的返回值来确定是否成功解析了两个数据项。如果字符串中没有足够的输入数据,或者格式字符串中的格式规范符与输入数据不匹配,sscanf 可能不会成功匹配所有输入项,或者根本不匹配任何输入项。 

#include <stdio.h>

int main() {
    char input[20];
    int num;
    float value;

    // 假设输入字符串为 "42 3.14"
    strcpy(input, "42 3.14");

    // 从字符串中解析整数和浮点数
    if (sscanf(input, "%d %f", &num, &value) == 2) {
        printf("Parsed: num = %d, value = %f\n", num, value);
    } else {
        printf("Failed to parse data\n");
    }

    return 0;
}

5.  文件的随机读写

5.1 fssek 

根据文件指针的位置和偏移量来定位文件指针。 

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

参数说明:

  • stream:指向 FILE 对象的指针,该对象标识了要设置位置的文件流。
  • offset:要移动的字节数,可以是正数、负数或零。
  • origin:指定移动的起点,可以是以下常量之一:
  • SEEK_SET:从文件流的开始位置开始移动。
  • SEEK_CUR:从文件流的当前位置开始移动。
  • SEEK_END:从文件流的结束位置开始移动。 
#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r+"); // 打开文件进行读写操作

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    // 将文件指针移动到文件末尾
    if (fseek(file, 0, SEEK_END) == 0) {
        printf("File pointer moved to end of file\n");
    } else {
        perror("Error moving file pointer");
    }

    fclose(file); // 关闭文件
    return 0;
}

在这个例子中,我们使用 fseek 将文件指针移动到文件末尾。我们检查 fseek 的返回值来确定是否成功移动了文件指针。如果文件打开或移动过程中发生错误,我们会使用 perror 函数来打印错误信息。最后,我们关闭文件流以释放资源。

5.2 ftell

返回文件指针相对于起始位置的偏移量 

long int ftell(FILE* stream);
/* ftell example : getting size of a file */
#include <stdio.h>
int main()
{
    FILE* pFile;
    long size;
    pFile = fopen("myfile.txt", "rb");
    if (pFile == NULL) perror("Error opening file");
    else
    {
        fseek(pFile, 0, SEEK_END);   // non-portable
        size = ftell(pFile);
        fclose(pFile);
        printf("Size of myfile.txt: %ld bytes.\n", size);
    }
    return 0;
}

5.3 rewind 

让文件指针的位置回到文件的起始位置 

void rewind ( FILE * stream );
/* rewind example */
#include <stdio.h>
int main()
{
    int n;
    FILE* pFile;
    char buffer[27];
    pFile = fopen("myfile.txt", "w+");
    for (n = 'A'; n <= 'Z'; n++)
        fputc(n, pFile);
    rewind(pFile);
    fread(buffer, 1, 26, pFile);
    fclose(pFile);
    buffer[26] = '\0';
    puts(buffer);

    return 0;
}

6. 文本文件和二进制文件 

根据数据的组织形式,数据文件被称为文本文件或者二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件件
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而
二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。 

测试代码:

#include <stdio.h>

int main()
{
	int a = 10000;
	FILE* pf = fopen("test.txt", "wb");
	fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
	fclose(pf);
	pf = NULL;
	return 0;
}

7. 文件读取结束的判定 

 7.1 文件的分类 

  • 从用户观点: 

特殊文件(标准输入输出文件或标准设备文件)。

普通文件(磁盘文件)。 

  • 从操作系统的角度看,每一个与主机相连的输入、输出设备看作是一个文件。

例:

输入文件:终端键盘

输出文件:显示屏和打印机 

  • 按数据的组织形式: 

 ASCII 文件(文本文件):每一个字节放一个 ASCII 代码。在文本文件(textfile)中,字节表示字符,这使人们可以检查或编辑文件。例如,C程序源代码是存储在文本文件中的。

二进制文件:把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。 在二进制文件(binaryfile)中,字节不一定表示字符;字节组还可以表示其他类型的数据,比如整数和浮点数。如果试图查看可执行C程序的内容,你会立刻意识到它是存储在二进制文件中的。

7.2 被错误使用的feof 

牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。 

而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

正确的使用:

文本文件的例子: 

二进制文件的例子: 

8. 文件缓冲区 

C语言对文件的处理方法:

缓冲文件系统:

非缓冲文件系统:

系统不自动开辟确定大小的缓冲区,而由程序为每个文件设定缓冲区。用非缓冲文件系统进行的输入输出又称为低级输入输出系统。

int fflush(FILE *stream);

void setbuf(FILE *stream, char *buffer);

int setvbuf(FILE *stream, char *buffer, int mode, size_t size);

向磁盘驱动器传入数据或者从磁盘驱动器传出数据都是相对较慢的操作。因此,在每次程序想读或写字符时都直接访问磁盘文件是不可行的。获得较好性能的诀窍就是缓冲(buffering):把写入流的数据存储在内存的缓冲区域内;当缓冲区满了(或者关闭流)时,对缓冲区进行“清洗”(写入实际的输出设备)。输入流可以用类似的方法进行缓冲:缓冲区包含来自输入设备的数据,从缓冲区读数据而不是从设备本身读数据。缓冲在效率上可以取得巨大的收益,因为从缓冲区读字符或者在缓冲区内存储字符几乎不花什么时间。当然,把缓冲区的内容传递给磁盘,或者从磁盘传递给缓冲区是需要花时间的,但是一次大的“块移动”比多次小字节移动要快很多。

当程序向文件中写输出时,数据通常先放入缓冲区中。当缓冲区满了或者关闭文件时,缓冲区会自动清洗。然而,通过调用fflush函数,程序可以按我们所希望的频率来清洗文件的缓冲区。

  • 调用 fflush(fp);为和fp相关联的文件清晰了缓冲区。 
  • 调用 fflush(NULL);  清洗了全部输出流。如果调用成功,fflush函数会返回零;如果发生错误,则返回EOF。
#include <stdio.h>
#include <windows.h>
//VS2013 WIN10环境测试
int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcdef", pf);//先将代码放在输出缓冲区
	printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
	Sleep(10000);
	printf("刷新缓冲区\n");
	fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
	//注:fflush 在高版本的VS上不能使用了
	printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
	Sleep(10000);
	fclose(pf);
	//注:fclose在关闭文件的时候,也会刷新缓冲区
	pf = NULL;

	return 0;
}

这里可以得出一个结论

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。 如果不做,可能导致读写文件的问题。 

 本篇文章到此结束,这篇文章学透,对于C语言中的文件操作就会行云流水~麻烦点个赞评论支持一下吧!

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

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

相关文章

STL-priority_queue的使用及其模拟实现

优先级队列(priority_queue)默认使用vector作为其底层存储数据的容器&#xff0c;在vector上又使用了堆算法将vector中的元素构造成堆的结构&#xff0c;因此priority_queue就是堆&#xff0c;所有需要用到堆的位置&#xff0c;都可以考虑使用priority_queue。 注意&#xff1…

代码助手之-百度Comate智能体验

简介 越来越多的厂商提供了智能代码助手&#xff0c;百度也不例外。Baidu Comate&#xff08;智能代码助手&#xff09;是基于文心大模型&#xff0c;Comate取自Coding Mate&#xff0c;寓意大家的AI编码伙伴。Comate融合了百度内部多年积累的编程现场大数据和外部开源代码和知…

革新风暴来袭:报事报修系统小程序如何重塑报事报修体验?

随着数字化、智能化的发展&#xff0c;已经应用在我们日常生活和工作的方方面面。那么&#xff0c;你还在为物业报修而头疼吗&#xff1f;想象一下&#xff0c;家里的水管突然爆裂&#xff0c;你急忙联系物业&#xff0c;时常面临物业电话忙音、接听后才进行登记繁琐的报修单、…

UC浏览器,居然这么牛?

你有一个10GB的文件&#xff0c;你想把它发送给你的好友&#xff0c;你会选择什么方式&#xff1f; A&#xff1a;某打败5G的网盘 B&#xff1a;聊天软件 C&#xff1a;文件传输助手 D&#xff1a;买一个U盘快递过去 E&#xff1a;钝角 我的答案是&#xff1a;文件传输助手&a…

图解Java数组的内存分布

我们知道&#xff0c;访问数组元素要通过数组索引&#xff0c;如&#xff1a; arr[0]如果直接访问数组&#xff0c;比如&#xff1a; int[] arr1 {1}; System.out.println(arr1);会发生什么呢&#xff1f; 打印的是一串奇怪的字符串&#xff1a;[I16b98e56。 这个字符串是J…

4-Django项目--资产管理

目录 项目结构 asset_data.html asset_data/add_modify.html views/asset_data.py ------资产管理-------- 资产信息展示 views/asset_data.py 添加资产信息 添加和编辑的html可参考学员信息添加修改html views/asset_data.py 修改信息资产 views/asset_data.py 项…

MySQL注入 — Dns 注入

DNS注入原理 通过子查询&#xff0c;将内容拼接到域名内&#xff0c;让load_file()去访问共享文件&#xff0c;访问的域名被记录此时变为显错注入,将盲注变显错注入,读取远程共享文件&#xff0c;通过拼接出函数做查询,拼接到域名中&#xff0c;访问时将访问服务器&#xff0c;…

聊聊最近很火的混合专家模型(MoE)

前段时间&#xff0c;在2024年NVIDIA GTC大会上&#xff0c;英伟达不小心透露了GPT-4采用了MoE架构&#xff0c;模型有1.8万亿参数&#xff0c;由8个220B模型组成&#xff0c;与此前的GPT-4泄露的信息一致。 近半年多以来&#xff0c;各类MoE大模型更是层出不穷。在海外&#…

【Tlias智能学习辅助系统】01 准备工作

Tlias智能学习辅助系统 01 创建员工、部门表创建springboot工程&#xff0c;引入对应的起步依赖(web、mybatis、mysql驱动、lombok)准备 Mapper、Service、Controller 等基础结构MapperServiceControllerpojo封装类application.properties 接口开发规范 创建员工、部门表 -- 创…

MyBatis的坑(动态SQL会把0和空串比较相等为true)

文章目录 前言一、场景如下二、原因分析1. 源码分析2. 写代码验证 三、解决办法代码及执行结果如下 总结 前言 在开发过程中遇到MyBatis的动态SQL的if条件不生效的情况&#xff0c;但经过debuger发现并不是参数问题&#xff0c;已经拿到了参数并传给了MyBatis&#xff0c;且从表…

第十九节:带你梳理Vue2: 父组件向子组件传参(props传参)

1. 组件嵌套 1.1 组件的嵌套使用 之前有说过,Vue组件跟Vue实例是一样的,因此在Vue中一个组件中也可以定义并使用自己的局部组件,这就是组件的嵌套使用 例如:示例代码如下: <div id"app"><!-- 3. 使用组件 --><my-component></my-component&…

inStrain:灵敏地检测共享微生物菌株

GitHub - MrOlm/inStrain: Bioinformatics program inStrain 安装 conda create -n instrain conda activate instrain pip install instrain inStrain -h 需要准备一个 scaffold-to-bin file &#xff08;.text 文件&#xff0c;包含由制表符分隔的两列&#xff0c;其中第一…

Kafka原生API使用Java代码-生产者-发送消息

文章目录 1、生产者发送消息1.1、使用EFAK创建主题my_topic31.2、根据kafka官网文档写代码1.3、pom.xml1.4、KafkaProducer1.java1.5、使用EFAK查看主题1.6、再次运行KafkaProducer1.java1.7、再次使用EFAK查看主题 1、生产者发送消息 1.1、使用EFAK创建主题my_topic3 1.2、根…

研学活动报名二维码怎么制作?

在组织研学活动时&#xff0c;老师们经常面临报名流程繁琐、信息收集不全面、统计工作耗时等问题&#xff1f;如何高效地管理学生的报名信息&#xff0c;确保活动顺利进行呢&#xff1f; 现在我们有了更多的选择。老师们可以快速制作出研学活动的研学活动报名二维码怎么制作&am…

DNF手游攻略:开荒必备攻略!

DNF手游马上就要开服了&#xff0c;今天给大家带来最完整的DNF手游入门教程。这篇攻略主要讲述了 DNF手游开服第一天要注意的事项&#xff0c;这是一个新手必备的技能书&#xff0c;可以让你在开服的时候&#xff0c;少走一些弯路&#xff0c;让你更快完成任务&#xff01;废话…

[MySQL最详细的知识点]

MySQL 关系型数据库以一行作为一个记录,列数据库以一列为一个记录一行是一个记录,一列是一个字段一行是一个实体,一列是一个属性 MySQL引擎: MySQL引擎&#xff1a;可以理解为&#xff0c;MySQL的“文件系统”&#xff0c;只不过功能更加强大。​MySQL引擎功能&#xff1a;除…

自动化测试-ddt数据驱动yaml文件实战(详细)

前言 ddt 驱动 yaml/yml 文件来实现数据驱动测试 ddt.file_data&#xff1a;装饰测试方法&#xff0c;参数是文件名。文件可以是 json 或者 yaml 类型。 注意&#xff1a;如果文件是以 “.yml”或者".yaml" 结尾&#xff0c;ddt 会作为 yaml 类型处理&#xff0c;…

【教学类-59-01】专注力视觉训练01(圆点百数图)

背景需求&#xff1a; 视觉训练的神奇效果&#xff0c;让你的宝贝成为焦点 - 小红书魔法视觉追踪-视觉训练—— &#x1f50d;视觉训练&#x1f50d; &#x1f539;想要提高宝宝的专注力&#xff0c;视觉训练是个绝佳方法&#xff01; &#x1f539;让宝宝仔细观察数字的路线&a…

JavaScript-内存分配,关键字const

内存空间 内存分为栈和堆 栈&#xff1a;由操作系统自动释放存放的变量值和函数值等。简单数据类型存放在栈中 栈会由低到高先入后出 堆&#xff1a;存储引用类型 &#xff08;数组&#xff0c;对象&#xff09; 对象会先将数据存放在堆里面&#xff0c;堆的地址放在栈里面 关键…

喜讯 | 盘古信息冠捷科技、锐明科技IMS项目荣获创新案例、优秀案例

5月28日&#xff0c;中国数据要素及行业应用创新大会盛大启幕&#xff0c;现场汇聚了中国工程院院士、数据要素研究机构及数据要素知名企业、数字要素行业生态代表等300位业内相关人士。广东盘古信息科技股份有限公司副总经理朱熀锋代表盘古信息出席大会&#xff0c;并带来了IM…