文件操作讲解

目录

一.为什么使用文件

二.什么是文件

2.1程序文件

2.2数据文件  

2.3文件名

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

fwrite函数

fclose函数 

 四.文件的打开和关闭 

4.1流和标准流 

4.2文件指针

4.3文件的打开和关闭

五.文件的顺序读写

5.1文件的顺序读写函数

5.1.1fgetc函数

5.1.2fputc函数

 5.1.3fgets函数

5.1.4fputs函数

5.2scanf和printf

5.2.1fscanf函数

 5.2.2sprintf函数

六.文件的随机读写

6.1fseek函数 

6.2ftell函数

 6.3rewind函数

七.文件读取结束的判定

 1.文本文件

 2.二进制文件

八.文件缓冲区 


一.为什么使用文件

如果没有文件,我们写的程序数据是储存在内存中的,一旦程序结束,内存回收,数据就没有了,再次运行程序,上次写的程序就消失了,如果我们要将数据持久化,我们就可以使用文件了。

二.什么是文件

在程序设计中,我们讨论的文件一般有两种:程序文件,数据文件(从文件的功能的角度来分类)

2.1程序文件

程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows 环境后缀为.exe)。

2.2数据文件  

⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。

2.3文件名

⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤。 

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

为了⽅便起⻅,⽂件标识常被称为⽂件名。 

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

根据数据的形式,数据文件被分为文本文件或者二进制文件

二进制文件:数据在内存中以二进制的形式存储,不加以转换的输出到外存的文件 。

文本文件:数据在内存中以二进制的形式存储,要求在外存上以ASCII码的形式存储,ASCII字符的形式存储的文件就是文本文件。

如何判断一个数据在文件中是怎么存储的呢?
字符一律以ASCII码值的形式存储,数值型数据即可以用ASCII形式存储,也可以使用二进制的形式进行存储。

比如整数10000,如果以ASCII形式存储,则磁盘中占用5个字节(每一个字符一个字节),而以二进制的形式进行输出,则在磁盘上只占4个字节。

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h>
int main()
{int a = 10000;	FILE* pf = fopen("text.txt","wb");if (pf == NULL)//如果文件打开失败返回NULL;{perror("fopen");return 1;}fwrite(&a,4,1,pf);fclose(pf);pf = NULL;return 0;
}

fopen函数:以二进制的写(“wb”)的形式打开text.txt文件.
如果项目路径下没有这个文件,就会自动创建一个这样的文件.并且返回一个文件指针 

fwrite函数

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

 这个函数的功能就是将数据写入一个文件中。

  1. ptr指向一个数组.这个数组就是我们要写入的数据。
  2. count指的是我们需要写入的数组的元素个数。
  3. size指的是数组元素的大小。
  4. 我们需要写入的这个文件的文件指针。
  5. 返回值是成功写入的元素个数

fclose函数 

在我们打开文件后,使用完成,就需要关闭这个文件,fclose这个函数是用于这个的,并且为了防止非法访问,我们还需要将文件指针置为空指针,避免野指针。

综上:

我们上面的代码就是打开了一个叫做text.txt的文件,并且以二进制的形式写入了一个数据a。 

这个文件可在我们的项目路径下看到。 

 因为a是一个整形占四个字节,所以参数2是4。

正常来说,我们运行程序后,我们点击项目文件中的text.txt文件,我们发现我们无法看懂写了什么,是乱码。

这是因为这个文件是二进制的文件,在vs2022中,我们把这个文件添加到解决方案资源管理器中

 

点击完现有项,再把这个文件添加进去。

在打开方式中选择二进制编辑器

这样我们就打开了这个文件 

 

前面的00000000不用管,后面的10 27 00 00 就是我们写入的数据,我们会发现这不是二进制的,其实是因为二进制的形式过于长了,所以采用十六进制,而且2个字符就是一个字节,更加方便。

我们存入的数据是10000,为什么显示10 27 00 00 呢?

我的这个机器是小端字节序存储,10000的二进制是00002710,所以int a的第一个字节是10 ,第二个字节是27,再进行写入数据的时候,是一个字节一个字节的写的,所以第一个是10,然后再是27. 

 四.文件的打开和关闭 

