Node.js路径处理模块摘要

文章目录 前言一、导入path模块二、核心API 1.path.join()2.path.basename()3.path.extname()4.path.parse() 前言 Node.js路径模块,也称path模块,作为Node.js内置API,path模块提供了一些用以处理文件路径的小工具。此篇用以总结常用核心API(自认为),其余API参照官方核心文档 path 路径 | Node.js API 文档... 或菜鸟教程 Node.js Path 模块 | 菜鸟教程 一、导入path模块 我们通过以下方式来引入该模块: const path = require('path'); 二、核心API 1.path.join() 使用path.join(),可以将多个路径片段,拼接成完整的路径字符串,其主要用途在于,会正确使用当前系统的路径分隔符,如Unix系统是"/",Windows系统是"\"。语法格式如下: path.join([path1][, path2][, ...]) 参数:多个路径片段 // 导入path模块,原以操作路径 const path = require('path'); let pathStr = path.join('/a', '/b/c', '../d', 'e'); console.log(pathStr); // \a\b\d\e let allPath = path.join(__dirname + './file/1.txt'); console.log(allPath); // C:\Users\林木木\Desktop\node\path模块\file\1.txt 注:若路径片段含有"../",意为屏蔽上一级路径;若路径片段含有"./",则会自动屏蔽掉该点后继续拼接 接上文:Node.js文件系统模块——读写文件操作https://blog.csdn.net/m0_53375764/article/details/126629578?spm=1001.2014.3001.5501 我们使用了__dirname与文件操作路径动态地拼接为文件的完整路径的方式,避免了预操作文件的路径动态拼接错误,但仍然存在错误风险,使用path.join()自动屏蔽“点”的策略,不仅避免了该低级错误的发生,也同时避免的采用“+”运算符拼接路径字符串的潜在风险。 const fs = require('fs'); const path = require('path'); // path.join()自动屏蔽 . let txtPath = path.

LRF-解决MySQL安装到start servic出现安装未响应或超时未安装成功

遇到这种情况一般都是以前安装过MySQL卸载后重新安装到最后一步配置出现问题:配置到start servic出现未响应或者超时未安装成功。 主要原因是MySQL部分配置文件并未完全清理。 方法一:清除MySQL残余文件 以下是清理MySQL残余文件步骤: 1 在控制面板-程序与功能中将以下两个MySQL软件卸载 2 将C:\ProgramData下的MySQL文件夹删除 C:\ProgramData一般处于隐藏状态,需要点击查看,将隐藏的项目勾上才可以看的到 3 删除MySQL在注册表中的信息:搜索注册表在以下路径找到MySQL目录删除 计算机\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\EventLog\Application\MySQL 4 搜索服务,进入服务界面,找到MySQL服务, 以管理员身份运行命令提示符,根据自己的MySQL服务输入以下代码,博主这里为MySQL80。所以输入 sc delete MySQL80 成功会返回一个: Delete service SUCCESS 完成以上步骤后重启电脑,进行MySQL的安装。 方法二:重置电脑(大招) 所谓大招是实在没办法了才使用的 注意:此方法重置电脑后所有配置的环境变量都需要重新配置:如jdk,git等,请三思!!! 设置–>更新与安全–>恢复–>重置此电脑 希望本文章能帮助到你,祝你MySQL配置成功!

深入了解下redis的acl

