当前位置: 首页 > news >正文

Linux——文件操作

前言

1)在Linux下面,一切皆文件,文件=文件内容+文件属性

2)在访问文件是,都得先将文件打开,修改文件的本质其实还是通过执行代码的形式修改。

3)文件是被进程打开的,一个进程可以打开多个文件,操作系统会将打开的文件进行管理,被打开的文件被加载到内存中,称为内存文件,未被打开的文件存放在磁盘上,称为磁盘文件。

本文对进程和文件之间的关系,以及操作系统如何对文件进行管理

一、C语言接口与重定向

        在C语言中,提供了打开文件接口fopen,通过查询man手册,其参数有两个,第一个为想要打开的文件名,第二个为打开方式,打开方式有以下12中,其中r表示读,w表示写,a表示追加,b表示二进制,+表示读写,只要带r的打开方式文件不存在就报错,只要带w的打开方式文件不存在就创建。以w形式打开文件,文件会被自动清空,以a方式打开文件,向文件内写入内容,内容追加到文件末尾

打开方式含义文件不存在处理方式
r只读报错
w只写创建新文件
a只写,打开后文件指针指向末尾创建新文件
rb只读,打开二进制文件报错
wb只写,打开二进制文件创建新文件
ab只写,打开二进制文件后指针指向末尾报错
r+读写出错
w+读写创建新文件
a+读写,打开后文件指针指向末尾创建新文件
rb+读写,打开一个二进制文件报错
wb+读写,打开一个二进制文件创建新文件
ab+读写,打开二进制文件后指针指向末尾创建新文件

验证重定向的文件打开方式

[root@hcss-ecs-e53a test5]# cat log.txt 
hello world
[root@hcss-ecs-e53a test5]# echo "hello">log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 
hello
[root@hcss-ecs-e53a test5]# >log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 

使用>重定向后,发现原来的内容被覆盖,如果左边为空,重定向结果是文件内容被清空,所以可以推断出,>重定向的打开文件方式是w

[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 
hello world
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# echo "hello world" >>log.txt 
[root@hcss-ecs-e53a test5]# cat log.txt 
hello world
hello world
hello world
hello world
hello world

使用>>对文件重定向,发现原来的内容没有被覆盖,新的内容追加到了文件末尾,所以推断出,>>重定向的打开方式是a

二、C语言文件读写接口

fgets(char *s, int size, FILE *stream),整行读取,遇到回车换行或结尾停止.在文本方式时使用。且会在末尾追加一个'\0',占据一个字符,所以实际读取字符数为size-1。

fread(void *ptr, size_t size, size_t nmemb, FILE *stream),读取二进制流,参数为写入的指针,读取单元字符大小,字符数量,目标流。末尾会插入一个

fputs(const char*str,FILE*stream),写入字符串流,参数为字符串和需要写入的文件流。

fwrite(const void*ptr,size_t size,size_t nmemb,FILE* stream),写入二进制流,参数为需要写入的内容,基本单元的大小,需要写入几个基本单元,以及需要写入的文件流。返回值为写入了多少个基本单位

三、Linux下文件I/O接口

1.当前路径

进程在启动的时候,会自动记录当前所在的路径,可以在/proc/PID/cwd查询到当前进程所对应的当前路径

2.程序默认打开的文件流

在开发操作过程中,开发人员

stdin:标准输入-->键盘设备

stdout:标准输出-->显示器设备

stderr:标准错误-->显示器设备

所以,可以对stdout和stderr进行写入后显示屏显示指定内容。例如,使用printf对stdout进行写入,使用fprintf对指定流进行写入等。可以通过读取stdin内容读取键盘输入的数据,例如,使用scanf和fread读取标准输入流数据。

3.文件操作

1.通过C语言操作文件

2.通过系统调用操作文件

1)open

open(const char * filename,int flags),以特定的方式打开文件,返回值为文件打开状态。返回值为文件描述符,返回-1表示文件打开失败。

flags含义
O_RDONLY只读打开
O_WRONLY只写打开
O_RDWR读写打开
O_CREAT若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND追加写
O_TRUNC清空文件内容