4.1流和标准流 

我们的程序的数据需要输出到各种外部的设备 ,也需要从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们把流想象成流淌着字符的河流

C程序针对文件,画面,键盘等数据的输入输出操作都是通过流操作的。

一般情况下,我们想要向流里写数据或者从流中读取数据,都是要打开流的,然后操作。

那为什么我们从键盘上输入数据,向屏幕上输出数据,并没有打开流呢?

那是因为C语言程序默认打开了3个流:

  1. stdin:标准输入流,在大多数情况下,从键盘输入,scanf函数就是从标准输入流中读取数据的
  2. stdout:标准输出流,在大多数情况下,输出至显示器界面,printf就是将信息输出到标准输出流中。
  3. srderr:标准错误流,大多数环境输出到显示器界面。

这三个流的类型都是FILE*,通常也叫做文件指针。

4.2文件指针

缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名 FILE.

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

一般都是通过一个FILE的文件指针来维护这个FILE的结构变量,这样使用起来更加方便。

FILE * pf;

这个pf的变量指向这个文件的文件信息区,通过这个文件的文件信息区就能够访问该文件,也就是说,通过文件指针变量能够间接找到与它相关联的文件了。

4.3文件的打开和关闭

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

在编写程序的时候,我们使用fopen函数打开这个文件,这个函数会返回一个FILE*的指针变量指向这个文件,也相当于建立了指针和文件的关系。

ASCI C规定使用fopen函数打开文件,fclose函数来关闭文件。

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

 filename就是文件名主干和后缀名,mode就是打开的方式

int fclose ( FILE * stream );

 stream就是流,也就是文件指针。

mode表示文件的打开方式

文件的使用方式含义如果指定的文件不存在
"r"只读,为了读取数据,打开一个已经存在的文本文件出错
"w"只写,为了写入数据,打开一个的文本文件创建一个新的文件
"a"追加,在文件的末尾追加数据,打开一个文本文件创建一个新的文件
"rb"只读,为了读取数据,打开一个二进制文件出错
"wb"只写,为了写入数据,打开一个二进制文件创建一个新的文件
"ab"追加,在二进制文件末尾添加数据创建一个新的文件
"r+"读写,打开一个文本文件出错
"w+"读写,打开一个文本文件创建一个新的文件
"a+"读写,在文件的末尾进行读写创建一个新的文件
"rb+"读写,打开了二进制文件出错
"wb+"读写,打开一个二进制文件创建一个新的文件
"ab+"读写,打开一个二进制文件创建一个新的文件
  1. r是读(read),w是写(write),a是追加(append)
  2. 所有只能读的文件,如果不存在,就会报错。而写和追加就会创建新的文件
  3. b是二进制的意思(binary)
  4. 后面有+,就是既可以读又可以写。

实例代码:

#include<stdio.h>
int main()
{FILE* pf = fopen("text.txt","w");if (pf == NULL) {perror("fopen");return 1;};fputs("file open example",pf);fclose(pf);pf = NULL;return 0;
}

五.文件的顺序读写

5.1文件的顺序读写函数

观察下面这个代码:

	//打开文件FILE* pf = fopen("text.txt","w");if (pf == NULL){perror("fopen");return 1;}//访问文件char arr[10] = "abcde";fwrite(arr,1,5,pf);//关闭文件fclose(pf);pf = NULL;

当我们打开这个txt文件,我们发现fwrite就向这个文件中写了五个字符abcde。

5.1.1fgetc函数

 函数原型:

int fgetc ( FILE * stream );

这个函数的功能是从流中获得字符。返回又文件中的光标所指向的字符 。

在我们运行完上面的的代码后,我们再次运行以下代码.

	int ch1 = fgetc(pf);int ch2 = fgetc(pf);int ch3 = fgetc(pf);printf("%c %c %c ", ch1, ch2, ch3);

我们发现输出结果是 a b c,为什么呢?

这是因为 指定流的内部文件位置指示器,最开始是在开头的,每一次调用函数后,它的位置会往后移动一个字符,所以会依次打印a b c。

