Node.js当中的文件操作(二)

文件的复制 我们可以利用流式读取与流式写入相配合进行文件的复制 let fs = require('fs'); // 文件的流式读取 let rs = createReadStream('./data.txt'); // 文件的流式写入 let ws = createWriteStream('./newData.txt'); // 给文件的流式读取添加 data 事件 rs.on('data',message => { // 每读取一小块就写入一下块 ws.write(message); }) // 监听流式读取的结束 rs.on('end',() => { console.log('读取完成'); }) 文件的移动与重命名 在 Node.js 中,我们可以使用 rename 或 renameSync 来移动或重命名 文件或文件夹 语法: fs.rename(oldPath, newPath, callback) fs.renameSync(oldPath, newPath) 参数说明: oldPath 文件当前的路径newPath 文件新的路径callback 操作后的回调 无论移动文件也好还是文件的重命名也好,其实本质上都是文件的路径转移(从当前路径转移到目标路径) 异步操作 fs.rename('./data.txt','./message.txt',(err) => { if (err) { console.log("移动失败"); return; } console.log('移动完成'); }) 同步操作

华为交换机日常维护检查有哪些常用的命令?

1、查看子卡的运行状态,可以用命令display device。此命令可以查看子卡在位信息及状态信息是否正常。 2、查看设备复位情况,可以用命令display reboot-info。 3、查看设备温度,可以用命令display temperature all。各模块当前的温度应该在上下限之间,即“Current”的值在“Lower”和“Upper”之间。 4、查看设备的告警信息,可以用命令display alarm urgent。如果没有告警就会显示无。 5、查看cpu状态,可以用命令display cpu-usage。各模块的CPU占用率正常。如果出现CPU占用率长时间超过80%或者频繁出现超过80%的情况,建议重点关注。 6、查看内存占用情况,可以使用display memory-usage。 7、查看日志信息,可以用display logbuffer或者display trapbuffer。这两个命令为会经常用到。

赞爆!凭借阿里的Java面试突击手册,成功翻盘上岸

你有面试机会了吗? 近期,肯定有很多小伙伴,投出去的简历HR基本上都是已读不回,甚至都没有任何回复,或者平台默认筛选,你的简历HR根本就看不到。 即使有些小伙伴简历通过,收到面试邀请了,结果被通知不用面试了; 还有些小伙伴,有面试机会了,甚至已经参加了面试,但是还是被刷下来了。 为什么会有这样的情况发生呢? 我给大家总结以下几点,只是作为参考,不喜勿喷: 学历,学历这一块儿是硬伤,也是敲门砖,不够的话就自动被筛选掉了,你投简历之前最好先看要面试的公司的学历要求,如果学历符合要求,再去投递简历; 简历,简历这一块儿,也是需要按需去做准备的,不能一份简历投递多家公司,因为你压根儿就不符合人家的要求,所以也是需要针对公司的业务、招聘需求去写对应的简历,符合公司要求,肯定会有优先权; 技能栈,技能这一块儿,才是真正要好好准备的。因为就算你的学历够,你的简历写的比较好,面试机会非常多;但是你面试都通过不了,就是因为你的技术栈不够宽,也不够深,不成体系化,所以说技术才是王道! 前面三项都通过了,但是还是没有收到入职邀请,直接被放鸽子了。那就是因为有比你更优秀的人出现,背景比你好,技术栈比你更深、更广,学历比你更好。 总之卷之又卷,在这种趋势下,不得不好好地提升自己,让自己的技术栈更加丰满,有机会上升到更大更高的平台,让自己的履历更加优秀,项目经验更加丰富,实现自己的人生价值! 在此前提之下,还需要先满足当下的需求,就是如何准备符合企业要求的技术栈呢? 为了能够助力大家准备面试,拿个高频面试手册系统查漏补缺一下多少是对你有帮助的!前段时间从阿里的朋友那里嫖到了一份据说是阿里技术官编写的面试手册,分享给大家。 由于篇幅限制小编,展示了部分目录及截图。 目录大纲七大点: 分布式 中间件 大数据与高并发 数据库 设计模式与实践 数据结构与算法 HR面试题举例 综合大纲截图 第一篇:分布式 一、大型网站系统的特点 二、大型网站架构演化发展历程 三、拆分 VS 集群 四、微服务 VS SOA 五、前后端完全分离与Rest规范 六、CAP三进二和Base定理 第二篇:中间件 一、缓存 二、消息队列 三、搜索引擎 第三篇:大数据与高并发 第四篇:数据库 第五篇:设计模式与实践 第六篇:数据结构与算法 ​ 第七篇:HR面试题举例 学Java会很坎坷,遇到问题自己解决不了,找工作碰壁,不知道如何练习项目,这是大多数人自学Java都会遇到的难题,也是我曾经学习过程中体验过的痛苦。 准备面试就要大量的去刷面经,刷面试题,这相当于高考前2个月的冲刺,一定会大大提高你获得更多offer的概率。 文中资料已整理打包存放网盘,有需要的朋友可以点击下方的名片自取!

Linux入侵检测病毒清理流程

