【Linux】-文件操作(重定向、缓冲区以及Linux下一切皆文件的详解)

在这里插入图片描述

💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、以c语言为例,认识一下之前的接口
  • 二、过度到系统,再谈文件系统调用
  • 三、访问文件的本质
  • 四、重定向的原理介绍
  • 五、理解Linux下一切皆文件。
  • 六、缓冲区
  • 七、总结


前言

今天博主来讲一篇大家以前很害怕的但又不得不说的一个的一个知识点–文件管理,再我们c语言的时候,博主就给大家介绍过文件操作,那时候我们使用过很多函数去对文件操作,而我们又不怎么去使用这些函数,所以又熟悉又陌生,今天我们又把文件拿出来讲,远远不至于之前的哪些内容,博主讲深入系统层面来给大家进行讲解,让大家明白我们之前的函数是怎么去操作的,会解决大家很多疑惑,话不多说我们开始进入正文讲解。


共识原理

  1. 文件=内容+属性
  2. 文件分为打开的文件和没打开的文件
  3. 打开的文件,是谁打开的?? 答案是进程,所以我们后面讨论的是进程和文件的关系
  4. 没打开的文件,在哪放着的?答案是磁盘上。没打开的文件最关注的问题是什么? 答案是没打开的文件很多,这样就要我们把文件分类好,管理起来,就必须先描述在组织才能方便我们后面对文件的增删查改操作,所以在系统里面必须又关于文件管理的属性指针,来指向这样文件,方便管理。
  5. 打开的文件是由进程加载到内存的,一个进程可以打开多个文件所以是1:n的关系,此时进程也需要把他打开的文件管理起来,才知道哪些文件是他自己打开的,最后才有办法关闭。

针对4,5点的管理我们一会再正文部分给大家具体介绍,并画出详细的图。上面的我相信大家应该都可以理解,可以理解为人(进程),快递(文件),驿站(磁盘)的关系。


一、以c语言为例,认识一下之前的接口

我们只看写文件,因为读文件没有什么好看的。再进行一个文件操作的时候,需要先打开一个文件,我们来回顾一下c语言的打开文件操作
在这里插入图片描述

在这里插入图片描述
第一个参数是写入的内容字符串,第二个参数是内容多大,第三个参数是写几个这样的,第四个是要传打开的文件

w方式:

#include<stdio.h>
#include<string.h>
int main()
{
    FILE* fp=fopen("login.txt","w");
    if(fp==NULL)
    {
        perror("fopen");
        return -1;
    }

    const char*msg="hello,file";
    fwrite(msg,strlen(msg),1,fp);
    fclose(fp);
    return 0;
}

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

我们看到效果和我们文档里面是一样的,如果没有的文件会在当前路径自动创建一个,而每次打开文件都会先清空文件,再进行写入,通过第三个图我们也发现和写不写内容没有关系,只要每次重新打开就会情空。

a方式:

#include<stdio.h>
#include<string.h>
int main()
{
    FILE* fp=fopen("login1.txt","a");
    if(fp==NULL)
    {
        perror("fopen");
        return -1;
    }

    const char*msg="hello,file";
    fwrite(msg,strlen(msg),1,fp);
    fclose(fp);
    return 0;
}

在这里插入图片描述

结果和文档的效果是一样的,没有文件就会在当前路径创建新的文件,然后每次打开就会再文件的末尾追加内容。


解决疑惑
(1)在fwrite的时候我们传的strlen(msg),此时需不需要加+1.就是这个\0的长度要不要加上去,我们加一下看看结果:
在这里插入图片描述

我们打开文件发现会出现乱码,说明/0确实被写进去了,因为我们的vim是文本解析器,所以会出现乱码,那我们到底要不要加1呢,答案是不要的,这一看就是不对了,注意:\0是c语言层面的为了给字符串作为结束标志的,而写入文件只需要把有效字符写进去就行了,这个\0和文件是没有关系的,所以不用写进去

(2)fopen的两种方式中博主都提到了当前路径,是怎么做到的,修改当前路径会不会在其他路径下创建,来看演示:
在这里插入图片描述
我们来使用一个系统函数改变当前路径
在这里插入图片描述