介绍 在Redis6之前的版本,我们只能使用requirepass参数给default用户配置登录密码,同一个redis集群的所有开发都共享default用户,难免会出现误操作把别人的key删掉或者数据泄露的情况,那之前我们也可以使用rename command的方式给一些危险函数重命名或禁用,但是这样也防止不了自己的key被其他人访问。 登陆Redis Server只需要输入密码(前提配置了密码 requirepass )即可,不需要输入用户名,而且密码也是明文配置到配置文件中,安全性不高。并且应用连接也使用该密码,导致应用有所有权限处理数据,风险也极高。在Redis6.0有了ACL之后,终于解决了这些不安全的因素,可以按照不同的需求设置相关的用户和权限。 因此Redis6版本推出了ACL(Access Control List)访问控制权限的功能,基于此功能,我们可以设置多个用户,并且给每个用户单独设置命令权限和数据权限。 为了保证向下兼容,Redis6保留了default用户和使用requirepass的方式给default用户设置密码,默认情况下default用户拥有Redis最大权限,我们使用redis-cli连接时如果没有指定用户名,用户也是默认default。 我们可以在配置文件中或者命令行中设置ACL,如果使用配置config文件的话需要重启服务,使用配置aclfile文件或者命令行授权的话无需重启Redis服务但需要及时将权限持久化到磁盘,否则下次重启的时候无法恢复该权限, 本文来介绍下Redis 6.0 ACL相关的配置和使用,具体的说明可以查看官方文档:ACL | Redis 配置文件模式 配置ACL的方式有两种,一种是在config文件中直接配置,另一种是在外部aclfile中配置。配置的命令是一样的,但是两种方式只能选择其中一种。 ACL规则 ACL是使用DSL(Domain specific language)定义的,该DSL描述了用户能够执行的操作。该规则始终从上到下,从左到右应用,因为规则的顺序对于理解用户的实际权限很重要。ACL规则可以在redis.conf文件以及users.acl文件中配置DSL,也可以在命令行中通过ACL命令配置。 启用和禁用用户 on:启用用户:可以以该用户身份进行认证。 off:禁用用户:不再可以使用此用户进行身份验证,但是已经通过身份验证的连接仍然可以使用。 允许和禁止调用命令 +<command>:将命令添加到用户可以调用的命令列表中。 -<command>:将命令从用户可以调用的命令列表中移除。 +@<category>:允许用户调用 <category> 类别中的所有命令,有效类别为@admin,@set,@sortedset等,可通过调用ACL CAT命令查看完整列表。特殊类别@all表示所有命令,包括当前和未来版本中存在的所有命令。 -@<category>:禁止用户调用<category> 类别中的所有命令。 +<command>|subcommand:允许使用已禁用命令的特定子命令。 allcommands:+@all的别名。包括当前存在的命令以及将来通过模块加载的所有命令。 nocommands:-@all的别名,禁止调用所有命令。 允许或禁止访问某些Key ~<pattern>:添加可以在命令中提及的键模式。例如~*和* allkeys 允许所有键。 * resetkeys:使用当前模式覆盖所有允许的模式。如: ~foo:* ~bar:* resetkeys ~objects:* ,客户端只能访问匹配 object:* 模式的 KEY。 为用户配置有效密码 ><password>:将此密码添加到用户的有效密码列表中。例如,>mypass将“mypass”添加到有效密码列表中。该命令会清除用户的nopass标记。每个用户可以有任意数量的有效密码。 <<password>:从有效密码列表中删除此密码。若该用户的有效密码列表中没有此密码则会返回错误信息。 #<hash>:将此SHA-256哈希值添加到用户的有效密码列表中。该哈希值将与为ACL用户输入的密码的哈希值进行比较。允许用户将哈希存储在users.acl文件中,而不是存储明文密码。仅接受SHA-256哈希值,因为密码哈希必须为64个字符且小写的十六进制字符。 !<hash>:从有效密码列表中删除该哈希值。当不知道哈希值对应的明文是什么时很有用。 nopass:移除该用户已设置的所有密码,并将该用户标记为nopass无密码状态:任何密码都可以登录。resetpass命令可以清除nopass这种状态。 resetpass:情况该用户的所有密码列表。而且移除nopass状态。resetpass之后用户没有关联的密码同时也无法使用无密码登录,因此resetpass之后必须添加密码或改为nopass状态才能正常登录。 reset:重置用户状态为初始状态。执行以下操作resetpass,resetkeys,off,-@all。 使用下面的命令查看help文档: ACL LIST 我们可以使用ACL LIST命令来查看当前活动的ACL,默认情况下,有一个“default”用户: 其中user为关键词,default为用户名,后面的内容为ACL规则描述,on表示活跃的,nopass表示无密码, ~* 表示所有key,+@all表示所有命令。所以上面的命令表示活跃用户default无密码且可以访问所有命令以及所有数据。 授权方式:

浏览器-错误 未能加载 PDF 文档

**问题现象:**使用浏览器chrome / firefox等时打开pdf文档报错,但排查后端接口数据返回正常 日志:错误 未能加载 PDF 文档 二:问题原因 浏览器安全配置阻止了非信任网站的跳转和弹窗等行为,无法加载PDF文档。现可以配置解决 三、Chrome配置办法: 1、在浏览器中输入 chrome://settings/ 2、隐私设置和安全性 >> 网站设置>>弹出式窗口和重定向 配置白名单后即可访问pdf文档

关于篮球计算战斗力的一道题

