Linux_文件IO

目录

一、库函数进行文件操作

1、fopen/fclose

2、fwrite 

3、追加方式-“a” 

4、fread 

5、三个默认文件流 

二、系统函数进行文件操作

1、open/close

2、write 

3、追加方式-“O_APPEND” 

4、read 

5、struct file结构体

6、文件描述符

6.1 struct file的引用计数 

7、查看文件描述符的值

8、验证文件描述符0、1、2 

结语


前言:

        IO是Input/Output的首字母缩写,表示输入和输出,在Linux下一切皆为文件,使用文件无非只有读和写两种状态,即读对应Input,写对应Output,构成Linux下的基础IO。而对一个文件进行读写操作的前提是使用库函数 、系统调用函数先打开文件,然后再进行一系列的文件操作,本文着重介绍这些接口的使用。

一、库函数进行文件操作

        c语言标准库给上层提供了大量的文件接口,通过这些接口上层就可以对文件进行操作了,最常用的接口如下。 

1、fopen/fclose

        在对文件进行读写操作前,首先需要使用fopen打开文件,fopen是c中标准库<stdio.h>里的函数,用于打开一个文件,并且在打开文件时就要规定该文件是用于读还是用于写,或者是用于可读可写。

        fopen函数格式如下:

FILE *fopen(const char *filename, const char *mode);
//filename表示打开文件的路径,默认路径是该进程所在的路径
//mode表示打开文件的模式:常用的有:r(可读),w(可写),a(追加写)int fclose(FILE *fp);
//关闭一个文件流

        fopen测试代码如下:

#include <stdio.h>int main()
{// 打开文件的路径和文件名,默认在当前进程的路径下新建一个文件FILE *fp = fopen("log.txt", "a");//a表示追加写if(fp == NULL){perror("fopen");return 1;}fclose(fp);return 0;
}

         测试结果:

        发现在进程fopen.c的路径下创建了一个log.txt文件。

2、fwrite 

        fwrite将缓冲区内的数据输出至打开的文件中,该函数的格式如下:

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
//ptr表示指向要写入文件的缓冲区
//size表示从缓冲区内写入文件的数据的大小(单位字节)
//count表示写入多少个size字节至文件中,比如size是3,count是3,则从缓冲区拿9个字节
//stream表示写入的文件流//写入成功时返回count的值,写入失败返回小于(或不等于)count的数。

         fwrite测试代码(注意fopen的打开模式是“w”):

#include <stdio.h>
#include <string.h>int main()
{// 打开文件的路径和文件名,默认在当前进程的路径下新建一个文件FILE *fp = fopen("log.txt", "w");//此处要变成wif(fp == NULL){perror("fopen");return 1;}const char *message = "abcd\n";//定义输出缓冲区fwrite(message, strlen(message), 1, fp);fclose(fp);//sleep(1000);return 0;
}

        测试结果:

        从结果来看,abcd正常的写入到文件log.txt当中并且换行,所以可以理解现在log.txt中的内容是abcd+\n。


        更改上述代码中的缓冲区内容其他代码不变,并且重新执行该代码,观察log.txt中的内容是否发生变化:

const char *message = "该文件中只有这一句\n";

        测试结果:

        发现原先的内容abcd+\n被新内容覆盖了。原因就是fopen中“w“模式在写入前,会把文件内的内容全部清空,因此当重新调用fopen时会把目标文件的内容清空,所以若想保留文件中的内容对文件进行输出数据,要将fopen中的选项改成”a”追加选项。

3、追加方式-“a” 

        选项a会保留文件的内容,并且把数据输出在文件的末尾处:

#include <stdio.h>
#include <string.h>int main()
{// 打开文件的路径和文件名,默认在当前进程的路径下新建一个文件FILE *fp = fopen("log.txt", "a");//此处是a,表示追加写if(fp == NULL){perror("fopen");return 1;}const char *message = "追加写入\n";fwrite(message, strlen(message), 1, fp);fclose(fp);//sleep(1000);return 0;
}

         运行结果:

4、fread 

        以上是将缓冲区内的数据输出至文件中,fread则是从文件中输入数据至缓冲区内,然后通过打印缓冲区将文件的内容显示到屏幕上。 

        fread格式如下:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
//ptr指向缓冲区的指针
//size表示从文件中读取的每个元素的大小(单位字节)
//nmemb表示希望从文件中读取nmemb个size的内容
//stream表示读取的文件流//返回值表示最终读取的有效元素个数,读取失败返回-1,读到文件末尾返回0

        fread测试代码(注意fopen中选项要改成“r”):

#include <stdio.h>
#include <string.h>int main()
{// 打开文件的路径和文件名,默认在当前进程的路径下新建一个文件FILE *fp = fopen("log.txt", "r");//此处是a,表示追加写if(fp == NULL){perror("fopen");return 1;}char message[128];//-1的目的是预留一个位置给\0,否则读取的数据塞满了message数组,则后续手动//添加\0会导致越界访问size_t n = fread(message,sizeof(char),sizeof(message)-1,fp);if(n>0){//printf("n=%d",n);message[n] = 0;printf("%s\n",message);}fclose(fp);//sleep(1000);return 0;
}

         运行结果:

5、三个默认文件流 

        c程序启动时会默认打开三个标准输入输出文件流,分别是stdin(键盘文件)、stdout(显示器文件)、stderr(显示器文件),其中stdout和stderr的区别是:stdout是标准输出流,stderr是标准错误流,后者通常用于打印一些错误信息,其中printf默认从stdout标准输出打印。 

        将上述代码中fwrite的目标文件流换成stdout,则缓冲区内的信息会打印在屏幕上:

#include <stdio.h>
#include <string.h>int main()
{// 打开文件的路径和文件名,默认在当前进程的路径下新建一个文件FILE *fp = fopen("log.txt", "a");//此处是a,表示追加写if(fp == NULL){perror("fopen");return 1;}const char *message = "追加写入\n";fwrite(message, strlen(message), 1, stdout);//此处不再是fp而是stdoutfclose(fp);//sleep(1000);return 0;
}

        测试结果:

二、系统函数进行文件操作

        文件是存储在磁盘上的,而磁盘属于硬件设备,因此访问文件的本质就是让计算机访问硬件设备,访问硬件设备的权力只有操作系统有,所以可以推断标准库提供的大量文件操作函数的底层是调用系统函数的,因此我们可以直接调用系统函数来实现操作文件。

1、open/close

        open/close对标fopen/fclose,也有着创建文件和关闭文件的作用,只不过open更偏向底层一些,具体格式如下:

#include <unistd.h>int open(const char *pathname, int flags, mode_t mode);
//pathname表示路径,即创建或打开文件的所在路径
//flag是一个整形,但是他可以表示打开文件的多种模式,对标fopen中“w”,“a”选项,falg也是一个选项
//mode表示新建文件的初始权限,用十进制来表示权限//返回值是一个整形,表示的是文件描述符,而不是fopen的文件指针,错误返回-1并设置错误码errorint close(int fildes);
//关闭一个文件描述符

        从open的格式可以发现,flag比较特殊,因为他是一个整形而不是字符串的形式,所以系统规定了几个特殊的宏,这些宏才是表示文件可读、可写的各种选项,常用的宏如下:

  • O_RDONLY:以只读模式打开文件,对标“r”(必填之一)。
  • O_WRONLY:以只写模式打开文件,对标“w”(必填之一)。
  • O_RDWR:以读写模式打开文件,对标“rw”。
  • O_CREAT:如果文件不存在,则创建新文件。通常需要与O_WRONLYO_RDWR一起使用。
  • O_APPEND:每次写入都在文件的末尾添加数据,对标“a”。
  • O_TRUNC:如果文件已存在,并以写方式打开,则将其内容清空。

        并且open的返回值是一个整形,表示文件描述符,和fopen不一样,但是该整形的用法和fopen的文件指针是一样的,即在该进程下,用文件描述符表示访问一个文件的入口


         open测试代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{//0666 = rw- rw- rw-int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);if(fd < 0)//当文件描述符小于0则说明打开失败{printf("open file error\n");return 1;}close(fd);//关闭文件描述符return 0;
}

         运行结果:

         从运行结果来看,确实成功创建了文件log.txt,但是仔细观察发生log.txt的权限不是0666,而是0664,原因就是我们创建文件的最终权限=起始权限&(~umask),而umask默认值是0002,所以导致最后一个权限的中间bit位一定会是0,因此正确设置文件的初始权限,则要把umask的值设为0。

        在上述代码调用open前加上