Linux入侵检测病毒清理流程 1.前言: 根据阿里云快讯病毒公布: Redis RCE导致h2Miner蠕虫病毒,其利用Redis未授权或弱口令作为入口,使用主从同步的方式从恶意服务器上同步恶意module,之后在目标机器上加载此恶意module并执行恶意指令。在以往常见的攻击者或蠕虫中,其大多都沿用登陆redis后写入定时任务或写ssh key的方式进行入侵,这种方式受权限与系统类型影响并不一定能够成功。而此次使用redis加载module的攻击方式,可以直接执行任意指令或拿到shell交互环境,危害极大。 当服务器中毒了,使用SSH/FTPS大多连接不上的。这时候就需要到云平台,使用VNC方式登录。 2.确认Linux是否是中毒 1.使用命令查看当前系统所有进程 一般消耗CUP或者内存90%以上的基本都是病毒,常见的挖矿进程:xfsdatad、rshim、YDService.exe、kinsing、kdevtmpfsi、sysupdate、systemxlv、kthreaddi、kthreaddk 等,病毒进程一版都会跟系统进程名称相似,要注意区分 top 或 ps aux | less 注:top实时监控退出按键:q 2.查看隐藏进程 如果top命令查看没发现异常,但是服务器依然很卡,服务器资源占用居高不下,那就换个命令,查看是否存在隐藏进程 ps -aux --sort=-pcpu|head -10 3. 确定病毒攻击方式 1.使用命令查看系统日志: cat /var/log/secure 1.1分析日志文件,看看是否是远程强行破解系统密码,如下:如果是远程登录root,清理病毒后要修改root的密码 1.2如果不是远程登录root,很可能是redis远程登录导致:1.1.2查看redis连接记录: lsof -i:6379 如果有大量异常链接,立即找到redis安装路径,打开 redis.conf vim redis.conf 把 bind:127.0.0.1 打开,重启redis ps -ef | grep redis kill -9 PID ./src/redis-server ./redis.conf 1.1.3如果redis也没有问题,那就查看系统其他用户:查看系统用户 vim /etc/shadow 或者 vim /etc/passwd 检查是否有异常的用户名,如果有就删除 userdel -r 用户名 4.查看单个进程的执行日志: more /var/log/cron log | grep “进程名称” 3.病毒查杀 1.先确定挖矿进程的PID

CentOS7离线安装GCC9.3.0(亲测)

目录 前言 安装文件下载 离线安装 安装GMP 安装MPFR 安装MPC 安装ISL-0.24 安装GCC-9.3.0 配置环境变量 更新动态库 参考资料 前言 安装CentOS7后,系统会默认安装GCC4.8.5(可执行文件位于 /usr/bin 目录,头文件位于 /usr/include 目录,库文件位于 /usr/lib 目录)。但有些C/C++源代码需要较高版本编译器才能编译,且服务器还在公司内网,不能在线升级编译器。本文主要介绍如何在不删除原编译器的条件下,离线安装GCC9.3.0。 安装文件下载 GCC依赖四个库:GMP、MPFR、MPC、ISL。GMP:计算任意精度的数学库, 包括支持整数,有理数和浮点。MPFR: 一个多精度高效的浮点计算C语言库, 基于GMP。MPC:一个支持高精度复数的算术运算的C库,并能正确的进行结果舍入。ISL:用于操作集合和线性约束下的整数点的关系的库,支持集合的交,并和补操作。 其中,MPFR依赖GMP,MPC依赖GMP和MPFR,GCC依赖上面四个库,所以推荐的编译安装顺序是GMP->MPFR->MPC->ISL->GCC。 我们选择下载如下版本,且给出了下载地址: GMP-6.2.1 https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xzMPFR-4.2.0 https://www.mpfr.org/mpfr-current/mpfr-4.2.0.tar.xzMPC-1.3.1 https://ftp.gnu.org/gnu/mpc/mpc-1.3.1.tar.gzISL -0.24 http://ftp.tsukuba.wide.ad.jp/software/gcc/infrastructure/isl-0.24.tar.bz2GCC-9.3.0 http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-9.3.0/gcc-9.3.0.tar.xz 离线安装 安装GMP 将下载的gmp-6.2.1.tar.xz解压缩到/home目录(/home/gmp-6.2.1),为了便于后续管理,新建 /usr/local/gmp-6.2.1 目录,并将gmp库安装于此目录,安装指令如下: cd /home/gmp-6.2.1 ./configure --prefix=/usr/local/gmp-6.2.1 make -j8 make install -j8 安装MPFR 将下载的mpfr-4.2.0.tar.xz解压缩到/home目录(/home/mpfr-4.2.0),新建 /usr/local/mpfr-4.2.0 目录,并将mpfr库安装于此目录,安装指令如下: cd /home/mpfr-4.2.0 ./configure --prefix=/usr/local/mpfr-4.2.0 --with-gmp-include=/usr/local/gmp-6.2.1/include --with-gmp-lib=/usr/local/gmp-6.2.1/lib make -j8 make install -j8 由于MPFR库依赖GMP库,因此需要–with命令指定GMP库的头文件目录和库文件目录。 安装MPC 将下载的mpc-1.3.1.tar.xz解压缩到/home目录(/home/mpc-1.3.1),新建 /usr/local/mpc-1.3.1 目录,并将mpc库安装于此目录,安装指令如下: cd /home/mpc-1.