以前看到过一道题。 有十个人打篮球。每个人都有对应的战斗力。如何去将这些人分成两队。并且在战斗力的差距上是最小的。 要求 输入[1,2,3,4,5,6,7,8,9,10] 输出 1 let arr =[1,2,3,4,5,6,20,60,100,110] function dps(arr){ let la= [arr[9]] let ra = [arr[8]] for (let i = 7; i >=0; i-=2) { let num= arr[i],sunNum= arr[i-1] // 求两个数组的差 let arrsPoor = poor(la,ra) //左队的战斗力比右队的大,并且差值少于后面两个人战斗力总和 或者 两队战斗力相当 或者左队的战斗力比右队的大并且差值大于后面两个人的总和的时候当右队只能进入一个队员 if((arrsPoor > 0 && arrsPoor<(num+sunNum)) || arrsPoor==0 ||(arrsPoor > 0&&arrsPoor> (num+sunNum)&&ra.length==4)){ la.push(sunNum) ra.push(num) }else if((arrsPoor<0 && Math.abs(arrsPoor)<(num+sunNum))||(arrsPoor<0 &&Math.abs(arrsPoor)>(num+sunNum)&&la.length==4) ){ la.push(num) ra.push(sunNum) }else if(arrsPoor >0 &&arrsPoor>(num+sunNum)&&ra.length<=3){ ra.push(num,sunNum) }else if(arrsPoor<0 &&Math.

计算机网络笔记(王道考研) 第四章:网络层

内容基于中国大学MOOC的2023考研计算机网络课程所做的笔记。 感谢LY,他帮我做了一部分笔记。其中第四章网络层各小节的顺序稍微做了下调整,和上课老师讲的先后顺序稍有不同,但内容是完整的。 课程内容和西电平时讲课的内容大致重合,西电可能会多讲一点内容,但多讲的考试基本不是重点,自己对照任课老师的课件补一下即可。考试要复习的内容看上去很多,但最后考的都很基础,基本不会考特别偏的知识。 王道的计网讲的中规中矩,听课听完可能会有点懵,建议快速过一遍内容后就开始刷题来加深理解。 其他章节的链接如下: 计算机网络笔记(王道考研) 第一章:计算机网络体系结构 计算机网络笔记(王道考研) 第二章:物理层 计算机网络笔记(王道考研) 第三章:数据链路层 计算机网络笔记(王道考研) 第四章:网络层 计算机网络笔记(王道考研) 第五章:传输层 计算机网络笔记(王道考研) 第六章:应用层 其他各科笔记汇总 网络层 网络层功能概述 网络层 主要任务是把分组从源端传到目的端,为分组交换网上的不同主机提供通信服务 网络传输单位是数据报 IP数据报过大就会进行分片,分片后的小单位即网络层的传输单元分组 功能一:路由选择和分组转发 最佳路径 功能二:异构网络互联 功能三:拥塞控制 若所有结点都来不及接受分组,而要丢弃大量分组的话,网络就处于拥塞状态。因此要采取一定措施,缓解这种拥塞 解决拥塞的方法: 开环控制:静态。在网络开始工作前就考虑所有能够产生拥塞的因素进行预先控制闭环控制:动态。网络运行起来后自动调整 路由算法及路由协议 路由算法 路由协议使用路由算法算出最佳路由填入路由表的每一个表项 路由算法的分类 链路费用(路径代价)即路由器的跳数 分层次的路由选择协议 产生原因: 因特网的规模很大。如果让所有的路由器都知道所有的网络如何到达,每个路由器的路由表都会异常庞大,处理起来很耗时许多单位不想让外界知道自己的路由选择协议,但还是想连入因特网 将整个因特网分成许多自治系统AS,AS外部和内部互相看不到使用的协议 网关≈路由器 RIP协议与距离路由算法 RIP和OSPF使用的路由算法不同(RIP —— 距离向量路由算法,OSPF —— 链路状态路由算法),适用的网络大小不同(RIP —— 较小网络,OSPF —— 较大网络) RIP协议 直接交付:路由器和目的网络直接相连 RIP协议和谁交换?多久交换一次?交换什么? 距离向量算法 之所以要替换是因为路由表的更新要以最新消息为准 练习1: 练习2: RIP协议的报文格式 不需要记忆报文的格式以及相应字段。只需要注意到RIP是应用层协议,封装好的RIP报文塞到UDP数据报中传送,并且一个报文最多可以传送25条路由表项信息 RIP协议好消息传得快,坏消息传得慢 RIP的特点:当网络出现故障时,要经过比较长的时间(例如数分钟)才能将此信息传送到所有的路由器,”慢收敛“ OSPF协议及链路状态算法 OSPF协议 链路状态协议≈链路状态算法 注意这里链路的度量/代价和之前讲的距离向量不一样,不是跳数 链路状态路由算法 OSPF区域 主干区域的标识符规定为0.0.0.0,负责连通其他下层区域

25. Python 字符串的切片方法

25. Python 字符串的切片方法 文章目录 25. Python 字符串的切片方法1. 索引取值知识回顾2. 什么是切片3. 切片的语法4. 切片示例4.1 步长为1的切片取值4.2 步长为2的切片取值4.3 省略开始索引4.4 省略结束索引4.5 步长为-2 5. 课堂练习6. 总结 1. 索引取值知识回顾 【索引取值语法】 字符串索引取值由3部分构成: 字符串变量名或者字符串本身。英文中括号。索引。 【代码示例】 # 将字符串ABCDEFG赋值给变量string string = 'ABCDEFG' # 取字符串的第1个元素 # 变量名string ;英文中括号;索引为0 print(string [0]) 【终端输出】 A 2. 什么是切片 索引取值可以从字符串中取出1个字符。 如果要从字符串中取出多个字符,可以用字符串的切片方法。 【备注】上述图片来自关东升的《看漫画学Python》。 3. 切片的语法 【语法】 字符串[star:end:step] 字符串[开始字符:结束字符:步长] 字符串切片取值由4部分构成: 字符串变量名或者字符串本身。 英文中括号。 3个参数。 3个参数之间用英文冒号分隔。 参数start:表示要取的第1字符的索引(包括该字符),如果不指定,则默认为0。 参数end:表示要取的最后一个字符的索引(不包括该字符),如果不指定,则默认为字符串的长度。 参数step:表示切片的步长。如果省略,则默认为1,当省略该步长时,最后一个冒号也可以省略。 步长我的理解就是向前或向后走几步,可以是正整数,也可以是负整数。 步长为1,表示向前走1步,那就是依次取值。 步长为2,表示一次性向前走2步,那就是要跳过1个字符。 步长为-2,表示一次性向后退2步,即从右往左跳过1个字符。 【重点提示】切片取值时包括开始字符,不包括结束字符,简单记忆为含前不含后。 4. 切片示例 4.1 步长为1的切片取值 # 将字符串"星河滚烫你是人间理想"赋值给变量a a = "

2022/08/31 吉软 JSP的基本使用

学习目录 一、JSP的介绍与创建 二、JSP的本质 三、JSP的语法 四、JSP中的常用脚本 1. 声明脚本 2. 表达式脚本 3. 代码脚本 五、JSP三种注释 六、JSP九大内置对象 七、JSP四大域对象 面试题: 1.JSP和servlet的区别 2.JSP作用域 3.JSP的九大内置对象。内置:不需要创建,直接就能用。 一、JSP的介绍与创建 JSP的全称是Java Server Pages,即Java的服务器页面JSP的主要作用是代替Servlet程序回传HTML页面的数据web目录(或其他)右击 --> new --> JSP/JSPX --> 输入文件名 --> 选择JSP file创建 二、JSP的本质 JSP页面本质上是一个Servlet程序,第一次访问JSP页面时(运行Tomcat服务器后在浏览器地址栏 输入路径),Tomcat服务器会将此JSP页面翻译成为一个Java源文件,并对其进行编译成为.class字 节码文件(一个.java,一个.class),当打开.java文件时发现其中的内容是: 而HttpJspBase类直接继承于HttpServlet类,即JSP翻译出来的Java类间接继承于HttpServlet类,证明JSP页面是一个Servlet程序 三、JSP的语法 JSP头部的page指令: <%@ page contentType="text/html;charset=UTF-8" language="java" %> JSP头部的page指令可以修改JSP页面中的一些重要属性或行为 (以下属性均写在page指令中,默认page指令中没有出现的属性都采用默认值): (1) contentType属性:表示JSP返回的数据类型是什么,即response.setContentType()的参数值 (2) language属性:表示JSP翻译之后是什么语言文件(目前只支持Java) (3) pageEncoding属性:表示当前JSP文件本身的字符集(可在IDEA右下角看到) (4) import属性:表示导包(导类),与Java一致 (5) autoFlush属性:设置当out输出流缓冲区满了之后是否自动刷新缓冲区,默认值是true (6) buffer属性:设置out缓冲区的大小,默认是8kb 注意:out缓冲区满了之后不能自动刷新的话会报错 (7) errorPage属性: 设置当JSP页面运行出错时自动跳转到的页面(错误信息页面)的路径,这个 路径一般都是以斜杠打头,表示请求的地址是http://ip:port/工程路径/,对应代码web目录 (8) isErrorPage属性: 设置当前JSP页面是否是错误信息页面,默认是false,如果是true可以 获取错误信息 (9) session属性:设置访问当前JSP页面时是否会创建HttpSession对象,默认值是true (10) extends属性:设置JSP页面翻译出来的Java类默认继承谁

vm虚拟机安装centos7

目录 一、centos7 安装流程 1、创建新的虚拟机 2、选择典型并下一步 3、选择稍后安装操作系统并下一步 4、客户机操作系统选择Linux,版本选择CentOS 7 64 位并下一步 5、命名虚拟机名称并选择存储位置,选择下一步 6、根据建议设置磁盘大小,选择下一步 7、虚拟机已准备好创建,进行硬件设置 8、设g置内存大小2G(建议不小于2G) 9、设置处理器核数4核 10、设置CD/DVD,使用iso镜像文件 11、网络适配器选择NAT模式,否则虚拟机无法联网 12、结束硬件配置,关闭页面,选择完成 13、开启虚拟机 14、选择Install CentOS 7并enter(白色为当前选择) 15、选择语言并继续 16、软件选择GNOME桌面,便于前期练手,附加选项选择开发工具,最后完成 17、安装位置–我要配置分区–完成 18、点击"+“----挂载点选择”/"----50GB 19、点击"+“----挂载点选择"boot”----5GB 20、点击"+“----挂载点选择"swap”----5GB----完成 21、接受更改—开始安装 22、用户设置----root密码—输入–完成 23、用户设置–创建用户–完成—等待安装 24、重启 25、接受许可证—完成–完成配置 26、点击登录 27、选择汉语–前进 28、开始使用 二、总结 1、必须选择相对应的镜像文件 2、注意"/"“BOOT”"SWAP"的大小,不要超过总大小,否则要添加新的硬盘 3、网络适配器一定要选NAT模式 ** 正文 ** 一、centos7 安装流程 1、创建新的虚拟机 2、选择典型并下一步 3、选择稍后安装操作系统并下一步 4、客户机操作系统选择Linux,版本选择CentOS 7 64 位并下一步 5、命名虚拟机名称并选择存储位置,选择下一步 此处注意最好不要出现中文,并且单独的虚拟机单独一个文件夹 6、根据建议设置磁盘大小,选择下一步 大小可根据需求设置,但不得低于建议大小,此处设置的磁盘大小不是实际大小 7、虚拟机已准备好创建,进行硬件设置 8、设g置内存大小2G(建议不小于2G) 此处的内存大小可根据个人需求设置,不低于建议内存即可 9、设置处理器核数4核 两处都设2,处理器速度变快,4核效率也更快 10、设置CD/DVD,使用iso镜像文件 11、网络适配器选择NAT模式,否则虚拟机无法联网 一定要选择NAT模式,否则虚拟机处在一个封闭环境中无法联网 12、结束硬件配置,关闭页面,选择完成 13、开启虚拟机 14、选择Install CentOS 7并enter(白色为当前选择) 若看不见鼠标,可ctrl+ alt

qemu与gdb内核调试环境搭建

调试环境基于韦东山系列开发板IMX6ull虚拟环境搭建,韦东山给了详细的教程Qemu - 百问网嵌入式Linux wiki 。本篇文章主要是研究linux-4.9.88内核的基本架构,所以不对开发相关驱动进行太多的研究,所以整理出来的也是内核从编译到开发基本路径。环境基于Ubuntu18.04系统,可以通过VMware+Ubuntu的形式搭建环境,也可以直接使用独立的服务器Ubuntu进行。 1. qemu环境下载与配置 1.1 下载qemu整个开发包 在视频中演示的方法可能是直接下载压缩包,但是由于GIT仓库改版,只能使用下面方法下载使用GIT clone方式下载 请在ubuntu终端下执行如下命令,直接在线克隆整个仓库 git clone https://e.coding.net/weidongshan/ubuntu-16.04_imx6ul_qemu_system.git 如果使用GIT命令失败,有如下提示时 fatal: Out of memory, malloc failed (tried to allocate 314572801 bytes) fatal: index-pack failed 先执行下列命令增加swap分区 sudo dd if=/dev/zero of=/root/myswapfile bs=1M count=1024 sudo chmod 600 /root/myswapfile sudo mkswap /root/myswapfile sudo swapon /root/myswapfile 然后修改/etc/fstab,增加如下一行 /root/myswapfile swap swap defaults 0 0 最后重新执行上面的GIT命令进行下载,下载结束以后下载包镜像目录结构说明如下,在后续的开发过程中,我们有可能更换红框中的文件: 1.2 运行QEMU系统 假设你已经按照上文下载、解压好了QEMU镜像文件,你需要进入QEMU的目录,执行下列命令。 首次运行需要安装SDL环境 使用脚本自动解压安装: $./install_sdl.sh // 提示输入用户密码,等待安装完成 如果出现报错 Package xxxx is not installed.,可使用apt命令修复:

网页开发基础之HTML最常见的标记汇总

给大家总结收集了HTML中最常见的一些标签,这些也是学习前端最基础的必备知识,下面是最精简的汇总,可以把他们给记下来。 <!DOCTYPE>标记 位于文档的最前面,用于向浏览器说明当前文档使用哪种HTML标准规范。 <html>标记 用于告知浏览器其自身是一个HTML文档,<html>标记标记着HTML文档的开始。 <head>标记 用于定义HTML文档的头部信息,主要用来封装其他位于文档头部的标记。 <title>标记 用来描述文档的标题。 <meta>标记 可提供有关页面的元信息。 <link>标记 用于定义文档与外部资源的关系,其最常见的用途是链接样式表。 <style>标记 用于为HTML文档定义样式信息。 <body>标记 用于定义HTML文档所要显示的内容。 <hr />单标记 用于定义一条水平线。 <p>标记 使网页中的文字有条理地显示出来。 <br />标记 某段文字强行换行显示。 <font>标记 控制网页中文本的样式,face、size、color属性分别设置了文本的字体、大小、颜色。 <img />标记 在HTML网页中显示图像。src属性用于指定图像文件的路径,width、height属性宽度和高度,border属性用来设置图像的边框。 <table>标记 定义一个表格。 <tr>标记 用于定义表格中的行。 <td>标记 用于定义表格中的单元格,也可称为表格中的列,必须嵌套在<tr></tr>标记中。 <fieldset>标记 是将表单内的元素分组。 <legend>标记 则为<fieldset>标记定义标题。 <form>标记 用于定义表单域,即创建一个表单。action属性用于指定表单提交的地址,method属性用于设置表单数据的提交方式,其取值为GET或POST。 <input />控件 单行文本输入框、单选按钮、复选框、重置按钮等,使用<input />控件可以在表单中定义这些元素。 <textarea>标记 通过此标记可以创建多行文本框,cols=”每行中的字符数”,rows=”显示的行数”。 <ul>标记 定义无序列表。 <li>标记 嵌套在<ul></ul>标记中,用于描述具体的列表项。 <a>标记 创建超链接。 <div>标记 一个区块容器标记。

Linux网络编程--select()和pselect()函数

函数select()和pselect()用于IO复用,它们监视多个文件描述符的集合,判断是否有符合条件的时间发生。 1.select()函数 函数select()与之前的recv()和send()直接操作文件描述符不同。使用select()函数可以先对需要操作的文件描述符进行查询,查看是否目标文件描述符可以进行读、写或者错误操作,然后当文件描述符满足操作的条件的时候才进行真正的IO操作。 select()函数原型以及解释说明如下: select()函数例子: 使用select函数监视标准输入是否有数据处理,设置超时时间为5s。 #include<unistd.h> #include<sys/time.h> #include<sys/types.h> int main(){ fd_set rd;//定义fd_set类型的读描述符集合 struct timeval tv;//timeval 结构 int retval;//select返回值 FD_ZERO(&rd);//清空读描述符集合 FD_SET(0,&rd);//将描述符标准输入0放入读描述符集合中 tv.tv_sec=5; tv.tv_usec=0;//设置超时间为5S,select函数调用返回的时候会修改timeval的值为剩余的时间。 retval=select(2,&rd,NULL,NULL,&tv);//调用select函数监听标准输入,fd最大描述符个数加1(这里只监听标准输入一个描述符,那么这个值就是1+1,也就是2) // printf("[tv.tv_sec:%d]\n",tv.tv_sec); if(retval==-1){ perror("select"); } else if(retval){ printf("Data is avaialble now\n"); } else{ printf("NO Data within five seconds\n"); } return 0; } 2.pselect()函数 函数select()是用一种超时轮循的方式来查看文件的读写错误可操作性。在Linux下,还有一个相似的函数pselect()。 pselect()函数例子: #include<unistd.h> #include<sys/time.h> #include<sys/types.h> #include <signal.h> int sigint_event=0; void sigint_sig_handler(int s){//设置信号处理函数 sigint_event++; signal(SIGINT,sigint_sig_handler); } int main(){ int r; fd_set rd; sigset_t sigmask,orignal_sigmask;//设置新掩码和保存原始掩码 FD_ZERO(&rd);//清空读描述符集合 FD_SET(0,&rd);//将标准输入放入读描述符集合 sigemptyset(&sigmask);//清空信号 sigaddset(&sigmask,SIGINT);//将SIGINT信号加入sigmask中 //设置信号SIG_BLOCK的掩码sigmask,并将原始的掩码保存在orignal_sigmask中 sigprocmask(SIG_BLOCK,&sigmask,&orignal_sigmask); signal(SIGINT,sigint_sig_handler);//挂接信号处理函数 for(;;){ for(;sigint_event>0;sigint_event--){ printf("

ES6~ES13新特性整理

简单整理下ES6-13新特性的知识点 1.ES6 1.1 let和const var会有变量提升,let和const不会; let和const存在暂时性死区; let和const不可重复声明; var定义的变量为函数级作用域,let和const 块级作用域; const声明一个只读的常量。一旦声明,常量的值就不能改变。 【const一旦声明变量,就必须立即初始化。】实际上是指变量指向的内存地址保存的数据不可改动。对象数组,变量指向的内存地址保存的只是指针并不是实际的数据,所以const声明对象的时候,该对象本身是可以改的,但是不能将这个对象指向另一个地址。严格模式下可以用Object.freeze()。 1.2 class类 一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。 类的方法内部如果含有this,它默认指向类的实例。 //以项目中使用为例 class Person { constructor(first, last) { this.firstName = first this.lastName = last } } export default Person //使用的时候引入 import Person from 'xxxxxx' const person = new Person('kkkk', 'oooo') //打印出 Person {firstName: 'kkkk', lastName: 'oooo'} ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象。 class Person { constructor(first, last) { this.firstName = first this.lastName = last } play() { console.log('play') } } class LittlePerson extends Person { constructor(x, y, color) { super(x, y) // 调用父类的constructor(x, y) this.

谷歌Xswitch插件下载及安装失败原因

点击跳转:(无需币) XSwitch谷歌浏览器插件-Node.js文档类资源-CSDN下载 插件安装不成功的方法(找了半天终于找到的,亲测有效!!!) 1. 如果是.crx文件不能直接点安装,拖动安装也失败,需要保存在电脑中。 2.把程序的扩展名从 “.crx” 改变到 “.zip或rar”. 3. 在解压程序中打开,形成一个文件包!!! 4. 把文件夹放到你的硬盘目录下 5. 在谷歌浏览器的地址栏输入 “chrome://extensions/” 进入 6. 选择 “开发人员模式” 图标, 之后点击 “载入未完成的开发包” 按钮 7. 浏览第四步中的文件夹,之后点击确定. 

抛开脚手架搭建vue工程

平台的各位大佬专家们,大家好😀😀😀,本人是当前平台的小萌新。本期给大家带来第一篇文章——抛开脚手架搭建vue工程 项目搭建是一个很常见的需求,为了解决这个需求。vue 官方也做了很多的努力,比如: vue-cli, vite等等。各位是不是以为博主要把vue-cli和vite的文档给拿过来,抄一遍。no,本人抱着分享技术而且,官网里面有的,大家可以去参考对应的文档: vue-cli: https://cli.vuejs.org/zh/guide/vite: https://cn.vitejs.dev/guide/ 在上面的两个官方地址中会有详细的说明。 这里来带着大家来用最简单安装包的方式,一步一步实现一个可用于测试包的项目环境,简单的说就是搭建一个非常轻量级的项目,因为在年限不多的大部分程序员中,都会想要有一个轻量级的demo来进行深度学习和开发。当然,有的会问这个有啥作用。如果你发布一个包并且需要写测试案列。这种项目就会非常有用,毕竟大家都不想要有一个那么重的环境。 vue2搭建 请思考一个问题,搭建一个vue工程化的项目,最少使用几个包就能完成? 有人可能会说3个5个啥的,答案先不着急。请跟着节奏往下看。 分析 搭建vue的工程项目, vue肯定是少不了的;vue工程里面写的是vue的模板文件或者是jsx,当然您也可以使用原生的js,使用h和render函数的方式来编写代码,但是一般来说工程化都会使用额外的语法来编写便于维护的代码。所以这里咋们还需要一个complier(编译器)既然是前端的工程化的项目,那肯定也会使用构建工具了,如:webpack,vite 等. 有了这3步操作,vue的工程化项目就可以搭建起来了。快来一起来动手试试吧😀😀😀 搭建 对于vue2的项目,咋们来安装下下面的包: vue: vue2代码的核心包 vue-template-compiler: 编译vue代码的包 @vue/cli-service: 构建工具,这里有人说不用webpack,vue-cli里面就是继承了webpack哦! npm install vue@2 -S npm install vue-template-compiler @vue/cli-service -D 安装完成后,来建立一些文件夹: 在根目录下面建立src和public两个文件,然后建立对应的文件。最终的目录结构如下: vue2-simple-pro // 项目名称 ├─ package.json // 启动入口 ├─ npm-lock.yaml // 依赖锁文件 ├─ public // 公共文件,不会参与打包的 │ └─ index.html // 最终渲染的html文件 └─ src // 核心功能文件 ├─ App.vue // 根节点文件 └─ main.js // 入口js,挂载vue的节点 有了目录,要想让这个功能跑起来也是很简单的哦!

Grads:绘制风流畅

1、画风分布图和风流场 folder = 50mAvgMonthPic i=0 res='E:\Pic\chenxia\drawPic\name.txt' while(i<17) 'reinit' i=i+1 text=read(res) ln=sublin(text,2) filename=subwrd(ln,1) titlestr=subwrd(ln,2) 'open E:\Pic\chenxia\drawPic\ctl\'filename'.ctl' 'set grads off' 'set grid off' 'run E:\Pic\chenxia\drawPic\Colors_Wind.gs' 'set lon 112.8 115.2' 'set lat 37.5 39.5' 'set t 1' 'set ylopts 1 5 0.13' 'set xlopts 1 5 0.13' 'set xlint 0.5' 'set ylint 0.5' 'set gxout shaded' 'set csmooth on' 'd fengsu' 'cbarn 0.8 1' 'set gxout vector' 'set arrscl 0.2' 'set ccolor 1' 'd -fengsu*sin(fengxiang*3.

TCP 报文首部的 6 个标记位

目录 1、URG 2、ACK 3、PSH 4、SYN 5、FIN 6、RST 1、URG URG表示紧急标记位。当发送方希望一些数据尽快被接收方的上层拿到的时候,就需要用到这个标记位。通常需要搭配16位紧急指针使用,要传递的紧急数据混在普通数据里,16位紧急指针指明了紧急数据在普通数据中的具体位置。 注意:紧急数据一般只能传递(或者说占用)一个字节,因为大多数情况下,报文都是按序到达然后被读取的,如果紧急数据太多,读取的时间太长,会破坏TCP按序到达的特性。 2、ACK ACK表示确认应答标记位。在TCP确认回复机制中,客户端和服务端任意一方发送数据后,另一方都需要给予应答以表明自己收到数据。在应答的报文中该标记位需要置1,同时应答的报文也可以携带数据。 3、PSH PSH表示催促标记位,可以理解为Push。Client在不断发数据,Server在不断接收数据同时在给Client发送应答,应答报文中包含了16位窗口大小的字段,其实就是在告诉Client自己接收缓冲区剩余空间的大小,以便于Client及时调整自己的发送速度。 但是,Server接收缓冲区快满了或者说已经满了,此时Client给在发送的报文里设置PSH标记位来催促对方尽快取走缓冲区的数据。 补充: (1) 为什么缓冲区会满了? 缓冲区满了可能是因为Server应用层还在处理上一条数据,导致没有时间调用read接口函数来取走缓冲区里的数据。 (2) 如何理解“OS催促上层尽快取走数据”? 缓冲区存在低水位和高水位标记,OS 催促上层取数据的依据便来源于此,低水位就代表当前数据太少了,先别急着读;高水位就代表缓冲区里的数据太多了,赶紧来取走。 一般OS是让上层每次都读取一批数据,而不是每次只读取一个字节。因为上层是调用read接口函数来从缓冲区读取数据的,如果每次都只读取一个字节,那就需要频繁的调用read函数,也就需要频繁的在用户态和内核态之间切换,这样会降低效率。 4、SYN SYN表示同步标记位,其实就是申请建立连接的标记位。TCP是面向连接的协议,双方在正常通信之前需要先建立连接,建立连接是一个三次握手的过程。 第一次,Client 给Server发送请求连接,报文中携带SYN标记位来表明当前报文是和建立连接相关的。 第二次,Server接受Client的连接,并询问何时建立连接,报文中也会携带SYN标记位,同时会携带ACK来回复上一条请求。 第三次,Client 回复 Server,立马建立连接,这里只是单纯的回复,只要设置ACK即可。 那么问题来了,站在Client的角度,什么时候认为连接已经建立起来了呢?答案是第二次握手以后,即收到Server的回复。然而站在Server的角度,建立连接的时候是在第三次握手,因为第二次握手只是Server端单方面同意了,Client端有没有同意是在第三次握手才知道。 5、FIN FIN表示结束标记位,可以理解为Finish,其实就是断开连接的标记位。断开连接是一个四次挥手的过程。为什么会有四次呢?Client 单方面断开连接需要两次;Server端单方面断开连接需要两次,加起来就是四次。谁先断开连接,这个没有限制,下面就假设Client先断开。 第一次挥手,Client 通知 Server 自己单方面断开连接,Client发送的报文中就会携带FIN标记位。 第二次挥手,Server收到Client的通知请求,并给Client发送应答报文,报文中携带ACK标记位。 第三次挥手,Server 通知 Client 自己单方面断开连接,Server发送的报文中会携带FIN标记位。 第四次挥手,Client收到Server的通知请求,并给Server发送应答报文,报文中携带ACK标记位。 补充:Client单方面断开连接以后,只是断开Client ——》Server方向上的数据传输,此时Server可以给Client发送数据,反过来不行。 6、RST RST表示复位标记位,用于非正常的关闭连接。客户端因为主机崩溃或者网线断开,但是服务端认为对方还在。如果服务端长时间没有收到对方的数据,就会定期发送报文询问对方是否在线;客户端收到以后,由于连接不存在,此时就会发送携带RST标志位的报文来间接告诉服务端连接异常。

解决ffmpeg读取视频流时,报错“Segmentation fault (core dumped)“,avformat_open_input 返回 -1330794744

错误现象: ffmpeg读取视频流时,直接报错返回“Segmentation fault (core dumped)”;排查中发现是avformat_open_input函数错误,返回的是-1330794744,而不是代表正确的0。 这个问题困扰了我很久,网上也搜了很久,但解决办法中都没提及ffmpeg的版本,在试错很多次后,发现了问题的所在,是代码与ffmpeg的版本有些不兼容的问题,那就直接切入主题。 这次我试了ffmpeg的两个大版本:(一定对照自己的版本来看) ffmpeg-n4.4-latest-linux64-gpl-shared-4.4.tar.xz (这是github上别人编译好的)(在ubuntu和windows上都能直接跑起来) 这个版本我在我的centos7上跑不起来,make就会报类似这样的错:“/opt/ffmpeg/lib/libavcodec.so: undefined reference to _ZGVcN4vv_pow@GLIBC_2.22 /opt/ffmpeg/lib/libavcodec.so: undefined reference to _ZGVeN16v_expf@GLIBC_2.22 /opt/ffmpeg/lib/libavcodec.so: undefined reference to _ZGVbN2v_exp@GLIBC_2.22 /opt/ffmpeg/lib/libavcodec.so: undefined reference to _ZGVbN2vv_pow@GLIBC_2.22’”warning说是因为缺乏libmvec.so.1这个库,显然因为glibc版本的问题(我centos的glibc是2.17的,版本太低,yum暂时最高就是这,不能yum升级;手动去升级话,是有可能会把系统弄崩的,所以要慎重,特别生产环境一定慎重,虚拟机可以先拍一个快照);然后我在一个centos虚拟机上,手动编译glibc,把glibc升级到2.25,就能成功运行;查看glibc版本的命令:ldd --version FFmpeg-n3.4.9 (这个是自己源码编译的) 这个在glibc为2.17的centos7上能make能成功,但是一运行,就报错"Segmentation fault (core dumped)”,排查是avformat_open_input()函数返回的是-1330794744,解决办法很简单,在你代码main()函数开头加这样两行: av_register_all(); avformat_network_init(); 这应该是在ffmpeg版本4后,是没有这俩api了,网上的解决办法也总是直接说加这两行,也没说版本,这要是加了这两行的代码使用上面ffmpeg-n4.4版本,编译都是会直接报错的。 嗯,说的是很详细了,别的错误情况也说到了,也是自己反复各种尝试,ffmpeg都编译了十多次,还以为是自己预编译指令没给对,所以重点是,一定要注意自己的ffmpeg版本是多少,看你报错是上面哪种,对症下药。 所以如果有帮到你,请点个赞吧!

Spring 异步事件监听器

基于spring SmartApplicationListener实现异步事件监听器,但是两个异步之间的控制不了执行顺序 /** * 定义事件监听器的顺序 * @return */ @Override public int getOrder() { return 100; } 无效 idea中需要加上延迟才能看出异步的效果 效果图 访问地址:http://127.0.0.1:8090/hello 配置线程池 package com.event.springboot.configuration; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.lang.reflect.Method; import java.util.concurrent.Executor; /** * 配置线程池 * @author */ @Configuration public class ListenerAsyncConfiguration implements AsyncConfigurer { /** * 获取异步线程池执行对象 * @return */ @Override public Executor getAsyncExecutor() { //使用Spring内置线程池任务对象 ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); //设置线程池参数 taskExecutor.setCorePoolSize(1); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(25); taskExecutor.

HK32F030C8T6把OSC_IN和OSC_OUT作为普通的IO口使用

1.将OSC_IN和OSC_OUT初始化相应的模式 GPIO_InitStructure.GPIO_Pin = CSB_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(CSB_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = RSTB_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(RSTB_GPIO_PORT, &GPIO_InitStructure); 2.这样配置完之后发现GPIO输出的高电平电压完全达不到3.3V。原因是我们在初始化systemclock时,把外部晶振也初始化了。所以我们只需要把外部晶振不使能,就可以把OSC_IN和OSC_OUT当作普通的IO口使用了。 打开函数 SystemInit();就会看到 void SystemInit (void) { /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; /* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits */ RCC->CFGR &= (uint32_t)0xF8FFB80C; /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */ RCC->CFGR &= (uint32_t)0xFFC0FFFF; /* Reset PREDIV1[3:0] bits */ RCC->CFGR2 &= (uint32_t)0xFFFFFFF0; /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */ RCC->CFGR3 &= (uint32_t)0xFFFFFEAC; /* Reset HSI14 bit */ RCC->CR2 &= (uint32_t)0xFFFFFFFE; /* Disable all interrupts */ RCC->CIR = 0x00000000; /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */ SetSysClock(); } 打开SetSysClock();并把 RCC->CR |= ((uint32_t)RCC_CR_HSEON) 修改为RCC->CR &= ~((uint32_t)RCC_CR_HSEON);