在open的flags参数,前三个宏必须存在且仅存在一个,后续选项如有需要直接与前三者进行按位或操作即可。如果文件不存在,则需要在flags参数后面追加mode参数以表示该文件的权限。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(){int fp =  open("log11.txt",O_RDONLY|O_CREAT,0777);if(fp == -1){perror("open error\n");return 1;}return 0;
}

通过观察创建后文件权限位可以看到,指定的文件权限为0777,但是创建后文件的权限为0755,这是因为,在设置文件的权限位的时候,不仅受参数影响,同时会受到umask的影响。如果不想收到umask的影响,可以使用系统接口umask,将该进程下umask设置为0,但是不影响其他地方的umask。

设置前:

设置后:

2)close

close(int fd)关闭打开的文件

3)write

ssize_t write(int fd, const void *buf, size_t count);向指定的文件写入内容,参数fd(目标文件的文件描述符)、buf(需要写入的内容)、count(需要写入的字符数)。如果文件原来有内容,则直接进行覆盖而不是将内容清空。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(){int fd = open("log.txt",O_WRONLY);if(fd == -1){perror("open error\n");return -1;}const char* str = "hahaha\n";write(fd,str,strlen(str));close(fd);int fd1 = open("text.txt",O_WRONLY);if(fd1 == -1){perror("open error\n");return -1;}write(fd1,str,strlen(str));close(fd1);return 0;
}

4)read

ssize_t read(int fd, void *buf, size_t count);读取指定的文件,参数fd(目标文件描述符),buf(内容保存位置),count(表示读取的字符个数)
 

int main(){int fd = open("log.txt",O_RDONLY);if(fd == -1){perror("error\n");return -1;}char buffer[1024];ssize_t s = read(fd,buffer,sizeof(buffer));if(s>0){buffer[s]=0;printf("%s\n",buffer);}close(fd);return 0;
}

四、Linux下的文件I\O

1)fd文件描述符

open的返回值是一个int类型的数字表示文件描述符, -1表示打开失败。打开5个文件,观察他们的fd

int main(){int fd1 = open("log1.txt",O_WRONLY|O_CREAT);int fd2 = open("log2.txt",O_WRONLY|O_CREAT);int fd3 = open("log3.txt",O_WRONLY|O_CREAT);int fd4 = open("log4.txt",O_WRONLY|O_CREAT);int fd5 = open("log5.txt",O_WRONLY|O_CREAT);printf("fd1 is %d\n",fd1);printf("fd2 is %d\n",fd2);printf("fd3 is %d\n",fd3);printf("fd4 is %d\n",fd4);printf("fd5 is %d\n",fd5);
}

发现他们的fd从3开始依次递增。因为0表示标准输入,1表示标准输出,2表示标准错误。

2)Linux进程文件描述

        在Linux系统下面,有一个结构体叫做file 的结构体将打开的文件进行描述管理,结构体中包括了文件的属性、方法集和缓冲区。操作系统将所需要打开的文件从磁盘中读取出来,然后以链表的形式串起来进行管理。

        在进程控制块结构体中,存在一个files_strucet指针,指向一个files_struct结构体对象,这个对象的作用是将进程打开的文件统一管理起来。在file_struct里面,存在一个叫做struct file*fd_array[]的数组(文件描述符表),用于存放文件指针,即将系统打开的文件列表中的指针。而文件对应的下标就是fd(文件描述符),所以可以通过文件描述符对文件进行操作。                                                                              ​​

 

在C语言中,FILE结构体本质就是对struct  file进行封装后的结果。

3)文件fd的文件分配规则

在Linux下面,fd为0,1,2分别为标准输入,标准输出和标准错误,所以,在打开文件时,默认是从3开始依次递增,所以下面代码运行结果为3,4。

int main(){int fd1 = open("log1.txt",O_RDONLY|O_CREAT);int fd2 = open("log2.txt",O_RDONLY|O_CREAT);printf("fd1 is:%d\nfd2 is:%d\n",fd1,fd2);return 0;
}