linux学习[11]磁盘与文件系统(2):lsblk&blkid&parted&fdisk&gdisk&mkfs

文章目录 前言:1. 磁盘容量1.1 lsblk1.2 blkid1.3 parted 2. 磁盘分区2.1 fdisk/gdisk2.2 磁盘分区实例参考: 3. 磁盘格式化3.1 mkfs.xfs3.2 mkfs.ext43.3 mkfs.vfat 总结: 前言: 写了VMware的磁盘扩容之后,磁盘分区格式化等操作用上了,这篇博客就做一个知识点补充归纳。 这篇博客主要写: 指令磁盘分区容量查看指令:lsblk、blkid、parted; 磁盘分区指令:gdisk/fdisk; 格式化指令:mkfs相关 1. 磁盘容量 1.1 lsblk lsblk真的是yyds了,和指令ls一样是常用指令。前者是磁盘的查看,ls是目录和文件的查看。 一般用法:lsblk 选项与参数 设备 例如:lsblk -d /dev/sda 选项与参数含义-d仅列出磁盘本身,并不会列出该磁盘的分区数据-f同时列出该磁盘内的文件系统名称-i使用 ASCII 的线段输出-m同时输出该设备在 /dev 下面的权限数据 (rwx 的数据)-p列出该设备的完整文件名-t列出该磁盘设备的详细数据,包括磁盘伫列机制、预读写的数据量大小等 以我的虚拟机上的60G磁盘为例进行效果演示。 使用lsblk常用的显示的字段含义如下: 字段名称字段含义NAME设备的文件名,省略 /dev 等前导目录MAJ:MIN主要:次要设备代码RM是否为可卸载设备,如光盘、USB 磁盘等等SIZE容量RO是否为只读设备TYPE种类:磁盘(disk)、分区(partition) 、只读存储器(om)MOUTPOINT挂载点FSTYPE文件系统LABEL标签UUID全域单一识别码 1.2 blkid blkid其实就是lsblk -f中单独显示UUID的一个指令。 所以其对应的含义为:列出设备的UUID; 这里需要注意的是,只有管理员权限才可以列出对应的内容。 下图中我用ubuntu用户输入blkid没有反应,改变为root权限后才可以。 其实也可以直接sudo blkid 如何想查看一个指定的磁盘,在没有管理员权限的情况下可以使用: 指令:sudo blkid /dev/sda 使用这个指令,可能linux系统还会提示你输入管理员密码。 1.3 parted parted指令用来列出磁盘的分区表类型以及分区信息。 一般用法:parted /dev/sda print 这个指令也是需要管理员权限的,别忘加sudo,或者切换到root 这里我们看字段:Partition Table:msdos

EPLAN2.9_连接定义点(线号)去斜线方法,自动线号放置与编号

本文将介绍连接定义点去斜线的方法、自动线号的放置及其自动编号命名。最终的效果图如下: 一、放置一套没有斜线的线号 新建一套连接定义点的命名规则,后续将用此套规则来放置及命名线号。 1.选定目标页面,执行菜单:选择>项目数据>连接>放置。 2.点击下图中右边三个小点点的拓展图标。 3.点击下图中右上方小太阳形状的新建图标,在弹出的新配置界面中输入名称(PPQ的)和描述后,点击下方的确认按钮。 4.在新界面中,选择放置一栏,之后点击图中央三个小点点的拓展图标,在弹出的符号选择界面中,将图标的序号<16002>从默认的308变更为311,如图所示,之后点击下方的确认按钮。 5.将放置数变更至-再连接的开端和末尾,点击当前界面的确认按钮,返回上一层。 6.点击当前界面的确认按钮。 7.这样,一套没有斜线的连接定义点(图中的一排红色问号????)就放置完成了。 二、线号的位置及方向调整 如果需要调整线号的位置及方向,可以进行如下设置: 8.选定目标页面,执行菜单:选择>项目数据>连接>重新对齐和格式化。 9.确认配置名称是刚刚创建的那个(PPQ的),点击弹出界面中右边三个小点点的拓展图标,之后在新界面中选择显示一栏,设定线号的位置及方向(我习惯使用:水平 -0.50mm,垂直 0.50mm,角度 与连接平行),如图设置完成后,点击下方的确定按钮返回上一级界面。 10.点击当前界面中的确定按钮,可以看到,图中问号的位置变的更佳和谐了。 三、线号的命名 如果想将问号变成有序的线号,可以进行如下设置: 11.点击键盘上的 Ctrl+A 进行当前界面的全选,之后执行菜单:选择>项目数据>连接>命名。 12.在弹出的界面中,确认配置名称是刚刚创建的那个(PPQ的),点击右方三个小点点的图标,之后在弹出的界面中点击右上角小太阳的新建图标。在弹出的新界面-连接编号:格式中,选择左边栏的计数器,之后点击界面中间的右箭头。在弹出的界面中将最小位数从0改为3,之后点击界面下方的确定按钮。 13.在返回的上一层界面中可以看到一个新建的格式元素,点击界面下方的确定按钮。 14.点击返回的上一层界面中的确定按钮。 15.在返回的上一层界面中确认增量的起始值和增量均为1,点击界面下方的确定按钮。 16.在弹出的界面:对连接进行说明:结果预览 中,可对新的连接代号进行预览(亦可在此手动对其进行修改),确认无误后,点击界面下方的确定按钮。 17.最终的编号效果图如下图所示。 结束,谢谢观看。