umask(0);

        再次测试上述代码:

2、write 

        write的作用自然不用多说,和fwrite是一样的,因为fwrite底层调用的就是write,wrtie格式如下:

#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
//fd表示目标文件的文件描述符
//buf表示缓冲区
//count表示从缓冲区内读取的字节数(对标fwrite的size*count)//成功写入时返回写入的字节数,失败时返回-1

         测试write的代码如下:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);if(fd < 0){printf("open file error\n");return 1;}const char message[] = "hello world\n";//自定义缓冲区ssize_t poi = write(fd, message, sizeof(message)-1);//无需把\0也写进文件中if (poi == -1) {  perror("write");  return -1;} close(fd);return 0;
}

         测试结果:


        注意:因为open的打开模式加上了O_TRUNC,所以每次调用open时会把log.txt的内容清空再打开,若open模式中没有O_TRUNC,则每次调用open时不会清空文件内容,但是是从文件是最开始进行覆盖式的写入,具体代码如下:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT, 0666);//没有O_TRUNCif(fd < 0){printf("open file error\n");return 1;}const char message[] = "zzz\n";//自定义缓冲区ssize_t poi = write(fd, message, sizeof(message)-1);//无需把\0也写进文件中if (poi == -1) {  perror("write");  return -1;} close(fd);return 0;
}

        测试结果:

        从结果看到,原先内容的前四个字节被覆盖了。 

3、追加方式-“O_APPEND” 

         若想实现系统函数open的追加方式,则在模式中添加O_APPEND宏即可,示例代码如下:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);//没有O_TRUNCif(fd < 0){printf("open file error\n");return 1;}const char message[] = "追加语句\n";//自定义缓冲区ssize_t poi = write(fd, message, sizeof(message)-1);//无需把\0也写进文件中if (poi == -1) {  perror("write");  return -1;} close(fd);return 0;
}

         运行结果:

        不过值得注意的是: O_APPEND是一种方式并不包含写模式,所以使用O_APPEND时必须是写模式,否则连数据都无法写入文件中更别提追加了。

4、read 

         read是系统提供的系统函数,他的作用是读取文件中的内容至输入缓冲区内,和fread的作用是一样的,具体格式如下:

#include <unistd.h>  ssize_t read(int fd, void *buf, size_t count);
//fd表示文件描述符
//buf表示存放文件内容的缓冲区
//count表示从文件中读取多少字节的数据//读取成功时返回值表示读取到有效字节的个数,读取失败返回-1,读到文件末尾返回0

        测试read的代码如下(注意将open的打开模式设为O_RDONLY或O_RDWR):

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{umask(0);int fd = open("log.txt", O_RDONLY,0666);if(fd < 0){printf("open file error\n");return 1;}char message[128];//自定义缓冲区ssize_t poi =read(fd,message,sizeof(message)-1);//预留\0的位置if(poi==-1){perror("read");return -1;}message[poi] = 0;printf("%s",message);close(fd);return 0;
}

        运行结果:

5、struct file结构体

        操作系统对新打开文件会创建一个结构体(struct file)来管理该文件,并且一个文件只有一个struct file,因为涉及到新打开的文件和新关闭的文件,所以关闭文件的时候会把该结构体删除,那么此时就要对管理文件的结构体进行数据结构化,因为要方便对其进行增删查改,所以有了文件管理链表,具体示意图如下:

        描述文件的结构体struct file有了,那么底层是如何找到struct file的呢?答案是通过文件描述符找到的。