如果将标准输入关闭,再打开新的文件,结果变成了0,3,分析其原因是stdin打开时,0被占用,当将stdin关闭后,

int main(){close(0);int fd1 = open("log1.txt",O_RDONLY|O_CREAT);int fd2 = open("log2.txt",O_RDONLY|O_CREAT);printf("fd1 is:%d\nfd2 is:%d\n",fd1,fd2);return 0;
}

所以得出结论,fd的分配规则按照文件打开的顺序,从0开始依次分配未使用的数组下标,即为fd。

4)文件重定向

在上面的例子中,可以通过fd关闭标准文件流,再打开文件时,原文件流的fd会被赋给其他文件,该现象就称为文件重定向。

int main(){close(0);close(1);int fd1 = open("log1.txt",O_RDONLY);int fd2 = open("log2.txt",O_WRONLY);char str[1024];scanf("%s",str);printf("%s\n",str);return 0;
}

        在代码中,关闭了标准输入标准输出流,再打开了文件log1.txt和log2.txt,此时这两个文件的fd分别为0和1,再调用scanf和printf函数,发现可以通过这连个函数进行从文件中读和向文件中写。

        重定向的底层原理,在操作系统层,将进程对应的文件描述列表对应下标替换为目标文件,而scanf和printf的底层其实是向下标为0和1的文件读取/写入内容。如果以只写的方式打开文件但是不进行写操作,目标文件会被清空。

5)dup2接口

        在上面已经可以实现输出和输入重定向,但是存在一点问题,需要将原文件关闭再按照顺序打开文件。在linux下面,有一个接口,dup2可以直接将文件的fd进行替换,从而实现文件重定向。

dup2(int oldfd,int newfd),oldfd(需要拷贝的目标文件的fd),newfd(需要被替换的文件fd)。

所以上面的代码就可以进行以下修改

int main(){int fd1 = open("log1.txt",O_RDONLY);int fd2 = open("log2.txt",O_WRONLY);dup2(fd1,0);dup2(fd2,1);char str[1024];scanf("%s",str);printf("%s\n",str);return 0;
}

五、C语言缓冲区

1)什么是缓冲区

        文件缓冲区其实就是内存里面的一块空间,在C语言中,其意义是文件操作只需要将需要读写的文件交给缓冲区,再由缓冲区与系统调用直接进行交互,减少了C语言接口调用时间,同时通过暂存的方式,减少了系统调用的次数,从而提高读写效率。

2)缓冲区在哪里

        在打开文件时,调用fopen接口,会返回一个FILE*指针,FILE是一个结构体,里面包含了fd和缓冲区指针。即每一个打开的文件都有一个·独立的缓冲区。在调用C语言接口对文件进行读取的时候,有一个FILE*的参数,其实质就是将文件里的内容拷贝到缓冲区里面,再内部决定何时进行缓冲区的刷新。

3)缓冲区刷新策略

1、无刷新

无刷新就是读取一个数据就即时将内容交给系统,

2、行刷新

当数据遇到'\n'或者'\r'时就进行刷新

3、全刷新

等数据完全完成读写后再对缓冲区进行刷新

4)缓冲区现象观察

       由于标准输出默认是输出到显示屏,属于行刷新,不便于观察,所以在输出的时候将其重定向到log.txt文件中。

int main(){const char* s1="111111111write\n";const char* s2="222222222fprintf\n";const char* s3="333333333fwrite\n";write(1,s1,strlen(s1));fprintf(stdout,"%s",s2);fwrite(s3,strlen(s3),1,stdout);
}

        到目前正常按照顺序将字符串内容写入到log.txt当中,现在在test.c文件末尾加上fork(),再次运行,观察现象。