当遇到文件末尾和读取失败的时候,这个函数会返回EOF.

如果需要打印完整个文件就可以采用循环的方式

	int ch = 0;while ((ch = fgetc(pf)) != EOF){printf("%c", ch);}

5.1.2fputc函数

函数原型:

int fputc ( int character, FILE * stream );

这个函数的功能就是将字符写到流中,并且使位置指示器前进一个字符。

	//写文件fputc('a',pf);fputc('b',pf);fputc('c',pf);//读文件int ch = 0;while ((ch = fgetc(pf)) != EOF){printf("%c", ch);}

在这个文件中显示的就是abc

在文件中打印26个字母:

	for(char ch = 'a'; ch <= 'z';ch++){fputc(ch,pf);}

 5.1.3fgets函数

fgetc是从流中得到字符,fgets就是从流中得到字符串

函数原型:

char * fgets ( char * str, int num, FILE * stream );

得到的字符串需要放在一个字符数组中,第一个参数就是数组名。

第二个参数是我们需要读取的字符个数。

第三个就是流

	char str[26] = { 0 };fgets(str,26,pf);printf(str);

运行这个代码输出结果是 

这是我们刚刚输入的26个字母。但是我们发现少了字符'z'。

通过调试我们发现 

 

这个字符数组的最后一个字符不是'z',而是'\0'。

这是因为fgets这个函数会默认给最后一个字符补上'\0',所以如果我们想完整打印出26个字母,参数2就不应该是26而应该是27,因为字符串的末尾均是'\0',所以需留'\0'。

这个函数在进行读取的时候,在遇到第num-1 个字符,和新的一行,或者文件末尾,均会停止读取,但是不会影响函数功能。前面读取的字符不会收到影响。

注意:在遇到换行符时,这个符号仍然会被包含进这个数组中。

5.1.4fputs函数

这个函数和fputc函数很相似。

函数原型:

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

 写一个字符串到流中去。

参数1就是字符串。

	fputs("hello world",pf);

运行这个代码,我们就可以在文件看到hello world.注意末尾的'\0'是不会被写到流中去的。

5.2scanf和printf

5.2.1fscanf函数

我们知道scanf是从键盘上读取格式化的数据

那么fscanf就是从文件中读取格式化的数据

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

这个函数的函数原型与scanf几乎一模一样,只不过多了一个文件指针而已。

//定义一个结构体
struct stu
{char name[10];int age;int score;
};

在文件中输入张三 18 99

再运行以下代码

	struct stu student;fscanf(pf, "%s %d %d", student.name,&(student.age),&(student.score));printf("%s %d %d ",student.name,student.age,student.score);

输出结果就是张三 18 99.

 sscanf也是同理,从字符串中读取数据,本文只涉及文件相关内容,想要了解的读者,可以自行了解:sscanf - C++ Reference

 5.2.2sprintf函数

函数原型:

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

这个函数同理与printf函数类似,多了一个文件指针。从在屏幕上打印变成了在文件中打印

	struct S s = { "李四",28,95};fprintf(pf, "%s %d %d\n", s.name, s.age, s.score);

这样我们就可以在文件中看到这个结构体的信息。当然其实也是可以在屏幕上打印的。

stdout就是标准输出流,把文件指针写成stdout就可以在屏幕上打印,起到和printf一样的效果。

同理前面的函数也可以使用

int main()
{fputc('a', stdout);return 0;
}

这样就会在屏幕上打印a.

六.文件的随机读写

6.1fseek函数 

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

 这个函数的功能就是改变位置指示器的位置。

参数1是文件指针

参数2是偏移量

参数3有三种文件开头,文件末尾,和位置指示器当前位置

SEEK_SET就是文件开头,SEEK_END是文件末尾,SEEK_CUR是当前位置。

例:

	FILE* pf = fopen("test.txt","wb");fputs("This is an apple.",pf);fseek(pf,9,SEEK_SET);fputs(" sam",pf);

这个代码的作用就是将位置指示器从文件开头偏移9个字符。

This is an apple.