博主讲当前路径改成上一级路径,我们发现创建的文件就跑到上一级文件了。可以通过这样的方式来改变当前路径。

---------------------------------------------------------------------------------------------------------------------------------
通过上面介绍的两种方式,我们还能想起来什么??
之前是不是说过重定向,一个输出重定向,一个追加重定向,都是往文件里面写内容,那么可以这样理解,我们的重定向的第一步肯定是要打开文件,输出和追加的区别就是打开方式的不同,但肯定是类似于上面的方式去实现的,再这里大家心里面现有一个印象,这个后面我会再重点谈的。

铺垫:

我们的c语言会默认打开三个FILE类型的文件
在这里插入图片描述
他们在stdio.h里面,这也是我们一开始学习c语言就要包含这个文件的原因

Linux下一切皆文件,所以这三个分别对应的是:键盘文件,显示器文件,显示器文件
我们来使用函数往这些文件里面写点东西

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    const char*msg="hello,file";
    fwrite(msg,strlen(msg),1,stdout);
    return 0;
}

在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    const char*msg="hello,file";
    fprintf(stderr, "%s: %d\n", msg, 1234);
    return 0;
}

在这里插入图片描述
stdin是键盘文件,不好演示的,可以从键盘读取数据,一会回过头来给大家演示。

这三个默认打开的文件我一会再回头过来讲。

二、过度到系统,再谈文件系统调用

再一开始的共识中,博主就说到文件没被打开时候是在磁盘上的,磁盘是外部设备,也就是硬件,所以访问磁盘文件就是再访问硬件,我们的用户通过库函数去打开文件就比如先经过系统调用接口,去让操作系统去访问硬件资源,操作系统不信任任何用户,而os又是管理着硬件资源,所以必须经过os这一关,几乎所有的库只要访问硬件设备,必定要封装系统调用 我们之前学的printf/fprintf/fscanf/fwrite/fread/fgetc/fopen/fclose都需要封装系统调用接口。

(1)打开文件的系统调用接口open
在这里插入图片描述
在这里插入图片描述

这个函数在二号手册,所以属于系统调用函数,调用失败返回-1
我们的第一个参数是打开的文件,第二个参数类似于位图操作,接下来使用一个例子带大家看看这个是什么:

#define ONE (1<<0) // 1
#define TWO (1<<1) // 2
#define THREE (1<<2) // 4
#define FOUR (1<<3) // 8

void show(int flags)
{
    if(flags&ONE) printf("hello function1\n");
    if(flags&TWO) printf("hello function2\n");
    if(flags&THREE) printf("hello function3\n");
    if(flags&FOUR) printf("hello function4\n");
}



int main()
{
    printf("-----------------------------\n");
    show(ONE);
    printf("-----------------------------\n");
    show(TWO);
    printf("-----------------------------\n");

    show(ONE|TWO);
    printf("-----------------------------\n");
    show(ONE|TWO|THREE);
    printf("-----------------------------\n");
    show(ONE|THREE);
    printf("-----------------------------\n");
    show(THREE|FOUR);
    printf("-----------------------------\n");
}


在这里插入图片描述
博主在文档中圈出来的一些宏定义就是表示功能通过声明也大致可以看出大致含义.


第三个参数是类型,给文件设置什么样的权限,默认是666,但是有掩码,我们看到的就是664,如果我们就像让文件变成默认的666,那么就要修改掩码,但是不要修改其他文件的默认,所以需要在打开这个文件的进程里面修改,使用umask函数就可以了。

(2)再来看看写入的函数:
在这里插入图片描述
这个函数其实和库函数有点像,一会看使用,具体参数博主就不做具体介绍了

来具体看看库函数是怎么使用的:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int  main()
{
    umask(0);//设置掩码为0
    //系统的掩码和这里的掩码程序因该听谁的,答案是谁进听谁的,不会更改系统的掩码。
    int fd=open("login2.txt",O_WRONLY,0666);
    if(fd<0)
    {
        perror("open");
        return 0;
    }
    char*msg="hello,fd\n";
    write(fd,msg,strlen(msg));//这个同样不需要加1
    return 0;
}

在这里插入图片描述