int main(){const char* s1="111111111write\n";const char* s2="222222222fprintf\n";const char* s3="333333333fwrite\n";write(1,s1,strlen(s1));fprintf(stdout,"%s",s2);fwrite(s3,strlen(s3),1,stdout);fork();
}

        发现后面两个字符串被写入了两次,而第一个字符串只写入一次,第一个字符串使用的是系统接口调用,而后面两个是使用的C语言函数接口。其原因是使用C语言文件接口后,文件内容其实是被写到了文件的缓冲区当中,而并没有直接写入到log.txt文件当中,当fork后,发生写时拷贝,缓冲区以及里面的内容也被子进程拷贝,在进程结束时。子进程和父进程都需要刷新缓冲区,此时就将缓冲区里面的内容通过系统调用写入到了log.txt文件当中,而write系统调用直接就将文件内容写入到了log.txt当中。

相关文章:

Linux——文件操作

前言 1&#xff09;在Linux下面&#xff0c;一切皆文件&#xff0c;文件文件内容文件属性 2&#xff09;在访问文件是&#xff0c;都得先将文件打开&#xff0c;修改文件的本质其实还是通过执行代码的形式修改。 3&#xff09;文件是被进程打开的&#xff0c;一个进程可以打…...

数据结构 ——— 数组栈oj题:有效括号

目录 题目要求 代码实现 题目要求 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每…...

Character AI被起诉!14岁青少年自杀,AI陪伴何去何从

终于&#xff0c;AI在青少年心理问题方面&#xff0c;被推上了风口浪尖。 最近&#xff0c;美国佛罗里达州&#xff0c;一名14岁男孩Sewell Setzer的父母控告Character AI公司&#xff0c;声称孩子沉迷该公司的AI聊天机器人&#xff0c;最后走上了自杀的道路。 跟AI聊天还能致…...

CSS3 动画相关属性实例大全(三)(columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性)

CSS3 动画相关属性实例大全&#xff08;三) &#xff08;columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性&#xff09; 本文目录&#xff1a; 一、columns属性&#xff08;设置元素的列宽和列数&#xff09; 二、filter属性&#xff08;调整图像、背景和边…...

中国最厉害的思想家改名大师颜廷利:以诚信为基,塑企业信誉

跨文化融合&#xff0c;共筑包容性文化殿堂。尊重差异&#xff0c;促进团队合作&#xff0c;以诚信为基&#xff0c;塑企业信誉。融合《升命学说》智慧&#xff0c;推动员工多元化&#xff0c;践行社会责任&#xff0c;树立良好形象。创新不息&#xff0c;持续学习&#xff0c;…...

Python 代码实现用于进行水质模拟和优化加氯量

# -*- coding:utf-8 -*- import epamodule as em import epanetmsxmodule as msx import pandas as pd import numpy as np# 水质模拟,会产生一个rpt文件,但并不是返回这个文件。 def quality_simulation(inp_file,rpt_file,msx_file...

挖矿病毒来势汹汹

病毒来了, 我的个人站点使用了 wordpress, 它的不知哪个漏洞让黑客攻入了我的站点 使用 top 命令看到了有不明进程始终占据了 100% 的 CPU snapshot 1 snapshot 2 通过以下 "三板斧"可以查杀这个进程 先用 top (shiftp) 查找占据 CPU 最多的进程根据其进程号 pid 查看…...

国产数据库的蓝海在哪?

昨天有幸参加了 OceanBase2024年度发布会。在过去的几年中&#xff0c;OB 作为国内自主研发的分布式数据库&#xff0c;取得了令人瞩目的成就&#xff0c;特别是在金融行业&#xff0c;OB 通过不断的技术革新和优化&#xff0c;已经成为行业的领导者之一。OceanBase 展现了强大…...

MySQL~表的操作(创建表,查看表,修改表,删除表)

1.创建表 1.1.创建表 首先要选择需要操作的数据库&#xff0c;USE 数据库名&#xff0c;后续可以根据实际情况操作时添加。 USE fruitsales;建表语法&#xff1a; create table 表名( 字段名1 数据类型, 字段名2 数据类型, ); 实例&#xff1a;创建fruit_bak1表。 create t…...

多线程加锁与手搓智能指针实践

前缀知识 如何手搓智能指针 参考链接 如何多线程加锁&#xff0c;线程间通信 参考链接 注意&#xff1a; 在第一个链接中&#xff0c;重载赋值构造函数时&#xff0c;返回值类型为引用类型&#xff0c;仅适用于返回的这个对象, 在该函数调用前 (已经)存在了!!! 具体可参考 参考…...