Centos7 离线安装gcc gcc-

方法一:centos7 挂载本地iso yum源 cd /etc/yum.repos.d/ mv /etc/yum.repos.d/CentOS-* /tmp/ vim ios.repo [ios] name=ios baseurl=file:///mnt/cdrom enable=1 gpgcheck=0 #镜像挂载本地 mount -o loop CentOS-7-x86_64-DVD-2009.iso /mnt/cdrom/ yum clean all yum makecache yum -y install gcc gcc-c++ 方法二: 1.下载centos镜像: https://buildlogs.centos.org/rolling/7/isos/x86_64/ 我下载的是 CentOS-7-x86_64-DVD-1611.iso,对应的gcc 版本是 4.8.5 如果需要更高版本的gcc,按照时间排序,选择日期靠前的镜像下载,如下图: 2.用压缩工具打开镜像,进入Packages 目录 拷贝下面的文件: 3.将文件上传到服务器,安装: rpm -Uvh *.rpm –nodeps –force 4.安装成功后,查看版本 gcc -v g++ -v

使用esp32+micropython+microdot搭建web(http+websocket)服务器(超详细)第一部分

使用esp32+micropython+microdot搭建web(http+websocket)服务器(超详细)第一部分 microdot文档速查 什么是Microdot?Microdot是一个可以在micropython中搭建物联网web服务器的框架micropyton文档api速查 Quick reference for the ESP32 先来个小demo先体验一下 演示视频链接 视频中我们简单的实现了 使用esp32搭建web服务器实现get请求上传网页到服务器手机打开网址访问该网页服务器处理请求,实现开灯关灯操作 准备工作 百度网盘:https://pan.baidu.com/s/1ZKbaGjdjuBMJgK9l6w9mdg?pwd=1234 提取码:1234 esp32开发板一个micro数据线一条(支持数据传输,有些只能充电)micropython固件,下载地址MicroPython - Python for microcontrollers或者网盘中获取(esp32-20220618-v1.19.1.bin)esp32电脑驱动(没有他电脑不能识别esp32),网盘中获取(esp32usbDriver.zip)Thonny,下载地址Thonny, Python IDE for beginners 或者网盘中获取(thonny-4.1.1.exe)vscode,下载地址Documentation for Visual Studio Code 或者网盘中获取(VSCodeUserSetup-x64-1.79.2.exe)microdot Microdot是一个可以在micropython中搭建物联网web服务器的框架(点击查看) 安装esp32电脑驱动 解压该文件 点击安装该驱动(64位电脑选择上面,32位电脑选择下面)安装完记得重启电脑,不然可能不生效 安装Thonny 点击安装 thonny切换中文,点击tools 点击options选择language,中文重启就汉化成功 新建一个空文件夹,然后新建一个main.py文件 使用thonny打开它 给esp32刷入micropython固件 micro数据线连接电脑,然后连接esp32点击配置解释器 选择Micropython(esp32)解释器和选择端口,这个端口就安装电脑驱动之后生成的,名字可能不一样(如果没有端口,可能是驱动没装上或者线没连好)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dUJJotD8-1687272884567)(<转存失败,建议直接上传图片文件 >)] 点击Install or update MicroPython选择端口和固件(网盘里面有) 等待进度条走完就好了 如果一直不显示百分比 按住 esp32上的boot键 ESP32开发板上有2个按键,分别是boot和EN。烧录前需要先打开Download模式:长按boot键,按一下EN键,即可烧录。烧录完毕,按EN返回运行模式。 完成! 右下角已经可选esp32开发板了 esp32首先执行的是boot.py文件。该文件是由MicroPython系统创建的。因此您无需自己创建该文件就可以在刚刚刷好固件的NodeMCU开发板根目录下找到它。我不建议MicroPython的初学者对该文件进行修改,因为boot.py文件出现问题能会导致MicroPython无法正常启动,严重的会导致系统崩溃。要修复可能只有重新刷固件才行。所以除非您很了解MicroPython,否则请不要自行修改该文件。 执行完boot.py以后,启动中的NodeMCU接下来将会执行main.py文件。如果您希望NodeMCU在每次启动后都执行一系列操作的话,可以将您的指令代码写入该文件。由于main.py文件是用户自己建立的而不是MicroPython系统建立的,因此在刚刚刷好固件的开发板根目录下是不存在该文件的。假如MicroPython在启动中找不到main.py文件,它会在系统启动时报错(如下图所示)。 所以我们新建main.py,删除boot.py,main.py作为项目的主入口文件 安装vscode 双击(VSCodeUserSetup-x64-1.79.2.exe)文件 esp32web服务器接口的搭建 解压网盘中的microdot-main.zip microdot-main\src下面有我们需要的文件 在MicroPython设备 新建目录结构 lib 存放一些库文件 microdot.py (microdot-main\src中) common