为什么没有打开成功呢,原因是打开文件的使用的功能就是O_WRONLY,必须要在加一个功能

  int fd=open("login2.txt",O_WRONLY|O_CREAT,0666);

在这里插入图片描述


(1)实现w的效果

  int fd=open("login2.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);

在这里插入图片描述
(2)实现a的效果
O_APPEND这是追加功能,所以不能和O_TRUNC同时使用,这两个是冲突的。

 int fd=open("login2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);

在这里插入图片描述
我们讲系统调用接口给大家演示了,大家也知道了我们系统调用接口的功能更加的全面,但是此时我不在给大家介绍内容了,我先讲下面一个主题

三、访问文件的本质

我们刚才使用了open这个函数,他的返回值fd,在write里面也需要传fd,那么fd到底是什么,答案是文件描述符(数组的下标)

接下来通过一幅图给大家介绍
在这里插入图片描述
接下来博主在进程里面再多创建几个文件,看看打印出来的fd是什么,和我们预期画图是不是一个效果:

int  main()
{
    umask(0);//设置掩码为0
    int fd=open("login2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd1=open("login3.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd2=open("login4.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd3=open("login5.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd4=open("login6.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    if(fd<0)
    {
        perror("open");
        return 0;
    }
    printf("fd:%d\n",fd);
    printf("fd1:%d\n",fd1);
    printf("fd2:%d\n",fd2);
    printf("fd3:%d\n",fd3);
    printf("fd4:%d\n",fd4);
    return 0;
}

在这里插入图片描述

umask(0);//设置掩码为0

    close(0);//这个一会再说
    int fd=open("login2.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd1=open("login3.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd2=open("login4.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    int fd3=open("login5.txt",O_WRONLY|O_CREAT|O_APPEND,0666);
    printf("fd:%d\n",fd);
    printf("fd1:%d\n",fd1);
    printf("fd2:%d\n",fd2);
    printf("fd3:%d\n",fd3);
    return 0;

在这里插入图片描述

确实和我们分析的一样。会再数组里面找没有使用并且下标最小的位置讲打开的文件信息填进去

提出疑问:回顾铺垫
我们的0 1 2这三个下标呢??大家还记不记得上面的铺垫,我们的c语言程序默认打开第三个文件,那这三个下标会不会就对应着三个文件呢,我们来通过实验演示一下,我们猜想他们是按照的文档的方式先后打开的。
stdin(0),stdout(1),stderr(2)

stdin(0)

int main()
{

    char buffer[1024];//0下标,我们默认是stdin
    ssize_t s = read(0, buffer, sizeof(buffer));//从键盘文件上只能读取数据,所以使用系统接口read,
                                                //虽然没有介绍过,但是大家看一下文档应该就会使用
    if(s < 0) return 1;
    buffer[s] = '\0';//因为从键盘读取到的只是有效字符,所以需要手动给字符数组加一个结束标志
    printf("echo : %s\n", buffer);
    return 0;
}

在这里插入图片描述

stdout(1),stderr(2)
这两个都指向显示器文件,就一起展示了

  const char *msg = "hello Linux\n";
  write(1, msg, strlen(msg));
  write(2, msg, strlen(msg));

在这里插入图片描述

结论出来了,那我们的c程序默认打开的三个文件是c语言的特性吗,肯定不是啊,这是os的特性,C语言拿来用了而已,**那为什么要默认打开这三个文件呢??**原因是我们的掉闹再一打开对应的键盘显示器就被加载了,这样程序员才能进行写代码,这是天然决定的

既然我们的c语言要支持这样默认打开的文件,那他必定要对fd进行封装,因为系统调用接口都是通过fd来对文件进行操作的,所以我们看到的FILE他是什么??是不是就是我们C语言里面的结构体,我们通过->来访问一下fd:

 printf("stdin:%d\n",stdin->_fileno);
 printf("stdout:%d\n",stdout->_fileno);
 printf("stderr:%d\n",stderr->_fileno);

在这里插入图片描述

看到这里大家对默认打开的文件是不是有了更深的了解了,大家可以自己下去测试关掉着三个默认的文件,还可不可以从键盘或者显示器进行操作,博主就不演示了,博主接下来带大家回过头来分析那幅图,我么再测试的默认打开的文件的时候,有两个文件都是显示器,那我们再关闭文件的时候,是怎么操作的:
在这里插入图片描述
我们的文件结构体里面有一个引用计数,他每次关闭,对应的文件的引用计数就会减减,到0此会真的关闭。我给大家测试一下:
const char *msg = "hello Linux\n";
write(1, msg, strlen(msg));
close(1);//关闭显示器文件
write(2, msg, strlen(msg));
在这里插入图片描述
结果即使关闭了1指向的显示器文件,但是显示器文件还是可以用的,原因就是close并没有关闭,只是将引用计数减减了。


四、重定向的原理介绍

大家如果从上面一直看下来应该知道我提到过重定向的内容,再铺垫之前就提到过,我们演示过w和a方式之后,往文件里面写东西,和重定向的效果是一样的,但是这节博主将带大家看看原理,再将这个之前,我先给大家讲解一下fd的分配规则,这个再上面也提到过

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{

    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
  	printf("fd=%d",fd);
    close(fd);
    return 0;
  }

在这里插入图片描述

int main()
{
	close(2);
    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
  	printf("fd=%d",fd);
    close(fd);
    return 0;
  }

在这里插入图片描述

int main()
{
	close(1);
    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
  	printf("fd=%d",fd);
    close(fd);
    return 0;
  }

在这里插入图片描述

通过前两个案例,我们可以看出,fd的分配规则是找文件描述符表里面下标最小并且为空的位置放我们先打开的文件,我们的fd是1或者2都是指向显示器文件,为什么第三个案例和第二个案例却结果不太,第三个案例没有打印出fd的数值,原因是printf他的功能是往fd=1这个文件上打印文件的,而关闭1了就显示不了。

我们再来写一个例子:

int main()
{
    
    close(1);
    int fd=open("log.txt",O_WRONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    
    const char*msg1="hello normal file\n";
    int cnt=5;
    while(cnt--)
    {
        write(1,msg1,strlen(msg1));
    }

    close(fd);
    return 0;
   }

在这里插入图片描述
我们看到我们打开log文件,万一往显示器上写内容,但是最后结果没有在显示器上显示,而是写道文件里面的,这是为什么??

来看图解:
在这里插入图片描述

这就是输出重定向

int main()
{
    
    close(0);
    int fd=open("log.txt",O_RDONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
   char inbuffer[1024];
    ssize_t s = read(0, inbuffer, sizeof(inbuffer)-1);
    if(s>0)
    {
        inbuffer[s] = '\0';
        printf("echo# %s\n", inbuffer);
    }
	close(fd);
	return 0;
}

在这里插入图片描述

本来是从键盘上读取文件,结果却从log.txt里面读取了,这就是输入重定向。

**特点:**上面两种重定向演示的特点都是,打log.txt文件,想在默认打开的三个文件进行写操作和读操作,但是结果都最后都是操作到log.txt上,原因就是充重定向。上面的办法,先关闭一个文件这样太不好看了,有没有系统函数专门做这样的事情呢??

dup2函数
在这里插入图片描述

int main()
{

    int fd=open("log.txt",O_RDONLY|O_CREAT,0666);
    if(fd<0)
    {
        perror("open");
        return -1;
    }
    dup2(fd,0);
   char inbuffer[1024];
    ssize_t s = read(0, inbuffer, sizeof(inbuffer)-1);
    if(s>0)
    {
        inbuffer[s] = '\0';
        printf("echo# %s\n", inbuffer);
    }
	close(fd);
	return 0;
}

在这里插入图片描述
也达到了相同的效果,接下来具体介绍一下函数的构成

这个参数的设计有点不和人情。
在这里插入图片描述
将oldfd拷贝到newfd上面,这里的oldfd就是新建的文件log.txt,newfd是你要拷贝的文件,最后再文件描述符表中会有两块位置的值是相同的,都是oldfd,这里面的拷贝不是下标拷贝,下标不可能有两个一样的,是将下标里面的内容拷贝,说这个参数的名字不好的原因是,新建的log.txt按道理比默认的文件后创建,他的fd应该是newold,结果看这个参数就跟搞反了一样。但也没办法,我们适应这个函数之后可以把oldfd给关闭,也可以不关闭,看你个人,这个函数的使用就比之前的方法好很多,一眼就能看出来你要干什么,博主会再下篇给大家写一个简单的shell给大家演示怎么默认实现命令行上面的重定向功能。

---------------------------------------------------------------------------------------------------------------------------------
我想在给大家解决一下心中的小疑惑,我们的os再启动的时候就会默认打开三个文件,但是其中有两个fd指向显示器文件,stdout(1),stderr(2),现在要解决的就是1 & 2的区别是什么??

博主先来写一段代码:

int main()
{

    const char*msg1="hello normal file\n";
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));
    write(1,msg1,strlen(msg1));

    const char*msg2="hell err file\n";
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    write(2,msg2,strlen(msg2));
    return 0;
}

我们看到两个效果是一样的

在这里插入图片描述

我们使用了重定向将1显示器文件和normal.log文件进行重定向,所以本来输出在显示器的内容重定向到normal.log文件里面了,而strerr是2显示器文件,和我没关系,默认的是把1显示器和别的文件进行重定向。下面的和上面的一样。
在这里插入图片描述


在这里插入图片描述

我们可以实现日志的分开写入,其实在本质上两者没有区别,但是为了分流去干一些是,就必须弄两个,方便分流操作。如果不想实现分流,就使用下面的方法:
在这里插入图片描述
先执行./mytest > normal.log 因为已经重定向了1号下标位置的值就是normal.log的内容,在通过&1就是把1号的内容给二号位置,此时如果一个文件都没有关闭,而且先创建normal.log文件的的话,那么1 2 3下标的内容都是3号下标里面normal.log,这样就可以写在同一个文件里面了。

至此我们的重定向就讲解完毕了,大家到时候来支持一下博主的手写shell程序吧。

五、理解Linux下一切皆文件。

在这里插入图片描述

大家好好的理解一下这个图,接下来给大家讲解缓冲区

六、缓冲区

相信这个名词大家在好久之前都听到过,但是只闻其人,未见其人,所以我们对缓冲区的概念还是非常模糊的,接下来我就带大家来看看这个缓冲区是什么。

提出问题:
什么是缓冲区?
为什么要有缓冲区??
缓冲区是怎么去工作的??
缓冲区在哪里?
这些问题我们之前都是不知道的,但是这节会给大家解决的。

首先我们来看一段代码:

#include<stdio.h>
#include<string.h>
int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";
    //c语言的接口
     printf("hello printf\n");
     fprintf(stdout, "hello fprintf\n");
     fwrite(fstr, strlen(fstr), 1, stdout);

	//系统调用的接口
     write(1, str, strlen(str)); 
    return 0;
}

在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    const char *fstr = "hello fwrite\n";
    const char *str = "hello write\n";
    //c语言的接口
     printf("hello printf\n");
     fprintf(stdout, "hello fprintf\n");
     fwrite(fstr, strlen(fstr), 1, stdout);

    //系统调用接口
     write(1, str, strlen(str)); 

     fork();
    return 0;
}

在这里插入图片描述

通过着两个测试用例,大家看出来差别了吗??四个写入函数,在第一个代码中打印出来的效果来看,我相信大家没啥疑惑,但是不代表大家懂了为什么会出现这样的结果,但是第二个代码,我们在执行完上面四个代码之后再进行fork的,但是往显示器上打印还是四个,而往文件打印就成了7个,细心的通过会发现,只有c语言调用的函数接口都打印了两次,而系统调用函数接口只打印了一次,而且肯定和fork有关系,但是这个结果很让人理解。,但是这节讲的是缓冲区,所以和缓冲区肯定有关系

再来看一个案例:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

因为再第一次测试的时候,两次代码只有c语言函数的接口函数出现了不同的变化,所以这次的案例,为了测试一下c语言调用函数接口,我们发现,我们的三个函数都是往显示器上打印,而我的close是再三个函数执行完毕后再关闭的,按道理往屏幕上打印是不受影响的,而两次代码的差距就在于打印的字符串有没有带\n,通过结果也可以发现,我们的第三个图没有带close,结果显示出来了,说明再执行close之前,三个函数打印的数据肯定放在其他地方了(缓冲区),而通过第二个图来看,如果1号被关闭打印不出来很正常,但是重定向到文件当中,应该把数据放进去文件,结果却是文件里面没有,原因是我么们先执行程序,显示器的数据先执行完再重定向到文件里面而1号被关闭了,就重定向不了了,所以得出1号文件没有被关闭的时候,再程序退出的时候,就会通过其他位置(缓冲区)把数据通过1号文件打印出来,如果1号被关闭,那么这些数据就被自动清除了。

七、总结

我们上面学完了稳健操作,大家对文件的恐惧感应该减少不少了,而且以前经常出现的概念今天也很好的解释了一遍,理解上面不难,主要的还是大家要贯穿,每个知识点都是连着的,跳着看就会有地方不理解,所以需要一步步,有逻辑性的去学习,那今天的只是就分享到这里了,我们下篇讲解一下文件系统。

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

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

相关文章

如何自己实现一个丝滑的流程图绘制工具(九) 自定义连接线

背景 产品又有更近的想法了&#xff0c;bpmn-js的连接线你用的时候是看不到的&#xff0c;也就是你从左侧点击连接线的没有线随鼠标移动. 但是产品想要看得见的连接线移动拖拽。 咩有办法&#xff0c;不能换框架&#xff0c;那就只能自己实现啦&#xff01; 思路&#xff1a; …

06-MySQL-进阶-视图存储函数存储过程触发器

涉及资料 链接&#xff1a;https://pan.baidu.com/s/1M1oXN_pH3RGADx90ZFbfLQ?pwdCoke 提取码&#xff1a;Coke 一、视图 数据准备 create table student(id int auto_increment comment 主键ID primary key,name varchar(10) null comment 姓名,no varchar(10) null co…

JDBC(一)

第1章&#xff1a;JDBC概述 1.1 数据的持久化 持久化(persistence)&#xff1a;把数据保存到可掉电式存储设备中以供之后使用。大多数情况下&#xff0c;特别是企业级应用&#xff0c;数据持久化意味着将内存中的数据保存到硬盘上**&#xff0c;而持久化的实现过程大多通过各种…

利用中断做数码表

功能要求:1.按下KEY1&#xff0c;显示数字开始每0.5秒加1&#xff0c;加到&#xff08;10学号&#xff09;返回0&#xff0c;0显示2秒后继续开始重复加1。 2. 任何时候按下KEY2数字清零&#xff0c;并停止加1。 3. KEY1和KEY2分别采用查询和外部中断方式。 要求程序中有硬件…

概念解析 | 高光谱图像:揭开自然世界的神秘面纱

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:高光谱图像 高光谱图像:揭开自然世界的神秘面纱 Hyperspectral imaging - Wikipedia 背景介绍 我们生活的世界充满了丰富多彩的颜色。这些颜色来源于各种物体反射或吸收不同波长…

PM - 项目管理 产品管理区别

产品管理和项目管理是两个在企业中至关重要的职能部门&#xff0c;它们各自承担着不同的职责和任务。虽然两者在某些方面存在重叠&#xff0c;但它们的核心目标和方法有很大的不同。本文将对产品管理和项目管理进行详细的比较和分析。 “项目管理和产品管理有什么区别&#xff…

微服务架构下如何使用多环境多服务联合调试

在 微服务 架构中&#xff0c;项目被分解成多个独立的模块&#xff0c;每个模块对应一个微服务。这些微服务各自承担不同的任务&#xff0c;例如用户管理、支付处理或订单管理。它们可以使用不同的技术栈&#xff0c;独立开发、测试和部署。微服务之间通过 API 等方式进行通信&…

Node.js中的child_process模块的作用

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【Python报错合集】Python元组tuple、张量tensor(IndexError、TypeError、RuntimeError……)~持续更新

文章目录 IndexError1. tuple index out of rangea. 示例代码b.报错原因c.解决方案 TypeError1. len() of a 0-d tensora. 示例代码b.报错原因c.解决方案 RuntimeError1. output with shape … doesnt match the broadcast shape …a. 示例代码b.报错原因c.解决方案 2. Cant ca…

apollo docker搭建

1 mysql搭建 先需要一个mysql&#xff0c;mysql我使用的是5.7&#xff0c;搭建过程忽略 2 数据导入 我们需要从github上下载apolloportaldb.sql, apolloconfigdb.sql 2个sql 随后cp apolloconfigdb.sql apolloconfigdbUat.sql cp apolloconfigdb.sql apolloconfigdbDev.sq…

内存取证分析

内存取证会临时存储一些有价值的信息 查看内存进程的信息等等&#xff0c;对溯源这种事情有帮助。不过要用到专门的工具获取信息 运行exe文件&#xff0c;输入y将一个系统的镜像完整的下载下来&#xff0c; 这就是保存下来的文件。 视频上别的工具搞不来&#xff0c;要不就是…

十五、W5100S/W5500+RP2040树莓派Pico<TFTP Client>

文章目录 1 前言2 简介2 .1 什么是TFTP&#xff1f;2.2 TFTP的优点2.3 TFTP和FTP对比2.4 TFTP应用场景 3 WIZnet以太网芯片4 ARP网络设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 一般来说&#xff0…

Deep Freeze冰点还原2024中文免费版恢电脑数据恢复工具

相信大家都认同更新日志&#xff1a;支持Win 10功能更新&#xff0c;Win更新的恢复升级&#xff0c;将系统驱动器从深度冻结保护中排除&#xff0c;全支持NVME驱动器&#xff0c;支持ISCSI驱动器。人所共知的是集成性和兼容性&#xff1a;Deep Freeze 冰点可兼容多种硬盘驱动器…

MySQL 8.0.13升级到8.0.35记录 .NET

1、修改表结构的字符集 utf8 修改成 utf8mb4 utf8_general_ci 修改成 utf8mb4_0900_ai_ci 注&#xff1a;所有地方都要替换。 否则会报错误提示&#xff1a;Character set utf8mb3 is not supported 下面是.NET环境升级遇到的问题 2、MySQL Connector Net 8.0.13 在程…

python自动化测试selenium核心技术3种等待方式详解

这篇文章主要为大家介绍了python自动化测试selenium的核心技术三种等待方式示例详解&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步早日升职加薪 UI自动化测试过程中&#xff0c;可能会出现因测试环境不稳定、网络慢等情况&a…

财税服务展示预约小程序的作用是什么

财税财政往往困扰着很多公司&#xff0c;尤其是公司里没有相应职员或工作压力大的情况下&#xff0c;不少商家就会寻找代理记账、审计服务、会计代理等服务的机构。 对财政服务代理机构&#xff08;会计公司&#xff09;来说&#xff0c;市场企业多而广&#xff0c;理论上来说…

【KingbaseES】R6 Liunx下使用命令行部署数据库集群

【KingbaseES】R6命令行部署数据库集群 A.数据库安装包下载软件下载页面授权下载页面 B.数据库集群部署软件安装第一步&#xff1a;创建Kingbase用户第二步&#xff1a;上传安装包1.创建Kingbase用户和准备安装目录2.使用FTP工具上传安装包镜像和授权文件到install目录下并授权…

城市内涝积水的原因有哪些?万宾科技内涝积水监测仪工作原理

一旦有暴雨预警出现多地便会立即响应&#xff0c;以防城市内涝问题出现。随着人口迁移&#xff0c;越来越多的人口涌入城市之中&#xff0c;为了完善城市基础设施建设&#xff0c;城市应急管理部门对内涝的监测越来越严格&#xff0c;在信息化时代&#xff0c;城市管理也趋向于…

阿里入局SSD赛道,刚发布的首款主控芯片有点猛啊

不知道大家有没有发现&#xff0c;这两年国产科技领域崛起势头是越来越猛了。 以往似乎多少年都没太大长进的 CPU、显卡等半导体产品&#xff0c;如今总能时不时冒出个劲爆消息。 前不久发布的龙芯 3A6000 处理器&#xff0c;性能达到了 Intel 10 代酷睿和 AMD Zen2 水平&…

git增加右键菜单

有次不小心清理系统垃圾&#xff0c;把git右击菜单搞没了&#xff0c;下面是恢复方法 将下面代码存为.reg文件&#xff0c;双击后导出生效&#xff0c;注意&#xff0c;你安装的git必须是默认C盘的&#xff0c;如果换了地方要改下面注册表文件中相关的位置 Windows Registry …