第二十讲:文件操作

2024-06-08 19:12
文章标签 操作 第二十

本文主要是介绍第二十讲:文件操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第二十讲:文件操作

  • 1.什么是文件
    • 1.1什么是文件
      • 1.1.1程序文件
      • 1.1.2数据文件
    • 1.2二进制文件和文本文件
      • 数据的存储方式
  • 2.流和标准流
    • 2.1流
    • 2.2标准流
  • 3.文件指针
  • 4.文件的打开与关闭
  • 5.文件顺序读写
    • 5.1顺序读写函数介绍
    • 5.2打开和关闭函数
      • 5.2.1fopen函数
      • 5.2.2fclose函数
    • 5.3fgetc函数和fputc函数
      • 5.3.1fgetc函数
      • 5.3.2fputc函数
    • 5.4fputs和fgets函数
      • 5.4.1fputs函数
      • 5.4.2fgets函数
    • 5.5fprintf和fscanf函数
      • 5.5.1fprint函数
      • 5.5.2fscanf函数
    • 5.6fwrite和fread函数
      • 5.6.1fwrite函数
      • 5.6.2fread函数
    • 拓展延申:5.7sprintf和sscanf函数
  • 6.文件的随机读写
    • 6.1fseek函数
    • 6.2ftell函数
    • 6.3rewind函数
  • 7.文件读取结束的判定
  • 8.文件缓冲区

1.什么是文件

如果没有了文件,我们在电脑上所写的程序会存储在电脑的内存中,程序退出,内存回收,我们所写的东西就丢失了,要将数据进行持久保存,就使用了文件

1.1什么是文件

存放在磁盘(硬盘)上的·文件就是文件
但在程序设计中,我们谈论的文件一般有两种:程序文件和数据文件(根据文件功能分类)

1.1.1程序文件

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

1.1.2数据文件

文件包含的内容不一定是程序,还可能是数据运行时读写的数据,在本文中讨论的是数据文件

在之前各讲中处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,然后将结果返回到显示器上
但是我们有时候会把信息输出到磁盘上,当需要的时候再从磁盘中把数据读取到内存中使用,这里处理的就是磁盘上的文件

1.2二进制文件和文本文件

根据数据的组织形式,数据文件被分为二进制文件和文本文件

数据在内存中以二进制的形式存储,如果不加转化地输出到外存中,就是二进制文件
如果要求在外存中以ASCII码形式进行存储,就需要在存储前进行转化,以ASCII码形式存储的文件就是文本文件

数据的存储方式

那么一个数据在文件中是怎么存储的呢?

字符:一律按照它的ASCII码进行存储
数值:即可以使用ASCII码进行存储,也可以使用二进制进行存储

比如整数10000,如果以ASCII码形式进行存储,需要占用5个字节,而以二进制形式进行输出,在磁盘上只占用4个字节
在这里插入图片描述

2.流和标准流

2.1流

我们程序的数据需要输出到各种外部设备,也需要不断从外部设备获取数据,不同外部设备之间输入和输出方式各不相同,为了方便程序员对各种设备进行方便的操作,我们引用了流的概念,也就是说,流的概念允许开发者以统一的方式处理不同类型的输入输出操作,而不需要关心数据的来源或目的地的具体细节
C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的
⼀般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作

2.2标准流

C语言系统在启动的时候,会自动打开三个流:

1.stdin:标准输入流,大多数情况下从键盘输入,scanf函数就是从标准输入流中读取数据
2.stdout:标准输出流,大多数情况输出到显示器界面,printf函数就是将信息输出到标准输出流中
3.stderr:标准错误流,大多数情况输出到显示器界面,与标准输出流不同,标准错误流常常发送需要立即注意的信息

这三个流的类型是:FILE*,通常称为文件指针
C语言中,就是通过FILE*来维护流的各种操作的

3.文件指针

想要对文件进行操作,文件指针就发挥着重要作用

每个被使用的文件都在内存中开辟了一个文件信息区,用来存放文件的相关信息(文件名称、文件状态、文件所在位置等),结构体有着这种存储能力,该结构体由系统命名,为FILE

如:VS2013中就有类似的声明:

struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_tmpfname;
};
typedef struct _iobuf FILE;

既然有了这个结构体,那么就可以使用一个指针来指向它,甚至访问、维护它,那么我们就来创建一个结构体指针变量:

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

4.文件的打开与关闭

文件在使用之前需要先打开,使用之后需要记得关闭

ANSI C规定,使用fopen来打开文件,使用fclose来关闭文件
而在打开文件的同时,都会返回一个FILE*类型的指针变量指向该文件,也相当于建立了指针和变量的关系