python3 setproctitle多进程重命名详解

今天由于便于管理,需要修改多进程(包括子进程)的名称,网上的资料不多,基本上没有我想要的案例,今天摸索了下才实现了我的目的,下面具体说一下。 首先,修改进程名,主要依靠一个第三方的模块:setproctitle 详情见:setproctitle · PyPI 用法很简单,基本就两个方法: setproctitle(title) Set title as the title for the current process. getproctitle() Return the current process title 我们先来一个例子,如下代码: # -*- coding: utf-8 -*- from multiprocessing import Process import time import setproctitle def task(name): print("name=",name) time.sleep(30) if __name__ == "__main__": setproctitle.setproctitle('python3 main--') start = time.time() p1 = Process(target=task,args=("safly1",),name='python3 safly1') p2 = Process(target=task, args=("safly2",),name='python3 safly2') p3 = Process(target=task, args=("safly3",),name='python3 safly3') p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print("

数据库三大范式讲解实用篇

数据库三大范式 第一范式: 第一范式(1NF)是指在关系模型中,对于添加的一个规范要求,所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合、数组、记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个域值只能是实体的一个属性或一个属性的一部分。简而言之,第一范式就是无重复的域。 第二范式 在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)。 候选码:候选键,任何能保证“唯一性”的字段都可以是候选键,例如在“用户”信息中,身份证号、验证过的手机号都是候选键, 任何候选键都可以被选作主键,如果无可用候选键,应创建ID等值不重复的字段。 第三范式: 在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖) 传递依赖:A依赖于B,B依赖于C,完整来看,A也是依赖于C的,这个依赖关系是传递过去的。 引申 关于冗余 只要是“可以不存”、“可以使用id表示”、“存了多次(非id)”的数据,却直接存储到数据库里,都可以称之为“冗余” 遵守数据库范式,设计不冗余的数据表,同时,也会把原本冗余的数据表中的数据拆分到多张表中去,导致“单一的数据表不足于表现数据”,例如当需要查看订单信息时,仅仅只是查询“订单信息表”是完全不够的,因为即使知道商品id是PO01也不知道这到底是什么商品,更不足以显示到软件的界面中去,为了查询到完整的信息,必须查询多张表,例如: select*from订单信息表join商品信息表on订单信息表.商品id=商品信息表.商品id; 如果还需要查询出用户的信息,则以上SQL语句还需要继续补充关联查询! 当表的关联越复杂,查询时需要关联的表就越多,但是,如果采取的是“冗余”的设计方案,只需要查询“订单信息表”这1张表就能查询到完整的信息。 可见,即使是“冗余”的设计方案,它也是有优点的,就是“简单!快! ” 在《阿里巴巴Java开发手册》中约定: 【推荐】库名与应用名称尽量一致。【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循: 不是频繁修改的字段不是varchar超长字段,更不能是text字段。正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存储类目名称,避免关联查询 所以,冗余不一定是缺点,适当冗余可提高查询性能,所以,数据库范式不是必须完全遵循的,应该根据实际情况来决定! 数据库范式建议: 数据库范式约定了创建数据表的规范((尽管可能不完全遵守),在实际开发中,通常还有以下建议: 如果varchar类型的字段的值的长度相对可控,推荐使用char替代,因为char的效率更高一些尽管varchar类型的理论长度可达65535,但如果可能超过5000 (部分企业可能约定为其它值),建议将其设计到另—张表中去,并与当前表关联-可能建议将字段类型改为text可能会在当前表把长字符串值进行截取,便于获取简要信息如果可行,建议使用更小的单位存储更大的数值,避免使用浮点类型,造成运算时的误差,例如价值为“18.52元”的商品,存储为“1852分” 总结: lNF:在关系模型中,对于添加的一个规范要求,所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项,简单来说就是:列不可再分2NF:在1NF的基础上,非码属性必须完全依赖于候选码,简单来说就是:非主属性不能只依赖主键的一部分3NF︰在2NF基础上,任何非主属性不依赖于其它非主属性,简单来说就是:每列数据都与主键直接相关 核心思想: 数据库范式的核心思想包括“消除冗余”,冗余的缺点在于: 不便于管理维护占用较多的存储空间 但是,适当冗余可提高查询性能 数据库范式不是必须严格遵守的 使用原则: 基本按照数据库范式来设计各数据表,但不完全遵循,并且: 查询频率高且修改频率低的较短长度的数据允许冗余,特别是关联查询如果varchar类型的字段的值的长度相对可控,推荐使用char替代,因为char的效率更高一些尽管varchar类型的理论长度可达65535,但如果可能超过5000(部分企业可能约定为其它值),建议将其设计到另一张表中去,并与当前表关联 -一可能建议将字段类型改为text可能会在当前表把长字符串值进行截取,便于获取简要信息如果可行,建议使用更小的单位存储更大的数值,避免使用浮点类型,造成运算时的误差,例如价值为“18.52元”的商品,存储为“1852分”

蓝桥杯嵌入式——RTC

蓝桥杯嵌入式——RTC 配置程序编写 配置 cubeMX 程序编写 获取时间 RTC_TimeTypeDef T; RTC_DateTypeDef D; void rtc_proc() { HAL_RTC_GetTime(&hrtc, &T, RTC_FORMAT_BIN); //日期和时间都要获取 HAL_RTC_GetDate(&hrtc, &D, RTC_FORMAT_BIN); if(second != T.Seconds) { second = T.Seconds; printf("%02d-%02d-%02d\r\n",T.Hours,T.Minutes,T.Seconds); } } 注:需要在调用HAL_RTC_GetTime()后再调用HAL_RTC_GetDate(),即使用不到日期。 闹钟中断 在闹钟不变的情况下: 如果 忽略小时,忽略分钟,不忽略秒。 一分钟中断一次 如果 忽略小时,不忽略分钟,不忽略秒。 一小时中断一次 如果 不忽略小时,不忽略分钟,不忽略秒。 一天中断一次 如每分钟中断一次: 3. 秒中断(1~59s 的中断) 定义一个包含 时、分、秒的结构体 typedef struct { uint8_t h; uint8_t m; uint8_t s; }nTime; 用到的变量 static uint8_t first_time_flag=1; //用于判断是否为第一次中断 static uint8_t sAlarm_flag=0; //闹钟标志位 RTC_AlarmTypeDef sAlarm; nTime Time; 这里我建立了新的bsp_rtc.

僵尸进程与孤儿进程,以及如何查看僵尸进程

转载来自:什么是僵尸进程与孤儿进程_张维鹏的博客-CSDN博客 1、什么是僵尸进程和孤儿进程: 在 Unix/Linux 系统中,正常情况下,子进程是通过父进程创建的,且两者的运行是相互独立的,父进程永远无法预测子进程到底什么时候结束。当一个进程调用 exit 命令结束自己的生命时,其实它并没有真正的被销毁,内核只是释放了该进程的所有资源,包括打开的文件、占用的内存等,但是留下一个称为僵尸进程的数据结构,这个结构保留了一定的信息(包括进程号 the process ID,退出状态,运行时间),这些信息直到父进程通过 wait()/waitpid() 来取时才释放。这样设计的目的主要是保证只要父进程想知道子进程结束时的状态信息,就可以得到 僵尸进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵死进程。 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被 init 进程(进程号为1)所收养,并由 init 进程对它们完成状态收集工作。 2、僵尸进程与孤儿进程的问题危害: 僵尸进程虽然不占有任何内存空间,但如果父进程不调用 wait() / waitpid() 的话,那么保留的信息就不会释放,其进程号就会一直被占用,而系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害。 孤儿进程是没有父进程的进程,孤儿进程这个重任就落到了 init 进程身上,init 进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为 init,而 init 进程会循环地 wait() 它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init 进程就会出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。 如果子进程在 exit() 之后,父进程没有来得及处理,这时用 ps 命令就能看到子进程的状态是“Z”。如果父进程能及时处理,可能用 ps 命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由 init 接管。init 将会以父进程的身份对僵尸状态的子进程进行处理。 3、如果解决僵尸进程造成的问题: (1)方案一:父进程通过 wait 和 waitpid 等函数等待子进程结束,但这会导致父进程挂起,所以这并不是一个好办法,父进程如果不能和子进程并发执行的话,那我们创建子进程的意义就没有。同时一个 wait 只能解决一个子进程,如果有多个子进程就要用到多个 wait (2)方案二:通过信号机制: 子进程退出时,向父进程发送 SIGCHILD 信号,父进程处理 SIGCHILD 信号,在信号处理函数中调用 wait 进行处理僵尸进程。 (3)方案三:fork两次:

Grid 网格响应式布局教程

一、概述 它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。 相对于display:flex 弹性布局,Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局,在某些使用场景下,会比flex布局更便捷一些。 二、基础使用 <div class="container"> <div class="item bg-color-red">1</div> <div class="item bg-color-yellow">2</div> <div class="item bg-color-green">3</div> <div class="item bg-color-red">4</div> <div class="item bg-color-yellow">5</div> <div class="item bg-color-green">6</div> <div class="item bg-color-red">7</div> <div class="item bg-color-yellow">8</div> <div class="item bg-color-green">9</div> </div> 那么我们采用网格布局的区域,称为"容器"(container)。容器内部采用网格定位的子元素,称为"项目"(item) .container { display: grid; /* 设置三列 宽度自适应 */ /* grid-template-columns: auto auto auto;*/ /* grid-template-columns: 1fr 2fr 1fr ; */ /* grid-template-columns:repeat(3, 1fr 2fr 1fr); */ /* 设置三列 宽度自适应 repeat()写法效果同上 */ grid-template-columns: repeat(3, auto); /* 设置三行 容器高度 200px */ /* grid-template-rows: 200px 200px 200px; */ /* grid-template-rows: repeat(3, 200px 200px 200px); */ grid-template-rows: repeat(3, 200px); /* 行内自动填充宽度为 200px */ /* grid-template-columns: repeat(auto-fill, 200px); */ /* 设置行列 直接的间距 */ grid-gap: 10px; } .

XML之解析(知识详解即基本使用)

XML解析 1. 了解XML解析 1.1 概念: XML解析是指将XML文件转换为程序可以处理的数据结构的过程。由于XML是一种用于描述数据结构和信息的语言,因此,通过XML解析,可以将XML文档中的数据转换为程序可以使用的对象或数据。 1.2 解析过程: XML解析包括两个主要过程:解析器(Parser)将XML文档读取到内存中并构建成树形结构,解析器会根据XML文档的规范对其进行语法和语义的验证;解析器读取完成后,解析器将把XML文档转换为程序可以使用的数据结构,这些数据结构可以便于程序对XML文档中的数据进行访问和处理。 图解: 1.3 常见的解析技术: DOM解析SAX解析XMLPull解析等 1.4 XML解析图解 2. XML解析的重要性 2.1 XML解析的主要作用: 读取和处理XML数据:XML解析器可以将XML文档读取到内存中,并将其转换为程序可以处理的数据。程序可以对这些数据进行处理,从而完成各种操作,例如数据编辑、转换、导入导出等。验证XML文件的合法性:解析器可以验证XML文档的合法性,检查XML文档是否符合XML规范和DTD/Schema定义,如果XML文档中存在错误或不可识别的元素,解析器将报告解析错误。基于XML文档结构进行操作:XML解析器将XML文档转换为一个树形结构(由元素、属性和文本等元素组成),程序可以依据这个树形结构对XML文档的结构进行操作,例如查询、模糊搜索或基于特定条件过滤等操作。解析和处理复杂的XML文档:XML是一种灵活和可扩展的数据格式,它具有嵌套和复杂的数据结构。XML解析器可以让程序轻松处理和操作这些复杂的XML文档,使得程序的开发和维护更加容易。 2.2 XML解析的作用域(使用方面): 数据分析和处理:由于XML可以存储和表示复杂的数据结构,因此XML解析器可以用于将XML数据转换为程序可以使用的内部数据结构,从而实现数据的分析和处理。网络通信:许多Web服务和REST API使用XML作为数据传输的格式,因此程序需要使用XML解析器解析和处理网络传输的XML数据,以便从中提取和处理必要的信息。数据存储和交换:XML解析器可以将XML数据转换为数据库可用的格式,或者将应用程序中的数据导出为XML文档。这样,开发人员就可以轻松地存储和交换数据,以满足与其他应用程序的数据交换需求。配置文件:许多应用程序使用XML格式的配置文件来定义系统配置和参数。 XML解析器可将配置文件读取到内存中,并使应用程序能够读取,解释和使用这些参数,以满足程序需求。 总结:总之,XML解析在现代软件开发中扮演着非常重要的角色,能够帮助程序员轻松处理和操作基于XML的数据结构。无论在何种应用场景下,简单且易于理解的XML格式仍然是开发人员最喜欢的数据格式之一。 3. XML解析的综合使用 3.1 Java中配置文件的三种配置位置及读取方式: 3.1.1 同包路径下的读取方式 图示: 读取方法: 类名.class.getResourceAsStream("配置文件名") 案例1: package com.YX.Parse; import java.io.InputStream; import java.util.Properties; /** * 读取不同路径下的配置文件 1.同包 2.根路径 3.安全路径 * * @author 86158 * */ public class Demo1 { // 打开主程序入口 public static void main(String[] args) throws Exception { // 1.

个人使用ChatGLM-6B遇到的部分问题汇总

本文目录 写在最前个人windows电脑部署时遇到KeyError: 'chatglm'问题原因:transformers版本有问题解决方法 OSError/AssertionError/Failed to load cpm_kernels问题原因:配置内容没有修改、依赖包不完整解决方法 想要运行web_demo2.py时遇到No matching distribution found for streamlit-chat问题原因:组件必须要在python>3.8的环境才能运行!!!! 写在最前 项目的github网址(https://github.com/THUDM/ChatGLM-6B)中有解决问题专用的Issues模块 建议遇到问题先将部分报错写在这里进行查询,大概率能找到问题的解决方法 本文章只用于记录个人在使用过程中遇到的问题,供以后回忆之用。 个人windows电脑部署时遇到 以下都是在运行cli_demo.py遇到 KeyError: ‘chatglm’ # 出现异常描述 (ai) Q:\Python\project\ChatGLM\ChatGLM-6B-main>python cli_demo.py Traceback (most recent call last): File "cli_demo.py", line 7, in <module> tokenizer = AutoTokenizer.from_pretrained("THUDM/ChatGLM-6B", trust_remote_code=True) File "Q:\IDE\Python\vitrual_enviroment\ai\lib\site-packages\transformers\models\auto\tokenization_auto.py", line 362, in from_pretrained config = AutoConfig.from_pretrained(pretrained_model_name_or_path, **kwargs) File "Q:\IDE\Python\vitrual_enviroment\ai\lib\site-packages\transformers\models\auto\configuration_auto.py", line 371, in from_pretrained config_class = CONFIG_MAPPING[config_dict["model_type"]] KeyError: 'chatglm' 问题原因:transformers版本有问题 推荐版本是4.27.1 ,但是好像不太行 解决方法 在出现这个问题之前,我先遇到了一个问题提示找不到模型,然后我查了以后有人说是因为transformer版本太低,然后我就把版本提升到4.3以上的一个版本,然后就出现了上所示问题重新去github上找人答疑时,有人说需要版本得是transformers 4.28.1,我就死马当活马医重新pip install,发现解决了,进入下一个问题 OSError/AssertionError/Failed to load cpm_kernels (ai) Q:\Python\project\ChatGLM\ChatGLM-6B-main>python cli_demo.

windows10企业版安装西门子博途V15---02安装软件

1、创建目录,将文件01.TIA_Portal_STEP_7_Pro_WINCC_Pro_V15解压到这个位置 2、点击这个.bat,让电脑不需要重启 3、进入解压的V15目录,管理员运行这个setup.exe文件 安装过程漫长,而且可能要重启,当出现要重启的时候,选择不要重启,而是重新执行前面的2.3步骤。如图 这里根据本尊的实际经验,会有3次重启的出现,直到第4次安装才会出现桌面的图标。这是一个坑,真正的坑,网上很多文章没有写到,还以为是安装成功,而不断重启,其实,只要桌面上没有出现5个图标,就需要重新安装,明白这个吗?每次运行那个setup.exe文件,都必须先点击西门子解除重启提示批处理-2018.bat这个文件。这就是技巧。看这个图,这是第4次重新安装才真正开始在桌面上有图标,这才是希望,只要没有出现图标,你就重新 安装,这就是造化的过程。 直到最后出现成功才重启电脑 4、开始授权 打开 这样做的目的是授权。之后重启电脑

1456. 定长子串中元音的最大数目(原始暴力匹配法以及滑动窗口法)

1.暴力求解 class Solution { public: int maxVowels(string s, int k) { int maxVowels = 0; for(int i = 0;i<s.size();i++){ if(i+k > s.size()) return maxVowels; string cur_str = s.substr(i,k); maxVowels = max(countVowel(cur_str),maxVowels); } return maxVowels; } int countVowel(string str){ int vowel_num = 0; for(int i = 0;i < str.size();i++){ switch(str[i]){ case 'a': case 'e': case 'i': case 'o': case 'u': vowel_num +=1; } } return vowel_num; } }; 最后求解后时间复杂度为: O ( k ⋅ n ) O(k·n) O(k⋅n)

【运筹优化】Java 调用 Gurobi 求解 LP 问题代码示例

文章目录 问题代码求解结果 问题 代码 import gurobi.*; /** * @Author:WSKH * @ClassName:TestGurobi * @ClassType: * @Description: * @Date:2022/6/5/11:38 * @Email:1187560563@qq.com * @Blog:https://blog.csdn.net/weixin_51545953?type=blog */ public class TestGurobi{ public static void main(String[] args) { try { // 创建环境 GRBEnv grbEnv = new GRBEnv("grbEnv"); // 创建模型 GRBModel grbModel = new GRBModel(grbEnv); // 声明CONTINUOUS连续变量 GRBVar x1 = grbModel.addVar(-10, 50, -10, GRB.CONTINUOUS, "x1"); GRBVar x2 = grbModel.addVar(0, Double.MAX_VALUE, 0, GRB.CONTINUOUS, "x2"); GRBVar x3 = grbModel.addVar(5, 5, 5, GRB.

【运筹优化】牛顿法详解 + Matlab代码实现

文章目录 1 牛顿法简介2 牛顿法原理3 牛顿法推导4 Matlab代码实现5 低版本Matlab报错 1 牛顿法简介 牛顿迭代法(Newton’s method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。 多数方程不存在求根公式,因此求精确根非常困难,甚至不可解,从而寻找方程的近似根就显得特别重要。方法使用函数 f ( x ) f(x) f(x) 的泰勒级数的前面几项来寻找方程 f ( x ) = 0 f(x)=0 f(x)=0 的根。牛顿迭代法是求方程根的重要方法之一,其最大优点是在方程 f ( x ) = 0 f(x)=0 f(x)=0 的单根附近具有平方收敛,而且该法还可以用来求方程的重根、复根,此时线性收敛,但是可通过一些方法变成超线 性收㪉。另外该方法广泛用于计算机编程中。 2 牛顿法原理 设 r r r 是 f ( x ) = 0 f(x)=0 f(x)=0 的根,选取 x 0 x_{0} x0​ 作为 r r r 的初始近似值,过点 ( x 0 , f ( x 0 ) ) \left(x_{0}, f\left(x_{0}\right)\right) (x0​,f(x0​)) 做曲线 y = f ( x ) y=f(x) y=f(x) 的切线 L L L ,