6、文件描述符

        要想访问文件的前提是调用open函数打开文件,并且open函数会返回该文件的文件描述符,所以打开一个文件只能是在进程中完成,因为只有进程中才能调用函数(因此文件描述符肯定是存放在进程PCB中)。在一个进程内访问一个文件必须通过该文件的文件描述符,文件描述符在单个进程中具有唯一性。 

        PCB、文件描述符、struct file关系图如下:

        通过上图可以发现文件描述符就是PCB中的一个结构体里的指针数组的下标,并且每个进程都会有属于自己是struct file_struct结构体,这也是为什么进程间的文件描述符是独立的。 

6.1 struct file的引用计数 

        打开文件会返回一个文件描述符,关闭一个文件描述符会关闭了一个文件吗?

        答案:不会,因为一个进程打开的文件,别的进程也许也打开了这个文件,比如一个进程open了显示器文件,则open函数会返回一个文件描述符给该进程,让该进程可以通过这个文件描述符访问显示器,即打印数据在显示器上,但是当该文件关闭了该文件描述符,如果直接把显示器文件关闭了,则其他的进程就无法打印数据到显示器上了,这不符合逻辑,因此当多个进程使用同一份文件时,进程关闭自己的文件描述符不会直接关闭文件管理链表上的文件

        因为一个文件只有一个struct file,所以大量的进程打开同一个文件时,struct file结构体中有一个专门记录进程个数的引用计数,只有当引用计数变成0时代表当前没有进程访问该文件了,就会把文件的结构体struct file从文件管理链表中删除。

7、查看文件描述符的值

        以下代码在一个进程内多次open文件,然后打印open返回的值,并观察其中的逻辑:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{umask(0); //一次创建四个文件int fd1 = open("log1.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);int fd2 = open("log2.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);int fd3 = open("log3.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);int fd4 = open("log4.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);if(fd1 < 0){printf("open file error\n");return 1;}//打印这四个文件描述符观察其逻辑printf("fd1: %d\n", fd1);printf("fd2: %d\n", fd2);printf("fd3: %d\n", fd3);printf("fd4: %d\n", fd4);return 0;
}

         运行结果:

        从结果发现,打开的第一个文件返回的文件描述符是从3开始,之后的文件描述符按顺序往下走,原因就是上文提到的c程序刚开始会默认打开三个文件流,分别是stdin、stdout、stderr,这三个文件流刚好就是0、1、2,所以我们在程序中open文件的文件描述符是从3开始的。 

8、验证文件描述符0、1、2 

        文件描述符0、1、2对应三个文件流stdin、stdout、stderr,所以当使用write接口时,可以把文件描述符1传给write,这样就可以在屏幕上看到输出的信息了。

        示例代码:

#include <stdio.h>
#include <unistd.h>int main()
{const char message[] = "hello world\n";//自定义缓冲区ssize_t poi = write(1, message, sizeof(message)-1);//此处fd传的1if (poi == -1) {  perror("write");  return -1;} return 0;
}

        运行结果:


        并且可以通过stdin、stdout、stderr来验证他们对应的文件描述符是0、1、2,因为stdin、stdout、stderr是c程序启动时默认打开的文件流所返回的文件指针,所以该文件指针指向的文件结构体FILE肯定封装了底层的0、1、2,因此肯定通过stdin、stdout、stderr三个文件指针来找到底层的文件描述符并打印出来。示例代码如下:

#include <stdio.h>int main()
{printf("stdin->fd: %d\n", stdin->_fileno);printf("stdout->fd: %d\n", stdout->_fileno);printf("stderr->fd: %d\n", stderr->_fileno);return 0;
}

        测试结果:

        所以可以得出一个很重要的结论:c程序默认打开三个文件流的底层逻辑是进程会默认打开三个文件描述符0、1、2。 

