文件操作详解(C语言)

1.为什么要用到文件?怎样数据才能持久化?

保存在内存中的数不安全(一次断电,忘记保存,不用了还给系统)

持久化:保存在硬盘上(放在文件中)

什么是文件?文件分为程序文件数据文件

程序文件是什么呢?

在windows环境下。.c源程序文件 / .obj目标文件 / .exe执行文件,这些就是程序文件

数据文件

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

如图:

编辑.c源程序文件(test.c)可以对A文件(数据文件)进行读写操作进行

2.文件名

一个文件有唯一的文件标识,以便于用户的识别和引用

文件名包含三部分:文件路径 + 文件主干名 + 文件后缀

例:  c:\code\heyerous\test.txt

3.文件的打开 or 关闭

->1. 文件指针

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

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

如图:

注:  每打开一个文件就会产生一个文件信息区,每一个文件信息区都需要一个文件指针来指向它。不同的C编译器的FILE类型包含的内容不完全相同,但大同小异

一般都是通过FILE的指针来维护这个FILE结构的变量,这样更方便

创建一个FILE指针的变量:

FILE* pf       //文件指针变量

->2. 文件的打开和关闭

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

ANSIC(标准C)规定使用fopen函数(打开成功放回文件地址,失败则返回NULL)来打开文件,fclose函数(打开成功返回0,打开失败返回EOF(-1))来关闭文件

fopen和fclose的使用示例:

#include <stdio.h>

int main()
{
    //打开文件
    FILE* pf = fopen("C:\\code\\heyerous\\test.txt", "r");
    //判断文件是否打开成功
    if(pf == NULL)
    {
       perror("fopen");
       return 1;
    }
    //读写文件
    //....
    //关闭文件
    fclose(pf);
    pf = NULL;
}

运行结果:

打开成功说明该路径存在这个文件

上面所示代码是用的绝对路径打开的文件 C:\code\heyerous\test.txt

绝对路径

文件的准确位置

相对路径

相对路径的理解,可以认为是程序和文件的相对位置,比如说和当前.c文件在同文件夹中,或者文件在.c文件的上级路径中 (以.c文件为例)

就可以看到该文本文件(test.txt)了

将文件放在上级目录程序依旧可以运行

除了这两个操作以外还其他的操作:

如:“../test.txt”  上级目录   “./text.txt”  当前目录  "././test,txt" 上一级目录的上一级目录

注:  创建文件的时候看看后缀名(扩展名)

4.怎么读写?

1.文件的顺序读写

fputc

->1.  fputc函数    //向文件中写一个字符

int fputc(int charactor, FILE* stream);

(1). FILE* stream 需要写入的文件的指针

(2). int charactor 需要向文件中写的字符

->2.  fputc函数的使用

puts按顺序向文件中写内容

#include <stdio.h>