3180. 执行操作可获得的最大总奖励 I

力扣刷题记录 dp 回溯 3180. 执行操作可获得的最大总奖励 I 思路 和往常一样&#xff0c;先使用暴力求解&#xff0c;想到了回溯算法&#xff0c;选择了当前数字&#xff0c;就跳到下一个数字&#xff0c;形成一个树形结构来遍历所有结果集合&#xff0c;但是没有找到优化算…...

react18中的jsx 底层渲染机制相关原理

jsx 底层渲染机制 渲染 jsx 时&#xff0c;会先解析 jsx&#xff0c;生成一个虚拟 dom(virtual dom)。然后将虚拟 dom 渲染成真实 dom。如果 jsx 中包含事件&#xff0c;会将事件绑定到真实 dom 上。 虚拟 dom 对象&#xff0c;是框架内部构建的一套对象体系&#xff0c;对象…...

Spring Boot 实现文件上传下载功能

文章目录 一、原理分析1.1 请求类型1.2 服务器解析 二、功能实现2.1 创建项目并导入依赖2.2 文件上传功能实现2.2.1 文件上传 Service2.2.2 文件上传 Controller 2.3 文件下载功能实现2.3.1 文件下载 Service2.3.2 文件下载 Controller 2.4 文件上传前端代码(可选)2.4.1 上传文…...

ArcGIS 10.8 安装教程(含安装包)

目录 一、ArcGIS10.8二、安装链接三、安装教程四、ArcGIS实战 &#xff08;一&#xff09;ArcGIS10.8 1. 概述 ArcGIS 10.8是由美国Esri公司开发的GIS平台&#xff0c;用于处理、分析、显示和管理地理数据&#xff0c;并实现数据共享。它具有新特性和功能&#xff0c;性能更…...

【小白学机器学习16】 概率论的世界观2: 从正态分布去认识世界

目录 1 从正态分布说起 1.1 正态分布的定义 1.2 正态分布的名字 1.3 正态分布的广泛&#xff0c;和基础性 2 正态分布的公式和图形 2.1 正态分布 2.2 标准正态分布 3 正态分布的认识的3个层次 3.1 第1层次&#xff1a;个体的某个属性的样本值&#xff0c;服从正态分布…...

Python 爬虫项目实战:爬取某云热歌榜歌曲

一、网络爬虫的定义 网络爬虫&#xff08;Web Crawler&#xff09;&#xff0c;也成为网页蜘蛛或者网页机器人&#xff0c;是一种按照既定规则自动浏览网络并提取信息的程序。爬虫的主要用途包括数据采集、网络索以及内容抓取等。 二、爬虫基本原理 1、种子URL&#xff1a;爬…...

HCIP-HarmonyOS Application Developer 习题(十八)

&#xff08;判断&#xff09;1、在HarmonyOS有序公共事件中&#xff0c;高优先级订阅者可修改公共事件内容或处理结果&#xff0c;但不能终止公共事件处理。 答案&#xff1a;错误 分析&#xff1a;有序公共事件&#xff1a;主要场景是多个订阅者有依赖关系或者对处理顺序有要…...

操作系统学习笔记2.3互斥

文章目录 进程同步实现方式 进程互斥实现方式 软件实现方法硬件实现方法同步问题生产者-消费者问题问题描述解决方案代码解析 多生产者-多消费者问题问题描述 解决方案代码解析总结 抽烟者问题问题背景 同步与互斥的挑战解决方案实现步骤代码解释 关键点 进程同步 进程同步是指…...

LLM - 使用 Neo4j 可视化 GraphRAG 构建的 知识图谱(KG) 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142938982 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Neo4j …...

Linux 环境的搭建方式->远程登录->免密登录

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;Linux系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;Linux知识点的补充_Jason_from_China的博客-CSDN博客 Linux 环境的搭建方式 Linux 环境的搭建主要有三种方式&#xff1a; 直接安…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...