结语

        以上就是关于文件IO的讲解,理解文件IO的首要工作是理解输入和输出的概念,常常把write写入数据至文件这个过程看成是输出,把read从文件中读取数据看成是输入,并且清楚理解文件描述符的意义,以及他和文件指针的关系。

         

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

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

相关文章

中学理化生实验室建设及配置要求

在中学物理、化学、生物等学科教学中&#xff0c;实验占据了非常重要的地位&#xff0c;是整个教学过程中不可或缺的部分。很多理科教学需要在实验室完成演示和学习任务&#xff0c;实验室也是保证教学计划得以实施的物质基础。因此&#xff0c;中学理化生实验室建设标准与否&a…

【C++ | const成员】类的 const数据成员、const成员函数、const对象、mutable 数据成员

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-06-14 2…

win10修改远程桌面端口号,在Windows 10中修改远程桌面端口号的步骤

在Windows 10中&#xff0c;远程桌面服务&#xff08;Remote Desktop Services, RDS&#xff09;允许用户从远程位置访问和操作计算机。默认情况下&#xff0c;远程桌面协议&#xff08;RDP&#xff09;使用端口3389进行通信。然而&#xff0c;出于安全考虑&#xff0c;管理员可…

VScode创建ROS项目 ROS集成开发环境

ROS使用VScode创建项目步骤 1.创建ROS工作空间2.启动VScode3.VScode编译ROS4.创建ROS功能包C语言开发Python语言开发 本文章介绍了如何在Ubuntu18.04系统下搭建VScode 的ROS项目 搭建项目分为一下几个步骤&#xff1a; 1.创建ROS工作空间 创建一个demo的ROS工作空间&#xff0…

大数据学习-Hadoop

介绍 是 Apache 的顶级开源项目&#xff0c;一个分布式框架&#xff0c;主要功能&#xff1a; 分布式大数据存储——HDFS 组件分布式大数据计算——MapReduce 组件分布式资源调度——YARN 组件 可以通过它来构建集群&#xff0c;完成大数据的存储和计算 学习起来相对简单&…

怎么看电脑实时充电功率

因为我想测试不同的充电器给电脑充电的速度&#xff0c;所以就想找一款软件可以看电脑当前充电功率的软件&#xff0c;我给一个图 直接搜索就可以下载了&#xff0c;charge rate就是功率&#xff0c;这里是毫瓦&#xff0c;换算单位是 1000mw1w 所以我这里充电功率是65w&…

6.21 移动语义与智能指针

//先构造&#xff0c;再拷贝构造//利用"hello"这个字符串创建了一个临时对象//并复制给了s3//这一步实际上new了两次String s3 "hello"; 背景需求&#xff1a; 这个隐式创建的字符串出了该行就直接销毁掉&#xff0c;效率比较低 可以让_pstr指向这个空间…

squareline studio浅尝(1)在对话框添加键盘

因项目需要&#xff0c;需要修改IP地址等参数&#xff0c;需要编辑文本对话框内容&#xff0c;这时候就需要调用键盘&#xff0c;操作如下。主要为了做笔记。如有误导请及时留言。 1&#xff09;拖一个键盘到对话框页面。默认把它隐藏&#xff08;flag:hidden&#xff09; 2&…

想更好应对突发网络与业务问题?您需要一款“全流量”

全流量分析&#xff0c;能为我做什么&#xff1f; 在生活中遇到问题&#xff0c;我们的第一反应可能是拿出手机拍照记录&#xff0c;方便后续处理。这些问题是临时的、突发的。 流量分析&#xff0c;就是网络中的“手机”&#xff0c;针对突发的网络故障和安全事件&#xff0…

课程管理系统

摘 要 在大学里&#xff0c;课程管理是一件非常重要的工作&#xff0c;教学工作人员每天都要与海量的数据和信息打交道。确保数据的精确度和完整程度&#xff0c;影响着每一位同学的学习、生活和各种活动的正常展开&#xff0c;更合理的信息管理也为高校工作的正规化运行和规范…

解锁空间数据奥秘:ArcGIS Pro与Python双剑合璧,处理表格数据、矢量数据、栅格数据、点云数据、GPS数据、多维数据以及遥感云平台数据等