int main()
{
	//用"w"会将我们上次写入的内容全部覆盖掉
	FILE* pf = fopen("C:\\code\\heyerous\\test.txt", "w"); 
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
    //方法1
	/*fputc('z', pf);
	fputc('y', pf);
	fputc('x', pf);
	fputc('6', pf);*/
    //方法2:使用for循环
	for (char ch = 'A'; ch <= 'Z'; ch++)
	{
		fputc(ch, pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果:

向文件写一个字符,不是字符串!!!

fgetc

->1. fgetc函数    //向文件中读一个字符

int fgetc(FILE* stream);

(1). 按顺序向文件读字符

(2). FILE* stream   需要读文件的指针

->2. fgetc函数的使用

#include <stdio.h>

int main()
{
	FILE* pf = fopen("C:\\code\\heyerous\\test.txt", "r"); 
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	int ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果:

fputs

->1. fputs函数   //向文件中写入一行内容

int fputs( const char *string, FILE *stream );

(1). const char *string  需要写入文件的内容

(2). FILE *stream 目标文件

->2. fputs函数的使用  

这里我们换用相对路径

#include <stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "w");
    if(NULL == pf)
    {
       perror("fopen");
       return 1;
    }
    fputs("hello world", pf);
    fclose(pf);
    pf ==NULL;
    return 0;
}

运行结果:

fgets

->1. fgets函数 //向文件读一行内容

char *fgets( char *string, int n, FILE *stream );

(1). char *string  将读到的内容放到另一个空间中

(2). int n  个数限制

(3). FILE *stream 需要读的文件的指针

->2. fgets函数的使用

#include <stdio.h>
int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (NULL == pf)
    {
        perror("fopen");
        return 1;
    }
    char buf[25] = { 0 };
    fgets(buf, 12, pf);
    printf(buf);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

注:  fgets读文件时会留一个空间存放\0,所以我们想要将hello world全部都读出来得限制12个个数(包括\0)

如果buf空间比文件中一行大,即:fgets只读一行的内容

1.buf > num, 直接读到末尾结束,第二行不管,只管第一行得内容

2.buf < num,只读num数量的字符

fprintf

->1. fprintf函数   //将格式化的内容写到文件中  

int fprintf(FILE* stream, const char*format, ...);

(1). FILE* stream  需要写入的文件的指针

(2). const char*format  数据流:格式化字符串等各种信息

(3). ...  可变参数列表可接收多个参数

->2. fprintf函数的使用

#include <stdio.h>

typedef struct S
{
    char name[20];
    int age;
    float score;
}S;

int main()
{
    FILE* pf = fopen("test.txt", "w");
    if(FILE == NULL)
    {
       perror("fopen");
       reutrn 1;
    }
    s stu = {"zhangsan", 20, 89.5}; 
    fprintf(pf, "%s %d %f", stu.name, stu.age, stu.score);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

 fscanf

->1. fscanf函数   //将格式化的内容写到文件中  

int fscanf(FILE* stream, const char*format, ...);

(1). FILE* stream  需要写入的文件的指针

(2). const char*format  数据流:格式化字符串等各种信息

(3). ...  可变参数列表可接收多个参数

->2. fprintf函数的使用

#include <stdio.h>

typedef struct S
{
    char name[20];
    int age;
    float score;
}S;

int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    S stu = { 0 };
    fscanf(pf, "%s %d %f", stu.name, &(stu.age), &(stu.score));
    printf("%s %d %f", stu.name, stu.age, stu.score);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:


以上函数操作时写入文件都看得懂,因为是文本信息(适用于所有输入输出流)

我们将数据传给输出设备如果这些设备的读写的都不相同,程序要使用的话都需要了解,那对一个程序来说太复杂了,所以为了解决这个问题C语言引入了流(stream)

将数据输出到流上,然后通过流输出到设备上

任何一个C语言程序运行的时候:默认打开3个流

1.stdin - 标准输出(键盘)

2.stdout - 标准输出(屏幕)

3.stderr - 标准错误(屏幕)

这三个流的类型都是FILE*

例1:

int ch = fgets(stdin)
fputc(ch, stdout)

从键盘上读一个字符然后写到屏幕上

例2:

#include <stdio.h>

typedef struct stu
{
    char name[20];
    int age;
    float score;
}stu;

int main()
{
    stu p = { 0 };
    fscanf(stdin, "%s %d %f", p.name, &(p.age), &(p.score));
    fprintf(stdout, "%s %d %f", p.name, p.age, p.score);
    return 0;
}

运行结果:

fwrite

->1. fwrite函数  //以二进制的方式向文件中写入

size_t fwrite(const void *ptr, size_t size, size_t count, FILE* stream)

(1). const void *ptr  需要写入数据的地址

(2). size_t size   每个元素的大小

(3). size_t count   需要写入文件的元素个数

(4). FILE *stream   该文件的指针

->2. fwrite函数的使用

#include <stdio.h>

typedef struct stu
{
    char name[20];
    int age;
    float score;
}stu;

int main()
{
    FILE *pf = fopen("test.txt", "wb"); //wb以二进制的方式写
    if(NULL ==pf)
    {
       perror("fopen");
       return 1;
    }
    stu p = {"zhangsan", 20, 85.5};
    fwrite(&p, sizeof(stu), 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;    
}

运行结果:

从运行结果来看,确实是以二进制的形式写进去的

 fread

->1. fread函数  //以二进制的方式读文件

size_t fwrite(void *ptr, size_t size, size_t count, FILE* stream)

(1). void *ptr  存放向文件读到的数据

(2). size_t size   每个元素的大小

(3). size_t count   需要写入文件的元素个数

(4). FILE *stream   该文件的指针

->2. fread函数的使用

#include <stdio.h>

typedef struct stu
{
    char name[20];
    int age;
    float score;
}stu;

int main()
{
    FILE *pf = fopen("test.txt", "rb"); //以二进制的形式读
    if(NULL == pf)
    {
       perror("fopen");
       return 1;
    }
    stu s = { 0 };
    fread(&s, sizeof(stu), 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

可以看到fread将文件的内容放入了结构体变量s上

sprintf

->1. sprintf函数  //把格式化的数据,以字符串的格式打印存放在一个字符串中

int sprintf(const char* s, const char* format, ...);

(1). const char* s  存放数据的地址

(2). const* format   数据流:格式化字符串等各种信息

(3). ...   可变参数列表,可以放多个参数

->2. sprintf函数的使用

#incldue <stdio.h>

typedef struct tmp
{
	char name[20];
	int age;
	float score;
}tmp;

int main()
{
	tmp s = {"zhangsan", 20, 86.5};
	char buf[30] = { 0 };
	sprintf(buf, "%s%d%f", s.name, s.age, s.score);
	printf(buf);
	return 0;
}

运行结果:

 sscanf

->1. sscanf函数  //从一个字符串中,还原出一个格式化的数据

int sscanf(const char* s, const char* format, ...);

(1). const char* s  存放数据的地址

(2). const* format   数据流:格式化字符串等各种信息

(3). ...   可变参数列表,可以放多个参数

->2. sscanf函数的使用

#include <stdio.h>

typedef struct tmp
{
	char name[20];
	int age;
	float score;
}tmp;

int main()
{
	tmp s = { 0 };
	char buf[30] = { "zhangsan 20 86.5" };
	sscanf(buf, "%s%d%f", s.name, &(s.age), &(s.score));
	printf("%s %d %f", s.name, s.age, s.score);
	return 0;
}

运行结果:


scanf - 从键盘(stdin)上读取格式化的数据

printf - 把数据输出到屏幕(stdout)上

fprintf - 针对所有输入流的格式化的输入函数:stdin,打开的文件

fscanf - 针对所有的输出流的格式化的输出函数:stdout,打开的文件

5.文件的随机读写

fseek

->1. fseek函数  //调整光标位置

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

(1). FILE* stream  目标文件

(2). long int offset   偏移量(往哪偏移)

(3). int orgin  从哪开始调整

​​​SEEK_SET    文件开始的位置

SEEK_CUR   光标现指向的位置

SEEK_END   文件末尾位置

->2. fseek函数的使用

 例:

文本文件中的内容

#include <stdio.h>
 
int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (NULL == pf)
    {
        perror("fopen");
        return 1;
    }
    int ch = fgetc(pf);
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    //此时光标在字符c的后面d的前面,如果继续往下读肯定回到d,但是我们调整一下去读b
    fseek(pf, 1, SEEK_SET);// 或者fseek(pf, -2, SEEK_SUR);
    //这时往下读就会读到b
    ch = fgetc(pf);
    printf("%c", ch);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

ftell

->1. ftell函数  //返回文件指针相对于起始位置的偏移量

long int fseek(FILE* stream);

(1). FILE* stream  目标文件

#include <stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (NULL == pf)
    {
        perror("fopen");
        return 1;
    }
    int ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);
    int pos = ftell(pf);
    printf("%d", pos);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

->2. rewind函数的使用

#include <stdio.h>

int main()
{
    FILE *pf = fopen("test.txt", "r");
    if(NULL == pf)
    {
       perror("fopen");
       return 1;
    }
    int ch = fgetc(pf);
    printf("%c\n", ch);
    rewind(pf);
    ch = fgetc(pf);
    printf("%c", ch);
    fclose(pf);
    pf = NULL;
    return 0;
}

rewind

->1. rewind函数  //使指针回到初始位置

void rewind( FILE *stream );

(1). FILE *stream  需要调整文件的指针

->2. rewind函数的使用

#include <stdio.h>

int main()
{
    FILE *pf = fopen("test.txt", "r");
    if(NULL == pf)
    {
       perror("fopen");
       return 1;
    }
    int ch = fgetc(pf);
    printf("%c\n", ch);
    rewind(pf);
    ch = fgetc(pf);
    printf("%c", ch);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

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

数据文件被称为文本文件或者二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到外存(文件),就是二进制文件

在外存上以ASCII码的形式储存,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

测试代码:

#include <stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "wb");
    if (NULL == pf)
    {
        perror("fopen");
        return 1;
    }
    int a = 10000;
    fwrite(&a, 4, 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

可以看到是二进制文件

我们来看看它是否是如我们所说的二进制一样

 

然后添加这个文件

添加进来之后右击点击这个文件,选择打开方式,点击二进制编辑器

可以看到是以十六进制的方式写的,因为这样更加方便表达展现,而且字节存储方式是小端

#include <stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "w");
    if (NULL == pf)
    {
        perror("fopen");
        return 1;
    }
    int a = 10000;
    fprintf(pf, "%d", a);
    fclose(pf);
    pf = NULL;
    return 0;
}

运行结果:

文本文件

7.文件读取结束的判定

feof 和 ferror

int ferror( FILE *stream );
int feof( FILE *stream );

(1). FILE *stream - 需要判断的文件

feof - 文件正常读取遇到了结束标志而结束就返回真

ferror - 返回真,说明文件在读取过程中出错了而结束

用这两个函数的前提是文件已经读取结束了才可以去使用这两个函数

用于文件读取结束的时候,判断是读取失败,还是到文件末尾结束 

1.文本文件读取是否结束,判断返回值是否为EOF(fgetc),NULL(fgets)

例如:

  • fgetc判断是否为EOF
  • fgets判断是否为NULL

文本文件的例子:

#include <stdio.h>
#define EXIT_FAILURE 1

int main()
{
    FILE *pf = fopen("test,txt", "r");
    if(NULL == pf)
    {
       perror("file opening failed");
       return EXIT_FAILURE;
    }
    int ch;
    while((ch = fgetc(pf)) != EOF)  //fgetc的返回值是int类型
    {
          putchar(ch);
    }
    //判断是什么原因结束的
    //判断文件是否是读取时遇到错误结束
    if(ferror(pf))
       puts("I/O error when reading"); //I/O读取文件
    else if(feof(pf))
       puts("End of file reached successfully");
    fclose(pf);
    pf = NULL;
    return 0;
}

2.二进制文件的读取结束判断,判断返回值是否小于实际要读的个数

例如:

  • fread 判断返回值是否小于实际要读的个数

二进制文件的例子:

#include <stdio.h>

enum     //没有枚举名作用和define差不多,文本替换
{
  size = 5,  
};

int main()
{
    FILE* pf = fopen("test.txt", "wb");
    if (NULL == pf)
    {
        perror("FILE fopening failed");
        return 1;
    }
    int a[size] = { 1, 2, 3, 4, 5, };
    fwrite(a, sizeof * a, size, pf);
    fclose(pf);
    pf = NULL;
    return 0;
}
//以上代码是将数组a中的容写进文件test.txt

#include <stdio.h>

enum     //没有枚举名作用和define差不多,文本替换
{
  size = 5,  
};

int main()
{
    FILE* pf = fopen("test.txt", "rb");
    int a[size] = { 0 };
    size_t ret_code = fread(a, sizeof *a, size, pf);
    if (ret_code == size)
    {
        perror("FILE fopening failed");
        return 1;
    }
    else if(feof(pf))
    {
            puts("Error reading test.txt: unexpected end of file\n");
    }
    else if(ferror(pf))
    {
            puts("Error reading test.txt");
    }
    fclose(pf);
    pf = NULL;
    return 0;
}

8.文件缓冲区

我们将数据冲数据区输出/输入到磁盘(文件)的时候不是直接输入/输出过去而是先经过缓冲区,通过缓冲区进入磁盘的,但是我们放到缓冲区的数据不会直接进入到磁盘,要怎么才能将数据放到磁盘了

将数据放入磁盘的条件

(1). 缓冲区放满的时候,缓冲区会自动将数据放入磁盘

(2). 主动刷新缓冲区的时候,缓冲区会将数放入磁盘

(3). 使用fclose关闭文件时,也会主动刷新缓冲区的将数据写到硬盘中然后关闭文件

 注:

因为有缓冲区的存在,C语言在操作文件的时候。需要做刷新缓冲区或者在文件操作结束的时候关闭文件   很重要!!!(保存信息)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pgrouting使用

pgRouting是一个为PostgreSQL和PostGIS提供路由功能的开源库&#xff0c;它支持复杂的图论算法&#xff0c;用于在地理网络中进行最短路径搜索。以下是pgRouting的一些应用实例。 注意事项&#xff1a; 1、路网表中的id、source、target必须是int类型&#xff0c;否则创建拓扑…

傅雷家书思维导图的制作方法,分享制作技巧和软件!

在浩如烟海的书海中&#xff0c;《傅雷家书》以其独特的视角和深厚的情感&#xff0c;成为了无数读者心中的经典。那么&#xff0c;如何将这部饱含父爱的书信集转化为清晰易懂的思维导图呢&#xff1f;本文将为您详细解读傅雷家书思维导图的制作技巧&#xff0c;并推荐几款实用…

java面试-SpringAOP

1.SpringAOP的使用 你了解Spring AOP 吗&#xff1f; 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 2.SpringAOP的原理 我们可以将ASM生成的类进行缓存&#xff0c;这样能解决生成的类比较低效的问题。 ASM是可以操作字节码的框架。 真实实现类和…

Windows 组策略编辑器怎么打开,这两种方法你必须知道

组策略编辑器&#xff08;Group Policy Editor, 简称 GPEdit.msc&#xff09;是 Windows 操作系统中一个强大的工具&#xff0c;主要用于管理和配置系统设置、安全选项、用户权限等&#xff0c;尤其适用于企业环境中批量部署和管理策略。 尽管家庭版 Windows&#xff08;如 Win…

数字集群手持终端是什么_鼎跃安全

在当今快速发展的科技时代&#xff0c;通信技术的进步为各行各业带来了巨大的变革。尤其是在公共安全、应急救援和交通运输等领域&#xff0c;通信的及时性和可靠性变得尤为重要。数字集群手持终端作为一种专用于数字集群通信系统的便携式设备&#xff0c;数字集群手持终端是一…

ubuntu安装miniconda、jupyer、ros2

miniconda: 类似于虚拟机 ,可以安装不同版本的python jupyer: python执行、调试命令工具 1.下载安装文件 wget https://repo.anaconda.com/miniconda/Miniconda3-py310_23.5.2-0-Linux-x86_64.sh 2.安装minconda bash https://repo.anaconda.com/miniconda/Miniconda3-py…

Linux 防火墙开放端口

启动防火墙服务&#xff1a;systemctl start firewalld 查看防火墙开放端口 &#xff1a;firewall-cmd --list-ports 开放3306端口&#xff1a;firewall-cmd --zonepublic --add-port2375/tcp --permanent 防火墙重启&#xff1a;firewall-cmd --reload

第十二届信息系统与计算技术国际会议(ISCTech 2024)

随着信息技术的迅猛发展&#xff0c;信息系统与计算技术已成为推动社会进步和经济发展的重要力量。为了加强国内外专家学者在信息系统与计算技术领域的交流与合作&#xff0c;第十二届信息系统与计算技术国际会议&#xff08;ISCTech 2024&#xff09;将于2024年11月8日至11日在…

BK145FRC10HSK、BK165FRC10HSK电液比例开环控制变量泵放大器

BK15FRC10HAK、BK35FRC10HAK、BK45FRC10HAK、BK55FRC10HAK、BK70FRC10HSK、BK80FRC10HSK、BK90FRC10HSK、BK100FRC10HSK、BK120FRC10HSK、BK145FRC10HSK、BK165FRC10HSK、BK180FRC10HSK电液比例开环控制柱塞泵主要是在传统的液压泵基础上&#xff0c;增加了电液比例控制先导阀。…

git基本使用(一):git的基本概念

Git 是一种分布式版本控制系统&#xff0c;最初由 Linus Torvalds 于 2005 年为 Linux 内核开发。它主要用于跟踪文件的更改&#xff0c;特别是在软件开发过程中&#xff0c;可以帮助团队成员协同工作。它在实际项目开发中&#xff0c;应用非常广泛&#xff0c;我们这一节来掌握…

【web3】分享一个web入门学习平台-HackQuest

前言 一直想进入web3行业&#xff0c;但是没有什么途径&#xff0c;偶然在电鸭平台看到HackQuest的共学营&#xff0c;发现真的不错&#xff0c;并且还接触到了黑客松这种形式。 链接地址&#xff1a;HackQuest 平台功能 学习路径&#xff1a;平台有完整的学习路径&#xff…

博途(TIA Portal)自动化工程软件下载安装,TIA Portal V18软件安装包获取

博途&#xff08;TIA Portal&#xff09;不仅仅是一款自动化工程软件&#xff0c;它更是西门子自动化领域的璀璨明珠。 它能够将西门子的所有自动化产品无缝集成在一起&#xff0c;无论是PLC、人机界面&#xff0c;还是伺服系统、马达、变频器、网络组件等&#xff0c;博途都能…

SMS群发信息API接口安全性有哪些保障方法?

SMS群发信息API接口支持哪些格式&#xff1f;如何使用API接口&#xff1f; SMS群发信息API接口被广泛应用于企业营销、客户服务、身份验证等多个领域。确保SMS群发信息API接口的安全性&#xff0c;已成为企业和开发者们必须重视的问题。AoKSend将探讨几种保障SMS群发信息API接…

容器技术-docker5

一、docker-compose 常用命令和指令 1. 概要 默认的模板文件是 docker-compose.yml&#xff0c;其中定义的每个服务可以通过 image 指令指定镜像或 build 指令&#xff08;需要 Dockerfile&#xff09;来自动构建。 注意如果使用 build 指令&#xff0c;在 Dockerfile 中设置…

前端技术(说明篇)

Introduction ##编写内容&#xff1a;1.前端概念梳理 2.前端技术种类 3.前端学习方式 ##编写人&#xff1a;贾雯爽 ##最后更新时间&#xff1a;2024/07/01 Overview 最近在广州粤嵌进行实习&#xff0c;项目名称是”基于Node实现多人聊天室“&#xff0c;主要内容是对前端界…

【RabbitMQ实战】邮件发送(直连交换机、手动ack)

一、实现思路 二、异常情况测试现象及解决 说明:本文涵盖了关于RabbitMQ很多方面的知识点, 如: 消息发送确认机制 、消费确认机制 、消息的重新投递 、消费幂等性, 二、实现思路 1.简略介绍163邮箱授权码的获取 2.编写发送邮件工具类 3.编写RabbitMQ配置文件 4.生产者发起调用…

8617 阶乘数字和

这是一个关于计算阶乘结果所有位上的数字之和的问题。我们可以通过以下步骤来解决这个问题&#xff1a; 1. 首先&#xff0c;我们需要一个函数来计算阶乘。由于n的范围可以达到50&#xff0c;阶乘的结果可能非常大&#xff0c;所以我们需要使用一个可以处理大整数的数据类型&a…

零成本、高效率:免费可视化工具的魅力所在

在如今这个数据驱动的时代&#xff0c;免费可视化工具越来越受到人们的欢迎。这些工具不仅降低了数据分析的门槛&#xff0c;还为用户提供了强大的功能和极高的灵活性&#xff0c;使得各行各业的人们都能够轻松地利用数据做出明智的决策。首先&#xff0c;免费可视化工具的零成…

软件鉴定测试的工作内容是什么?专业软件鉴定测试报告获取指南

软件鉴定测试是指对软件产品进行全面的检测和评估&#xff0c;以验证其是否符合规定的标准和要求。通过测试&#xff0c;能够发现软件中存在的问题和缺陷&#xff0c;并提供相应的改进建议。在不同的测试阶段&#xff0c;使用不同的测试方法和工具&#xff0c;包括功能测试、性…

智慧公厕系统改变了人们对服务区公厕的看法

在过去&#xff0c;服务区公厕常常给人留下脏乱差的印象&#xff0c;成为人们在长途旅行途中不愿停留的地方。然而&#xff0c;随着智慧科技的不断发展和应用&#xff0c;智慧公厕系统的出现改变了人们对服务区公厕的看法&#xff0c;为公共卫生设施的提升注入了新的活力。 一、…