//打开⽂件
FILE* fopen(const char* filename, const char* mode);//关闭⽂件
int fclose(FILE* stream);

mode表示文件的打开模式,打开模式如下:
在这里插入图片描述
我们来看一个示例:

//示例
int main()
{FILE* pa = fopen("myfile.txt", "w");//打开文件if (pa != NULL){fputs("fopen example", pa);//使用完要关闭文件fclose(pa);}return 0;
}

5.文件顺序读写

5.1顺序读写函数介绍

在这里插入图片描述
上面说的适用于所有输⼊流⼀般指适⽤于标准输⼊流和其他输入流(如文件输入流);
所有输出流⼀般指适⽤于标准输出流和其他输出流(如文件输出流)

5.2打开和关闭函数

它们都被包含在头文件<stdio.h>中

5.2.1fopen函数

函数原型:

FILE *fopen( const char *filename, const char *mode );

函数参数:
filename:要打开的文件的名称
mode:打开模式,在上面有
函数返回值:
成功时返回一个指向FILE对象的指针(returns a pointer to the open file)
失败时返回NULL,并设置errno全局变量

函数使用:

//函数使用
int main()
{FILE* pa = fopen("myfile.txt", "w");//对于文件,要提供正确的文件名称,保证文件是能够被打开的//使用之前要注意检查返回值是否为空if (pa == NULL){perror("fopen");//如果为空,可以使用perror函数来进行报错处理return 1;}else{fputs("fopen example", pa);}//最后要记得关闭文件fclose(pa);pa = NULL;return 0;
}

5.2.2fclose函数

函数原型:

int fclose( FILE *stream );

函数参数:
stream:指向FILE类型的指针,这个FILE对象通常由fopen函数返回
函数返回值:
如果流成功关闭,返回0
如果出错,返回EOF表示

函数使用:

//函数使用
int main()
{FILE* pa = fopen("myfile.txt", "w");//对于文件,要提供正确的文件名称,保证文件是能够被打开的//使用之前要注意检查返回值是否为空if (pa == NULL){perror("fopen");//如果为空,可以使用perror函数来进行报错处理return 1;}else{fputs("fopen example", pa);}//最后要记得关闭文件if (fclose(pa)){perror("Error Closing File");//最好有错误检测,看是否成功关闭了文件return -1;}//fclose(pa); //多次关闭文件是未定义的pa = NULL;return 0;
}

5.3fgetc函数和fputc函数

它们都包含在头文件<stdio.h>中

5.3.1fgetc函数

函数原型:

int fgetc( FILE *stream );

函数参数:
stream:指向FILE结构的指针,表示要读取的文件流
函数返回值:
成功时,返回读取的字符,然后,将函数相关的文件指针加1,也就是让它指向下一个字符,如果流位于文件末尾,则设置流的文件结束指示符,也就是返回EOF
失败时,返回EOF

函数使用:

//fgetc函数
int main()
{//肯定要先打开一个文件FILE* pa = fopen("myfile.txt", "r");//先检查pa是否为空if(pa != NULL){int a;while ((a = fgetc(pa)) != EOF)//这时可以进行检查是否为EOF看是否到文件末尾或出错{printf("%c ", a);}//记得关闭文件fclose(pa);pa = NULL;}return 0;
}

5.3.2fputc函数

函数原型:

int fputc( int c, FILE *stream );

函数参数:
c:表示要写入的字符,作为int类型传递
stream:表示要写入的文件流
函数返回值:
成功时,返回写入的字符,并将文件指针的位置向后移动一个字符,以指向下一个字符
失败时,返回EOF

函数使用:

//fputs函数使用
int main()
{FILE* pa = fopen("myfile.txt", "w");if (pa == NULL)return 1;else{int a = fputc('w', pa);if (a != EOF)putchar(a);a = fputc('x', pa);if (a != EOF)putchar(a);}fclose(pa);pa = NULL;return 0;
}

5.4fputs和fgets函数

5.4.1fputs函数

函数原型:

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

函数参数:
string:要写入的字符串
stream:表示要写入的文件流
函数返回值:
成功时,返回非负值(可以为0,且一般为0)
失败时,返回EOF

函数使用:

int main()
{FILE* pa = fopen("example.txt", "w");if (pa == NULL){perror("fopen");return 1;}else{fputs("abcdef", pa);fputs("ghi", pa);//文件中存储的是abcdefghi,它们是连在一起的,如果想要它们在两行上,可以进行更改:fputs("abcdef\n", pa); //要自己添加\n换行符fputs("ghi\n", pa);}fclose(pa);也可以对此进行判断//if (fclose(pa) == EOF)//{//	perror("fclose");//	return -1;//}pa = NULL;return 0;
}

5.4.2fgets函数

函数原型:

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

1.函数参数:
string:指向存储读取出的字符串的指针,用于存储从文件中读取出的字符串
n:指定最多可以从文件中读取出的字符数,包括空字符\0
stream:表示目标文件
返回值:
成功时,返回str的头指针,如果在读取过程中遇到了文件末尾,那么会设置eof指示符
失败时,也就是当未读取字符串时遇到文件结尾,或发生读取错误时,返回NULL

函数使用:
使用1

//函数的一般使用
int main()
{//文件中存储的是hello worldFILE* pa = fopen("example", "r");char arr[20];if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{fgets(arr, 10, pa);}fclose(pa);pa = NULL;return 0;
}

当要文件中的总字符数大于设置读取的字符数时,读取的字符数为n-1,因为要存储一个\0
在这里插入图片描述
使用2,当文件中这样存储时:
在这里插入图片描述

int main()
{FILE* pa = fopen("example", "r");char arr[20];if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{fgets(arr, 10, pa);printf("%s", arr);}fclose(pa);pa = NULL;return 0;
}

当我们要读取10个字符时,函数只会将一整行的数据读取,这也是为什么它叫文本输出函数了,然后它会读取\n,所以,当我们进行打印时,打印出的效果也会加上\n

在这里插入图片描述
所以对于多行,我们需要通过循环多次使用函数来读取:

int main()
{FILE* pa = fopen("example", "r");char arr[20];if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{while (fgets(arr, 10, pa) != NULL)printf("%s", arr);}fclose(pa);pa = NULL;return 0;
}

5.5fprintf和fscanf函数

5.5.1fprint函数

函数原型:

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

函数参数:
stream:要写入的目标文件流
formate:格式字符串,%d,%s,%c等等都是格式
…:可变参数列表,包含的是要进行输出的数据,包含变量指针
函数返回值:
成功时,返回写入的字符的个数
失败时,返回一个负数

函数的使用:

int main()
{FILE* pa = fopen("example", "w");char arr[20];if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{fprintf(pa, "Example:%s", "hello world");//文件中存储的是:Example:hello world}fclose(pa);pa = NULL;return 0;
}

当然,我们可以通过结构体更明显地看出格式化输出的作用:

struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu S;FILE* pa = fopen("example.txt", "w");if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{fprintf(pa, "%s %d %f", "zhangsan", 20, 66.6);}fclose(pa);pa = NULL;return 0;
}

5.5.2fscanf函数

函数原型:

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

函数参数:
stream:要读取的文件流
formate:格式字符串
…:可变参数列表,包含变量的指针
函数返回值:
成功时,返回读取的数据个数
失败是,也就是没有读取任何数据之前,遇到了文件末尾,或者读取发生错误(非法格式或读取错误),返回EOF

函数使用:

int main()
{struct Stu S = { 0 };FILE* pa = fopen("example.txt", "r");if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{int ret = fscanf(pa, "%s %d %f", S.name, &S.age, &S.score);//此处要记得&printf("%s %d %f\n", S.name, S.age, S.score);printf("%d", ret);}fclose(pa);pa = NULL;return 0;
}

结果如下:
在这里插入图片描述

5.6fwrite和fread函数

5.6.1fwrite函数

函数原型:

在这里插入图片描述

函数参数:
buffer:要写入数据的指针
size:接受输出的每个数据大小
count:要输出的数据的数量
stream:要写入的文件流
函数返回值:
成功时,返回写入数据项的个数
如果返回值小于count,表示操作可能发生了错误或未完成

函数使用:

int main()
{FILE* pa = fopen("example.txt", "wb");//注意这里要使用wb,因为写入的是二进制数据char arr[] = "hello world";if (pa == NULL){perror("FILE OPEN FILED");return 1;}else{fwrite(arr, sizeof(char), strlen(arr), pa);}fclose(pa);pa = NULL;return 0;
}

使用结构体:

struct S
{int age;char name[20];char sex[5];
};int main()
{struct S L = { 20,"李四","女" };FILE* pf = fopen("example.txt", "wb");//二进制输出时用wbif (pf == NULL){perror("fopen");return 1;}fwrite(&L, sizeof(struct S), 1, pf);if (fclose(pf) == EOF){//关闭失败perror("fclose");return 1;}pf = NULL;return 0;
}

5.6.2fread函数

函数原型;
在这里插入图片描述

函数参数:
1.buffer:要存储数据的指针
2.size:每个元素的大小,单位是字节
3.count:要读取的元素数量
4.stream:文件指针,指向要读取的文件
函数返回值:
函数返回读取成功的元素的数量,如果返回值小于count,可能是由于已经达到了文件末尾或发生错误

函数使用:

struct S
{int age;char name[20];char sex[5];
};int main()
{struct S L = { 20,"李四","女" };FILE* pa = fopen("text.txt", "rb");//二进制输入时用rbif (pa == NULL){perror("fopen");return 1;}fread(&L, sizeof(struct S), 1, pa);//使用fread函数能够读取二进制值printf("%d %s %s", L.age, L.name, L.sex);if (fclose(pa) == EOF){perror("fclose");return 1;}pa = NULL;return 0;
}

拓展延申:5.7sprintf和sscanf函数

我们直接将两个函数对比着看:

函数原型:
在这里插入图片描述
在这里插入图片描述

1.sprintf函数用于将格式化的数据写入到字符串中
2.sscanf函数用于从字符串中按照指定的格式解析数据
函数返回值:
1.sprintf函数返回成功写入到字符串中的字符数,不包括字符换末尾的\0,但是,对于字符串的写入,要遇到\0才停止写入,所以\0还是很有必要的
2.sscanf函数返回成功解析的项数,如果返回值小于请求的项数,可能是由于格式不匹配或达到字符串末尾

函数使用:

struct S
{int age;char name[20];float point;
};int main()
{struct S s = { 15, "lisi", 88.8f };char arr[20];//将各种数据转换成字符串int ret = sprintf(arr, "%d %s %f", s.age, s.name, s.point);//int sprintf(char* buffer, const char* format[, argument] ...);//函数参数://buffer:用于存储格式化后的字符串//formate:参数的格式//...:可变参数列表,包含了要被格式化的数据printf("%s\n", arr);printf("%d\n", ret);//将字符串中的数据按照格式化传入一个新的结构体变量中struct S m;sscanf(arr, "%d %s %f", &m.age, m.name, &m.point);//注意:要加上&符号//int sscanf( const char *buffer, const char *format [, argument ] ... );//函数参数://buffer:指向包含输入数据的字符串指针//formate:格式化字符串,定义如何分析字符串//...:可变参数列表 printf("%d %s %f", m.age, m.name, m.point);return 0;
}

运行结果:
在这里插入图片描述

6.文件的随机读写

6.1fseek函数

函数原型:

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

该函数是用来在文件中移动文件指针的位置

函数参数:
1.stream:文件指针
2.offset:要移动的字节数,可正可负,分别表示向前\后进行移动
3.origin:表示offset参数的起始点,有三种类型:
SEEK_SET:表示从文件开头开始计算
SEEK_CUR:表示从当前位置开始计算
SEEK_END:表示从文件末尾开始计算

函数使用:
假设我们的目标文件为:example.txt,文件中存储的数据为:
在这里插入图片描述
那么我们看下面的代码:

int main()
{FILE* pa = fopen("example.txt", "r");if (pa == NULL){perror("fopen");return 1;}int ret1 = fgetc(pa);printf("ret1 = %c\n", ret1);//结果为afseek(pa, 2, SEEK_SET);int ret2 = fgetc(pa);printf("ret2 = %c\n", ret2);//结果为cfclose(pa);pa = NULL;return 0;
}

6.2ftell函数

函数原型:

long ftell( FILE *stream );

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

函数参数:
该函数只有一个参数,就是文件指针
函数返回值:
成功时,返回一个非负的长整形值,表示文件指针距起始位置的偏移量
失败时,返回-1L

函数使用:

int main()
{FILE* pa = fopen("example.txt", "r");if (pa == NULL){perror("fopen");return 1;}int ret1 = fgetc(pa);printf("ret1 = %c\n", ret1);fseek(pa, 4, SEEK_SET);int re = ftell(pa);printf("re = %d\n", re);//结果为4fclose(pa);pa = NULL;return 0;
}

6.3rewind函数

函数原型:

void rewind( FILE *stream );

该函数是让文件指针的位置返回到起始位置的函数

函数参数:
很简单,只有一个文件指针
函数返回值:
函数没有返回值

函数使用:

int main()
{FILE* pa = fopen("example.txt", "r");if (pa == NULL){perror("fopen");return 1;}int ret1 = fgetc(pa);printf("ret1 = %c\n", ret1);//结果是afseek(pa, 4, SEEK_SET);//改变文件指针的位置rewind(pa);//再将文件指针的位置指向起始位置int ret2 = fgetc(pa);printf("ret2 = %c\n", ret2);//结果还应该是afclose(pa);pa = NULL;return 0;
}

7.文件读取结束的判定

在C语言中,我们可以使用feof函数来判断文件读取结束的原因是否是遇到文件结尾
函数原型:

int feof( FILE *stream );

函数参数:
文件指针
函数返回值:
如果stream指向的文件流已经到达文件结尾,返回非0值(通常为1)
如果没有到达文件末尾,返回0

函数使用:

int main()
{FILE* pa = fopen("example.txt", "r");if (pa == NULL){perror("fopen");return 1;}int c; // 注意:int,⾮char,要求处理EOF//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((c = fgetc(pa)) != EOF) // 标准C I/O读取⽂件循环{putchar(c);}//判断是什么原因结束的if (ferror(pa))//ferror函数参数和feof函数相同,如果检测到错误,函数返回非0值,否则返回0puts("I/O error when reading");else if (feof(pa))puts("End of file reached successfully");fclose(pa);pa = NULL;return 0;
}

对于ferror函数,检测到错误后会将错误标志设置为非0,如果需要再次使用ferror函数检测后续操作的错误,需要先调用clearerr函数来清除错误标志

8.文件缓冲区

ANSIC标准采用”操作文件系统“来处理数据文件,其功能其实就是系统会自动地为程序中每一个正在使用的文件开辟一块”文件缓冲区“,从内存向磁盘输入的数据都会先送到内存中的缓冲区,缓冲区填满后才将缓冲区中的数据写入磁盘
如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的⼤⼩根据C编译系统决定的。原理如下:

在这里插入图片描述
我们可以写一个程序观察缓冲区的存在:

// VS2022 WIN11环境测试
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语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。

这篇关于第二十讲:文件操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1043064

相关文章

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

Java Multimap实现类与操作的具体示例

《JavaMultimap实现类与操作的具体示例》Multimap出现在Google的Guava库中,它为Java提供了更加灵活的集合操作,:本文主要介绍JavaMultimap实现类与操作的... 目录一、Multimap 概述Multimap 主要特点:二、Multimap 实现类1. ListMult

Python中文件读取操作漏洞深度解析与防护指南

《Python中文件读取操作漏洞深度解析与防护指南》在Web应用开发中,文件操作是最基础也最危险的功能之一,这篇文章将全面剖析Python环境中常见的文件读取漏洞类型,成因及防护方案,感兴趣的小伙伴可... 目录引言一、静态资源处理中的路径穿越漏洞1.1 典型漏洞场景1.2 os.path.join()的陷

Python使用Code2flow将代码转化为流程图的操作教程

《Python使用Code2flow将代码转化为流程图的操作教程》Code2flow是一款开源工具,能够将代码自动转换为流程图,该工具对于代码审查、调试和理解大型代码库非常有用,在这篇博客中,我们将深... 目录引言1nVflRA、为什么选择 Code2flow?2、安装 Code2flow3、基本功能演示

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

python操作redis基础

《python操作redis基础》Redis(RemoteDictionaryServer)是一个开源的、基于内存的键值对(Key-Value)存储系统,它通常用作数据库、缓存和消息代理,这篇文章... 目录1. Redis 简介2. 前提条件3. 安装 python Redis 客户端库4. 连接到 Re

Java Stream.reduce()方法操作实际案例讲解

《JavaStream.reduce()方法操作实际案例讲解》reduce是JavaStreamAPI中的一个核心操作,用于将流中的元素组合起来产生单个结果,:本文主要介绍JavaStream.... 目录一、reduce的基本概念1. 什么是reduce操作2. reduce方法的三种形式二、reduce

MySQL表空间结构详解表空间到段页操作

《MySQL表空间结构详解表空间到段页操作》在MySQL架构和存储引擎专题中介绍了使用不同存储引擎创建表时生成的表空间数据文件,在本章节主要介绍使用InnoDB存储引擎创建表时生成的表空间数据文件,对... 目录️‍一、什么是表空间结构1.1 表空间与表空间文件的关系是什么?️‍二、用户数据在表空间中是怎么

Python对PDF书签进行添加,修改提取和删除操作

《Python对PDF书签进行添加,修改提取和删除操作》PDF书签是PDF文件中的导航工具,通常包含一个标题和一个跳转位置,本教程将详细介绍如何使用Python对PDF文件中的书签进行操作... 目录简介使用工具python 向 PDF 添加书签添加书签添加嵌套书签Python 修改 PDF 书签Pytho