偏移9个字符后,位置指示器的位置就到了第一个字符a的后面,然后打印" sam".

在我们写代码的过程中,我们快速并且准确的知道当前 位置指示器的位置,那怎么办呢?
这时候就需要用到第二个函数

6.2ftell函数

long int ftell ( FILE * stream );

这个函数会返回在流中的位置指示器相对于起始位置的偏移量。

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

偏移量的值是可以为0也可以为负和正的,正就是向右移动,负就是向左,0是原位置。 

这个代码计算了这个文件有多少个字节。

 6.3rewind函数

void rewind ( FILE * stream );

这个函数会将流的位置设置到文件开头。 

 例子:

#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';printf(buffer);return 0;
}

使用fseek函数也可以达到相同的效果

	fseek(pFile,0,SEEK_SET);

七.文件读取结束的判定

feof的作用是当文件读取结束的时候,判断文件读取结束的原因是不是遇到文件结尾而结束的。

ferror的作用是当文件读取结束的时候,判断文件读取结束的原因是不是发生错误而结束的。

 1.文本文件

文本文件的读取结束,判断返回值是否为EOF(fgetc函数),判断是否等于NULL(fgets)

 2.二进制文件

判断返回值是否小于实际要读取的个数(fread函数)

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int c; // 注意:int,⾮char,要求处理EOFFILE* fp = fopen("test.txt", "r");if (!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取⽂件循环{putchar(c);}//判断是什么原因结束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);
}
#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code == SIZE) {puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n)printf("%f ", b[n]);putchar('\n');}else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);
}

八.文件缓冲区 

ANSIC 标准采⽤“缓冲⽂件系统” 处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的⼤⼩根据C编译系统决定的。
#include <stdio.h>
#include <windows.h>
//VS2019 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.mzph.cn/news/791697.shtml

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

相关文章

【软件工程】概要设计

1. 导言 1.1 目的 该文档的目的是描述学生成绩管理系统的概要设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统结构简介 系统接口设计 数据设计 模块设计 界面设计 本文的预期读者是&#xff1a; 项目开发人员 项目管理人员 项目评测人员&#xff08;…

VS2022使用属性表快速设置OpenCV工程属性

1.创建C++控制台应用 2.配置工程 3.打开工程后,为工程添加属性表 打开属性管理器窗口,选择Debug|x64 然后右击选择添加新的项目属性表 并命名为opencv490_debug_x64 点击添加 Debug版本属性表添加成功 使用相同方法添加Release版本属性表

Windows通过git配置github代码仓库全流程

git git是代码的版本控制工具 git安装和github注册 这个默认弄过了 通过git和github之间的SSH配置 在github上面新建仓库&#xff0c;做好配置 git绑定GitHub账号 先cd到上传的文件所在的目录 git config --global user.name "你的github用户名"git config -…

网络原理 - HTTP / HTTPS(3)——http响应

目录 一、认识 “状态码”&#xff08;status code&#xff09; 常见的状态码 &#xff08;1&#xff09;200 OK &#xff08;2&#xff09;404 Not Found &#xff08;3&#xff09;403 ForBidden &#xff08;4&#xff09;405 Method Not Allowed &#xff08;5&…

基于java实现的弹幕视频网站

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示自定义字符应用

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864显示自定义字符应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD12864简单介绍一、LCD…

使用ffmpeg将视频解码为帧时,图像质量很差

当使用ffmpeg库自带的ffmpeg.exe对对视频进行解帧或合并时&#xff0c;结果质量很差。导致这种原因的是在使用ffmpeg.exe指令进行解帧或合并时使用的是默认的视频码率&#xff1a;200kb/s。 如解帧指令&#xff1a; ffmpeg.exe -i 600600pixels.avi -r 2 -f image2 img/%03d.…

深度学习arm cache系列--一篇就够了

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; 1. cache的基本概念介绍 1.1、为什么要用cache? ARM 架构刚开始开发时&#xff0c;处理器的时钟速度和内存的访问速度大致相似。今天的处理器内核要复杂得多&#xff0c;并且时…