ArcGISPro提供了用户友好的图形界面&#xff0c;适合初学者快速上手进行数据处理和分析。它拥有丰富的工具和功能&#xff0c;支持各种数据格式的处理和分析&#xff0c;适用于各种规模的数据处理任务。ArcGISPro在地理信息系统&#xff08;GIS&#xff09;领域拥有广泛的应用&…

安全生产第一位,靠谱的漏油监测系统有哪些?

漏油监测系统&#xff0c;一般是由漏油绳、漏油控制器、监控云平台组成&#xff0c;用于实时检测油库、油罐、加油站、输油管道、油类化工厂等场所是否发生漏油事故。在这些地方一旦发生漏油&#xff0c;就极可能引发爆炸&#xff0c;损害到人员及财产安全。而一套靠谱的漏油监…

mysql 主从延迟

mysql 主从延迟 精华推荐 | 【MySQL技术专题】「主从同步架构」全面详细透析MySQL的三种主从复制&#xff08;Replication&#xff09;机制的原理和实战开发&#xff08;原理实战&#xff09; https://blog.csdn.net/l569590478/article/details/128329929 mysql主从之多线程复…

iptables(6)扩展匹配条件--tcp-flags、icmp

简介 前面我们已经介绍了不少的扩展模块,例如multiport、iprange、string、time、connlimit模块,但是在tcp扩展模块中只介绍了tcp扩展模块中的”--sport”与--dport”选项,并没有介绍”--tcp-flags”选项,那么这篇文章,我们就来认识一下tcp扩展模块中的”--tcp-flags”和i…

【MySQL进阶之路 | 高级篇】InnoDB搜索引擎行格式

1. COMPACT行格式 COMPACT行格式是MySQL5.1的默认行格式.其结构示意图如下. 大体可以分为两部分. 记录的额外信息.这里面有包括变长字段长度列表&#xff0c;NULL值列表和记录头信息.记录的真实数据. (1).变长字段长度列表 MySQL支持一些变长的数据类型.比如VARCHAR(m), VA…

基于JSP技术的个性化影片推荐系统

开头语&#xff1a;你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSPServlet 工具&#xff1a;MyEclipse、Tomcat、MySQL 系统展示 首页 …

langchain教程-(1)Prompt模板

LangChain 的核心组件 模型 I/O 封装 LLMs&#xff1a;大语言模型Chat Models&#xff1a;一般基于 LLMs&#xff0c;但按对话结构重新封装PromptTemple&#xff1a;提示词模板OutputParser&#xff1a;解析输出 数据连接封装 Document Loaders&#xff1a;各种格式文件的加载…

Docker Desktop进入界面时一直转圈的解决办法记录

我的win10版本如下&#xff0c;是支持安装的&#xff0c;不支持安装的&#xff0c;可以先升级系统版本&#xff1a; 起初是因为运行Docker Desktop时一直转圈&#xff0c;无法进入主面板&#xff0c;百度之&#xff0c;需要安装hype-v环境&#xff0c;找到以下 勾选Hyper-V下的…

分享由AI制定一个商城网站的开发计划及推荐的开发语言

商城网站开发计划 一、项目概述 本商城网站开发计划旨在创建一个功能齐全、用户友好的在线购物平台&#xff0c;为顾客提供商品浏览、搜索、购物车管理、订单跟踪、在线支付等服务。商城将支持多种商品分类&#xff0c;包括但不限于电子产品、家居用品、服饰鞋帽等。 二、开…

在小公司可以做大模型吗?心得经验分享_第一份工作在小公司做大模型好吗

导读 继ChatGPT发布以来&#xff0c;各种大模型相继问世。近日Sora也突然走入大众的视野。那么做模型是否只有OpenAI这种巨头公司才能做呢&#xff0c;答案是否定的。在小公司做大模型&#xff0c;是可以的。本文作者结合切身经历&#xff0c;回答了如何在小公司做大模型。 在…