【基于HTML5的网页设计及应用】——-正则表达式.

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

ctf_show笔记篇(web入门---SSRF)

ssrf简介 ssrf产生原理&#xff1a; 服务端存在网络请求功能/函数&#xff0c;例如&#xff1a;file_get_contens()这一类类似于curl这种函数传入的参数用户是可控的没有对用户输入做过滤导致的ssrf漏洞 ssrf利用: 用于探测内网服务以及端口探针存活主机以及开放服务探针是否存…

C语言交换二进制位的奇数偶数位

基本思路 我们要先把想要交换的数的二进制位给写出来假如交换13的二进制位&#xff0c;13的二进制位是 0000 0000 0000 0000 0000 0000 0000 1101然后写出偶数位的二进制数&#xff08;偶数位是1的&#xff09; 1010 1010 1010 1010 1010 1010 1010 1010然后写出奇数位的二进…

uniapp切换中英文

一、安装 npm install uni-i18n --save 二、创建中英文切换的文件 1.英文en.js文件 2.中文zh_CN.js文件 三、 main.js中引用 // Vue i18n 国际化 import VueI18n from /common/vue-i18n.min.js; Vue.use(VueI18n);// i18n 部分的配置&#xff0c;引入语言包&#xff0c;注意路…

Linux :进程的程序替换

目录 一、什么是程序替换 1.1程序替换的原理 1.2更改为多进程版本 二、各种exe接口 2.2execlp ​编辑 2.2execv 2.3execle、execve、execvpe 一、什么是程序替换 1.1程序替换的原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往…

0基础安装配置Linux-ubuntu环境

Vmtools的安装参见 0基础教你安装VM 17PRO-直接就是专业许可证版_vm17许可证-CSDN博客 在vmtools中安装ubuntu 等待安装 这时候发现没有继续按钮&#xff0c;我们关闭这个界面&#xff0c;进入系统中&#xff0c;先更改分辨率 点击这个三角&#xff0c;因为还么有安装成功&am…

【Canavs与艺术】绘制蓝白绶带大卫之星勋章

【图例】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>用Canvas绘制蓝白绶带大卫之星勋章</title><style type&quo…

从 MongoDB 到 PostgreSQL 的大迁移

Infisical&#xff0c;一家做密钥管理的开源商业公司&#xff0c;主要对标的是 HashiCorp Vault Infisical 在过去一年里迅速发展&#xff0c;平台现在每天处理超过 5000 万个密钥&#xff0c;将应用程序配置和私密数据发送给需要的团队、CI/CD 流水线以及服务器 / 应用程序。 …

基于JSP的农产品供销服务系统

背景 互联网的迅猛扩张彻底革新了全球各类组织的运营模式。自20世纪90年代起&#xff0c;中国的政府机关和各类企业便开始探索利用网络系统来处理管理事务。然而&#xff0c;早期的网络覆盖范围有限、用户接受度不高、互联网相关法律法规不完善以及技术开发不够成熟等因素&…

Python如何解决“滑动拼图”验证码(8)

前言 本文是该专栏的第67篇,后面会持续分享python爬虫干货知识,记得关注。 做过爬虫项目的同学,或多或少都会接触到一些需要解决验证码才能正常获取数据的平台。 在本专栏之前的文章中,笔者有详细介绍通过python来解决多种“验证码”(点选验证,图文验证,滑块验证,滑块…

汽车EDI:如何与奔驰建立EDI连接?

梅赛德斯-奔驰是世界闻名的豪华汽车品牌&#xff0c;无论是技术实力还是历史底蕴都在全球汽车主机厂中居于领先位置。奔驰拥有多种车型&#xff0c;多元化的产品布局不仅满足了不同用户画像的需求&#xff0c;也对其供应链体系有着极大的考验。 本文将为大家介绍梅赛德斯-奔驰乘…

在s390x架构机器上构建frps/frpc镜像 —— 筑梦之路

源码&#xff1a;GitHub - fatedier/frp: A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet. # 克隆代码git clone https://github.com/fatedier/frp.git# 切换目录cd frp# 构建frps服务端docker build -t frps:s390x -f …