java类加载器获得路径中的中文问题解决 问题来源解决方案 问题来源 日常开发中,有时需要获取一些文件的路径,但由于业务环境的需要存在中文路径的情形,因此在开发中我们经常使用类加载器或类类型的 getResource 方法获取路径时的中文路径就会变体,例如:空格会转换为“%20”等情形,故获取真实的路径就是我们所需要的。
解决方案 方案1-去除URL中转换符在URL解码 String packagePath = url.getPath().replaceAll("%20"," "); //解决路径中含有空格的情况 packagePath = java.net.URLDecoder.decode(packagePath, "utf-8"); //解决路径包含中文的情况 方案2-url.toURI().getPath() String packagePath = url.toURI().getPath(); //完美解决 -但有异常需要处理
具体参考:在线Hex和Base64互转工具
项目管理后台采用Vue.js 架构,开发完毕后设计到打包上传到服务器发布。
发布成功后,总结出主要要决绝两个主要问题:
1.打包前,环境设置
2.上传到服务器,直接放在Tomcat中出现跨域访问问题。
此次项目实际处理方法为:
一、打包
有人说需要再config文件夹中index.js中 所以
assetsPublicPath: '/', 改为
assetsPublicPath: './',
其实这是不需要的,因为生产环境打包时,这里根本不会包含进入,这里只用于本地开发环境,vue.js本地产生的服务用于跨域转发,解决跨域访问产生的问题。
module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/zpin/*':{ // 本地开发环境设置 // target:'http://localhost:8081', // 本地开发环境连接服务器生产环境 target:'http://www.yi********.com:8081', changeOrigin:true, pathRewrite:{ '^/zpin': '/zpin' } } }, 包括在build 文件中的 uils.js 中 添加 if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, // 这里是不需要添加的,除非你对默认目录做了大的修改 // publicPath:'../../', fallback: 'vue-style-loader' }) } 如果你在最后和跨域问题一并解决后,其实只需要更改一处,就是修改axios库的baseurl地址即可,我的设置文件是这样的 let base = ''//本地测试环境 let base = 'http://besu.
目录 Altium Designer(AD)软件使用记录05-PCB叠层设计一、正片层和负片层的介绍1、正片层(Signal)2、负片层(Plane)3、内电层的分割实现 二、正片层和负片层的内缩设计1、负片设置内缩20H原则2、正片铺铜设置内缩1、设置规则2、重新铺铜 三、AD的层叠设计四、叠层设计需要注意的问题1、总的来说叠层设计主要要遵从两个规矩2、下面列出从两层板到八层板的叠层来进行示例讲解1、单面PCB板和双面PCB板的叠层2、四层板的叠层3、六层板的叠层4、八层板的叠层 Altium Designer(AD)软件使用记录05-PCB叠层设计 一、正片层和负片层的介绍 1、正片层(Signal) 正片就是平常用在走线的信号层,既走线的地方是铜线,用Polygon Pour进行大块敷铜填充。
2、负片层(Plane) 负片正好相反,既默认敷铜,走线的地方是分割线,也就是生成一个负片之后整一层就已经被敷铜了,要做的事情就是分割敷铜,再设置分割后的敷铜的网络。
3、内电层的分割实现 AD中直接用Line,快捷键PL,来分割,分割线不宜太细,用15mil及以上。
要分割敷铜时,只要用Line画一个封闭的多边形框,在双击框内敷铜设置网络即可。
正负片都可以用于内电层,正片通过走线和敷铜也可以实现。
负片的好处在于默认大块敷铜填充,在添加过孔,改变敷铜大小等等操作都不需要重Rebuild,这样省去了PROTEL重新敷铜计算的时间。中间层用于电源层和GND层时候,层面上大多是大块敷铜,这样用负片的优势就很明显。
建议与提示:建议信号层采取“正片”的方式处理,电源层和GND层采取“负片”的方式处理,可以很大程度上减小文件数据量的大小和提高设计的速度。
二、正片层和负片层的内缩设计 1、负片设置内缩 设计–>层叠管理器(快捷键DK),选中需要设置内缩的负片层
按F11弹出属性面板,找到Pullback distance栏填入需要内缩的值。
注:默认是叠层对称的,当设置第二层负片内缩值时,第三层也会同步修改为相同的值;若不需要同步修改(一层为GND,一层为PWR时),取消勾选Stack Symmetry即可设置不同的内缩值。
20H原则 20H原则是指电源层相对地层内缩20H的距离,H表示电源层与地层的距离。当然也是为抑制边缘辐射效应。在板的边缘会向外辐射电磁干扰。将电源层内缩,使得电场只在接地层的范围内传导,有效的提高了emc。若内缩20H则可以将70%的电场限制在接地边沿内;内缩100H则可以将98%的电场限制在内。
我们要求地平面大于电源或信号层,这样有利于防止对外辐射干扰和屏蔽外界对自身的干扰,一般情况下在pcb设计的时候把电源层比地层内缩1mm基本上就可以满足20H的原则。
我们内缩的距离就是我们之前说的“20H”的距离,这个H指的是电源层与地层之间的介质厚度,“20H规则”的采用是指要确保电源平面的边缘要比0V平面边缘至少缩入相当于两个平面间层距的20倍。
但是由于叠层的设计,在通常的一些PCB板上,严格满足20H的话,无法进行PCB布线了,所以一般的处理方式是电源GND 相对GND 内缩1MM,这样我们板子的性能也得到一定的保障。
我们也需要注意一下,我们的20H原则是在一定的前提下才可以有明显的效果。
1、电源平面要处在PCB内部,并且与他相邻的上下两个层都为0V平面,这两个0V平面向外延伸的距离至少要相当于他们各自与电源平面间层距的20倍。
2、PCB的总层数要大于或等于8层。
最后,负片地内缩20mil,负片电源内缩60mil。
然后在1mm的内缩带打上屏蔽地过孔,150mil一个。
2、正片铺铜设置内缩 1、设置规则 PCB设计界面 找到板框层,复制板框层并粘贴,转换为keep-out-layer禁止布线层 工具–转换–转换选择元素到keepout。建立一个和板框层一致的禁止布线层。
D-R 找到Clearance 右键选择新建规则,如下图所示:设置禁止布线层与铺铜的最小间距(内缩值)。
2、重新铺铜 PCB设计界面选中铺铜 T->G->R 重铺选中铺铜。
到此,就完成了。
三、AD的层叠设计 设计–>层叠管理器(快捷键DK)
1、可以添加层,Signal是正片,plane是负片
2、层的名字可以自己修改,一般设置为便于识别的名字
3、根据层叠结构设置板厚
4、为了满足设计的“20H”原则,可以设置负片层的内缩量
四、叠层设计需要注意的问题 1、总的来说叠层设计主要要遵从两个规矩 1、每个走线层都必须有一个邻近的参考层(电源或地层);
2、邻近的主电源层和地层要保持最小间距,以提供较大的耦合电容。
2、下面列出从两层板到八层板的叠层来进行示例讲解 1、单面PCB板和双面PCB板的叠层 对于两层板来说,由于板层数量少,已经不存在叠层的问题。控制EMI辐射主要从布线和布局来考虑;
单层板和双层板的电磁兼容问题越来越突出。造成这种现象的主要原因就是因是信号回路面积过大,不仅产生了较强的电磁辐射,而且使电路对外界干扰敏感。要改善线路的电磁兼容性,最简单的方法是减小关键信号的回路面积。
关键信号:从电磁兼容的角度考虑,关键信号主要指产生较强辐射的信号和对外界敏感的信号。能够产生较强辐射的信号一般是周期性信号,如时钟或地址的低位信号。对干扰敏感的信号是指那些电平较低的模拟信号。
单、双层板通常使用在低于10KHz的低频模拟设计中:
1)在同一层的电源走线以辐射状走线,并最小化线的长度总和;
2)走电源、地线时,相互靠近;在关键信号线边上布一条地线,这条地线应尽量靠近信号线。这样就形成了较小的回路面积,减小差模辐射对外界干扰的敏感度。当信号线的旁边加一条地线后,就形成了一个面积最小的回路,信号电流肯定会取道这个回路,而不是其它地线路径。
Kafka 入门(二) 接着Kafka 入门(一),接着就要在应用中使用。
Spring6-Kafka 生产者,消费者分别使用不同的应用
生产者 引入依赖 <dependencies> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>3.0.4</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.4.5</version> </dependency> </dependencies> application.properties spring.kafka.bootstrap-servers=192.168.79.177:9092 logback.xml <?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" status="WARN"> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息--> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%date %level %logger %msg%n</pattern> </layout> </appender> <logger name="pr.iceworld.fernando.spring6.kafka.producer" level="INFO" additivity="false"> <appender-ref ref="CONSOLE"/> </logger> <logger name="org.springframework.kafka" level="WARN" additivity="false"> <appender-ref ref="CONSOLE"/> </logger> <logger name="org.apache.kafka" level="WARN" additivity="
1. GB/T28181规范概述 GB/T28181-2011 《安全防范视频监控联网系统信息传输、交换、控制技术要求》是由公安部科技信息化局提出,由全国安全防范报警系统标准化技术委员会(SAC/TC100)归口,公安部一所等多家单位共同起草的一部国家标准。
该标准规定了城市监控报警联网系统中信息传输、交换、控制的互联结构、通信协议结构,传输、交换、控制的基本要求和安全性要求,以及控制、传输流程和协议接口等技术要求。简言之,就是规定了视频监控系统中各种设备、系统、角色之间的互通互联的关系和连接规范。
对于大多数使用场景,GB28181解决的一个主要问题就是如何远程、跨区域、跨级别的访问网络中的监控设备(包括IPC、NVR等)。在没有GB28181协议之前,想要远程访问某个局域网中的监控摄像头相当麻烦,通常要进行动态IP映射、端口映射、动态域名绑定等操作,在稳定性和易用性方面都不理想。虽然之前有成熟的ONVIF协议(ONVIF创建了一个视频监控和其他物理安全领域的IP产品如何进行相互通信的标准),但在跨网络和跨域访问方面,ONVIF缺少足够的灵活性。
2.GB28181平台的架构 一个完整的GB28181平台,通常由管理平台、信令服务器、流媒体服务器、监控设备(IPC、NVR)、管理终端等几部分组成。
信令服务器是与网络中监控设备与管理终端之间进行通信的代理,也是各级系统之间的代理,信令服务器要有固定的IP地址或域名,如果要面向公网服务,还需要有公网IP。由于是监控设备主动向信令服务器注册,所以监控设备不需要有固定的IP。监控设备注册到信令服务器上之后,管理者通过向信令服务器发送指令来管理监控设备。
流媒体服务器是视频传输的代理,该系统接受监控设备发送的视频流,向视频调取方转发视频。视频调取方可以是监控监控视频的用户、第三方业务系统或者是上下级平台。协议规定监控设备通过rtp协议向流媒体服务器发送视频流,但是没有约定流媒体服务器向其他方转发视频的协议,因此在视频转发时具有更大的灵活性,可以根据需要采用合适的协议转发视频。
架构图
管理平台是具有一定业务特色的业务平台,通常实现对监控设备、信令服务器、流媒体服务器、用户等进行管理。比如各种管理中心、指挥中心、智慧平台等。
数据流图
3. 主流的GB28181平台 一、华为IVS平台 华为IVS平台除了支持华为品牌的监控摄像机,同样支持其他符合GB28181标准的监控设备接入。
参考地址: https://support.huawei.com/enterprise/zh/doc/EDOC1100269456/156879c2
前提条件
设备可以通过专网或开放网络连接到IVS,设备与平台之间的网络是连通的;设备使用GB/T 28181协议与IVS平台对接时,需要获取平台侧添加摄像机时的参数,这个与其他平台是一致的 设备上的配置与其他终端设备一样,主要参数是一致的:
二、NTV GBS NTV GBS是一个功能完善的、敏捷的、产品化的GB28181平台,支持标准的监控设备的接入和管理,可以接入监控摄像头和硬盘录像机,视频调阅和设备控制操作都很顺畅,界面设计也相当不错。
前提条件
设备可以通过专网或开放网络连接到NTV GBS,设备与平台之间的网络是连通的;设备使用GB/T 28181协议与NTV GBS平台对接时,需要在平台上获取平台侧添加摄像机时的参数,这个与其他平台是一致的 平台端配置
登录NTV GBS平台后,首先通过点击左侧设备列表下方的“添加设备”按钮添加新设备。添加新设备只需要输入设备名称即可,其他信息由平台自动完善。
设备添加完毕后,右键点击设备,选择“配置信息”会获取详细的设备配置信息,使用该信息到设备上对照填写就可以完成设备端配置。
设备端配置
将上一步拿到的配置信息,到设备端进行配置,大部分支持GB28181的设备配置界面大同小异,我们以海康的IPC为例,配置界面如下:
配置完成后点击保存按钮。通常会在1分钟内连接到平台上,在平台就可以查看实时视频和对设备进行控制了。
整体运行效果:
三、开源平台WVP WVP(WEB VIDEO PLATFORM)是一个基于GB28181-2016标准实现的开箱即用的网络视频平台,负责实现核心信令与设备管理后台部分,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联,支持将不带国标功能的摄像机/直播流/直播推流转发到其他国标平台。
参考地址:https://github.com/648540858/wvp-GB28181-pro
该平台基本上实现了设备的接入和管理功能,是一个开源项目,通常懂Linux、Java技术的工程师就可以完成安装部署。
存在的一些小瑕疵是代码不是很好懂,作者也没有提供架构设计和更详细的说明文档,如果要基于此平台进行改进则需要付出较大工作,界面也相对粗糙一些。
MNIST手写数字数据库的训练集为60,000个示例,而测试集为10,000个示例。
一共4个文件,训练集、训练集标签、测试集、测试集标签,这些数据直接可以用mnist = tf.keras.datasets.mnist导入
1.调用神经网络API代码如下:
import tensorflow as tf mnist = tf.keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() # 对数据进行归一化 x_train, x_test = x_train/225.0, x_test/255.0 # 调用API搭建神经网络 model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(28, 28)), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dropout(0.25), tf.keras.layers.Dense(10, activation='softmax') ]) # 设置损失函数和梯度下降 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 开始训练模型 model.fit(x_train, y_train, epochs=5) # 查看准确率 model.evaluate(x_test, y_test, verbose=2) 2.手写简单神经网络代码如下:
import tensorflow as tf import numpy as np # 获取数据 from tensorflow.keras import datasets (x_train, y_train),(x_test, y_test) = datasets.
文章目录 摘要问题分析数据层面方法层面 本文方法整体框架TimesBlock1D to 2D选择最显著频率维度转换 捕捉2D特征自适应聚合 实验结果短期预测长期预测imputation分类异常检测 文章获取: https://openreview.net/pdf?id=ju_Uqw384Oq 代码地址: https://github.com/thuml/Time-Series-Library 摘要 时间序列分析在天气预报、异常检测、动作识别等领域有着广泛的应用。时间变化建模是大量分析任务中常见的关键问题。以前的方法试图直接从1D时间序列中完成这一点,由于复杂的时间模式,这是极具挑战性的。通过对时间序列多周期性的观察,我们将复杂的时间变化分解为多个周期内变化和周期间变化。为了解决一维时间序列在表示能力上的局限性,我们将一维时间序列转换为一组基于多个周期的二维张量,从而将时间变化分析扩展到二维空间。这种变换可以将周期内变化和周期间变化分别嵌入到二维张量的列和行中,使得二维变化可以很容易地用二维核来建模。从技术上讲,我们提出了以时间块作为时间序列分析的任务通用骨干的时间网。TimesBlock可以自适应地发现多周期性,并通过参数高效的初始块从转换后的二维张量中提取复杂的时间变化。我们提出的TimesNet在五个主流时间序列分析任务中达到了一致的最先进水平,包括短期和长期预测、imputation、分类和异常检测。
问题分析 数据层面 数据特征上,不同于自然语言、视频等序列数据,时间序列中单个时刻仅保存了一些标量,其关键信息更多地被蕴含在时序变化中
方法层面 近年来,应用于时间序列分析的方法大致可以分为基于卷积的方法和基于transformer的方法
基于卷积的方法主要关注捕捉临近时刻之间的变化,在长期依赖上建模能力不足。
基于transformer的方法虽然在建模长期依赖上具有天然优势,但是由于现实世界的时序变化极其复杂,仅仅依靠离散时间点之间的注意力难以挖掘出可靠的时序依赖。
本文方法 TimeNet从周期角度出发,从多种不同粒度提取数据在周期内以及周期间的变化
将数据进行FFT快速傅里叶变换,找出幅值最高的k个频率,并按照不同频率对数据进行多组采样将同一频率采样的多组数据拼在一起,将数据从一个一维数据转换为多个二维数据使用具有二维核的TimesBlock(基于Inception)对每一组二维数据进行特征提取将k组二维数据的特征使用自适应聚合进行拼接,得到时间序列的整体特征以残差形式多次叠加步骤1-4(TImesBlock) 整体框架 基于时间序列的多周期性,提出了具有模块化架构的时间网,以捕获来自不同周期的时间模式
对于每个周期,为了捕获相应的周期内和周期间变化,在TImesNet中设计了一个TimesBlock,它可以将1D时间序列转换为2D空间,并通过共享参数的InceptionBlock同时对两种类型的变化进行建模
TimesBlock TimesNet以残差模式组织TimesBlock,可以在二维空间中通过参数高效的Inception Block捕获k个不同的重塑张量的各种时间二维变化,并根据归一化的振幅值进行融合,除第一层外每一个TimesBlock中数据的变化都是1D->2D->1D
对于第1层,使用嵌入层将原始数据投影到一维深度特征空间
对于第l个TimesBlock,整个过程包括两个连续的部分:捕获时态2d变化和自适应聚合来自不同时期的表示
每一个TimesBlock都需要进行FFT变换,转为2D提取特征,再自适应聚合为1D
1D to 2D 每个时间点与相邻区域同时存在两种时间变化类型,即周期内变化和周期间变化。然而,原始的时间序列一维结构只能表现相邻时间点之间的变化
时间变化的二维结构,它可以明确地表示周期内和周期间的变化,从而在表示能力上更有优势,有利于后续的表示学习
选择最显著频率 有C个长度为T的时间序列,原始1D数据为X1D。为了表示周期间的变化,首先通过快速傅立叶变换(FFT)在频域对时间序列进行如下分析,发现数据周期
FFT(·)和Amp(·)表示FFT和振幅值的计算。A∈RT表示每个频率的计算振幅,由Avg(·)从C维取平均
考虑到频域的稀疏性,避免无意义高频带来的噪声,我们只选取前k个振幅值,得到了非归一化振幅{Af1,···,Afk}的最显著频率{f1,···,fk},其中k为超参数。这些选定的频率也对应k个周期长度{p1,···,pk}
由于频域的共轭性,只考虑{1,···,[t/2]}范围内的频率
维度转换 基于所选频率{f1 , · · · , fk}和同期长度{p1 , · · · , pk},可以将一个一维时间序列reshape多个二维张量
实现,若无法恰好根据频率完成采样,则对时间序列填充0到fi*pi长度
二维张量的列、行分别表示pi(长度)和fi(频率),对应周期长度pi下的周期内变化和周期间变化
基于所选择的频率和估计的周期,我们得到了一组二维张量{X12D,···,Xk2D},它表示了不同周期推导出的k个不同的时域二维变化
二维张量带来了两种类型的位置,即相邻时间点(列,周期内变化)和相邻周期(行,周期间变化)之间的位置。因此,二维核可以很容易地处理时序二维变化
捕捉2D特征 使用参数高效InceptionBlock对2D特征进行捕捉
首先获取一个2D数据然后通过FFT转换为多个2D数据转换后,我们通过一个共享参数的inceptionBlock处理2D张量,即inception(·),使得模型大小对超参数k的选择不变然后我们将学习到的二维表示转换回1D空间进行聚合,其中我们使用Trunc(·)将长度为pi × fi的填充级数截断为原始长度T 自适应聚合 作用:融合k个不同的1D表示
振幅A可以反映所选频率和周期的相对重要性,从而对应于每个转换的2D张量的重要性,因此基于振幅聚合1D表示
实验结果 为了验证TimesNet的通用性,对5个主流分析任务进行了广泛的实验,包括短期和长期预测、imputation、分类和异常检测。
文章目录 前言一、下载docker静态二进制存档二、将解压完的二进制文件移到可执行文件目录下三、配置docker.service四、启动dockerd服务五、在有网络的环境生成Oracle11g镜像并导入5.1下载镜像Oracle11g镜像5.2将镜像打包5.3将镜像导入 六、docker安装oracle11g6.1启动镜像6.2宿主机创建文件夹6.3拷贝数据库文件至宿主机6.4停止和删除容器6.5启动docker容器(映射数据文件)6.6执行并完成基础设置6.6.1 进入容器6.6.2加载环境变量6.6.3登录6.6.4修改默认用户密码6.6.5创建用户并指定表空间,授权 6.7 修改SID6.7.1关闭数据库6.7.2修改环境变量 总结 前言 docker是一个用Go语言实现的开源项目,可以让我们方便的创建和使用容器,docker将程序以及程序所有的依赖都打包到docker container,这样你的程序可以在任何环境都会有一致的表现,这里程序运行的依赖也就是容器就好比集装箱,容器所处的操作系统环境就好比货船或港口,程序的表现只和集装箱有关系(容器),和集装箱放在哪个货船或者哪个港口(操作系统)没有关系。
一、下载docker静态二进制存档 要根据硬件平台下载以免造成不兼容
https://download.docker.com/
根据自己的需求安装对应的版本(我这里选择的是docker-20.10.7)
https://download.docker.com/linux/static/stable/x86_64/docker-20.10.7.tgz
将下载好的的包上传到对应服务器
并解压 tar -zxvf docker-20.10.7.tgz
解压完的文件为docker
[root@v-ct-jy-czzp-app-160 opt]# tar -zxvf docker-20.10.7.tgz 二、将解压完的二进制文件移到可执行文件目录下 [root@v-ct-jy-czzp-app-160 opt]# mv docker/* /usr/bin/ 三、配置docker.service [root@v-ct-jy-czzp-app-160 opt]# vim /usr/lib/systemd/system/docker.service 将以下内容填入
[Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network-online.target firewalld.service Wants=network-online.target [Service] Type=notify ExecStart=/usr/bin/dockerd ExecReload=/bin/kill -s HUP $MAINPID LimitNOFILE=infinity LimitNPROC=infinity TimeoutStartSec=0 Delegate=yes KillMode=process Restart=on-failure StartLimitBurst=3 StartLimitInterval=60s [Install] WantedBy=multi-user.target 四、启动dockerd服务 [root@v-ct-jy-czzp-app-160 opt]# systemctl daemon-reload [root@v-ct-jy-czzp-app-160 opt]# systemctl start docker.
在Vue.js开发中,组件编写时添加和编辑功能页面布局一直,区别在于编辑时需要数据还原填充。
在面向对象思想里只需要编辑组件继承添加组件即可,那么Vue中怎么操作呢。
添加页面
<template> <el-dialog :title="titleType" :visible.sync="dialog" center :close-on-click-modal="false" :before-close="handleClose" :destroy-on-close="true" @close="vueclosed" @open="openvue" width="60%" > <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form-item label="职位标题" prop="jobTitle"> <el-input v-model="ruleForm.jobTitle" placeholder="请填写客户名称" clearable > </el-input> </el-form-item> </el-form> </el-dialog> </template> export default { name: 'LLAddJob' } 编辑页面
<script> import LLAddJob from './LLAddJob' export default { name: 'LLEditJob', extends: LLAddJob } </script> 用 extends 继承即可
但是这样有一个缺陷,就是编辑组件不能在页面上添加任何控件,否则会对父组件进行重写覆盖,
如果子组件的压面控件多余或者有不同于父组件的地方,怎么办呢?只能在父组件中添加数据字段,在页面显示的时候加以判断,进行不同的布局显示。这样做显然是不合理的,那要怎么做呢?
对,用到了Vue.的插槽功能。具体如下:
组件A
<template> <el-dialog :title="titleType" :visible.sync="dialog" center :close-on-click-modal="false" :before-close="
虽然很多时候后端会把分页,搜索,排序都做好,但是有些返回数据并不多的页面,或者其他原因不能后端分页的通常会前端处理,而前端分页一般会涉及:表格数据的搜索,表格分页,排序,有些需要加一列序号。实现效果如下:
目录
表格数据
表格分页
表格序号
前端排序
搜索
表格数据 这里以this.showData来存放表格的数据,
showData: [], 表格分页 我们需要引用一下el-pagination组件,因为就几个页面是前端分页,所以我是没有封装的
<div class="block"> <el-pagination :total="showData.length"//因为是前端分页,所以,showData是获取的表格所有数据 :current-page="query.page" :page-size="query.page_size" :page-sizes="[5, 10, 20, 50, 100]" layout=" total, sizes, prev, pager, next" background @current-change="handleCurrentChange"//页面跳转 @size-change="handleSizeChange"//选择pageSize ></el-pagination> </div> query: { page: 1, page_size: 10 }, 分页有两个常用方法,跳转页面与改变页数,如下:
handleSizeChange(val) { this.query.page = 1 this.query.page_size = val }, handleCurrentChange(val) { this.query.page = val }, 表格序号 给表格加序号,如下:
加序号需要和分页组件互动,这里先在表格里面添加“序号”列,因为是vue3 ,所以用template,加一个插槽,方法为getIndex(scope.$index),
<el-table size="medium" style="width: 100%" empty-text="暂无数据" :data="showData.slice((query.page - 1) * query.
因为Vue项目发布在Tomcat中出现跨域为,所以需要Nginx进行反向代理,所以特此在云服务器中安装Nginx,本文章记录安装过程及解决安装过程中的错误处理。
一、Nginx 安装
登录服务器后,执行命令
yum info gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel 检查安装需要的依赖是否安装。
如果没安装,也不怕,再安装中根据出现错误提示进行解决,继续往下操作:
1.新建Nginx安装目录
cd /usr/local mkdir nginx cd /usr/local/nginx 2.下载Nginx的安装包 下载 wget http://nginx.org/download/nginx-1.20.0.tar.gz 解压 tar -zxvf nginx-1.20.0.tar.gz 进入安装目录 cd /usr/local/nginx/nginx-1.20.0 进入之后如图
3.安装
执行./configure 命令就可以默认安装,如果我们需要的一些例如ssl https等模块,
这里我是用的命令
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-poll_module 输入make命令开始安装,如果出现错误提示,比如pcre,执行命令安装pcre
yum -y install pcre 再次make安装,如果出现
执行命令安装
yum -y install openssl openssl-devel 安装gd-devel
yum -y install gd-devel 打印出如下信息就可以下一步安装操作了
执行命令make install 安装即可 ,make命令是编译 make install 是安装,安装很快,完成之后要从当前的nginx-1.20.0 目录中退出来,cd .
1. 在mac上安装brew brew 是 Mac 下的一个包管理工具,没有安装brew ( 检测用 brew -v ),则执行下面的命令安装
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 2. 安装nodejs 使用brew安装nodejs ( 检测用 node -v )
brew install nodejs 也可以使用二进制安装,下载地址:
http://nodejs.org/en/download/
获取nodejs模块安装目录访问权限
sudo chmod -R 777 /usr/local/lib/node_modules/ npm ( 检测用 npm -v ) 是随同nodejs一起安装的包管理工具。npm用国外的服务器,速度比较慢,淘宝提供了一个国内的cnpm镜像,速度较快,淘宝镜像与官方同步频率目前为 10分钟一次。cnpm用法和npm相同。
安装淘宝镜像:
npm install -g cnpm --registry=https://registry.npm.taobao.org 3. 安装webpack npm install webpack -g 4. 安装vue 2.x 版本
npm install vue-cli -g 3.x 版本
npm install -g @vue/cli 检查安装是否成功 vue --version # 输出版本号说明安装成功 5.
jquery animate()方法 动画详解(超简单易懂)_坚毅的小解同志的博客-CSDN博客
// animate():第一个参数:{width:200} 运动的值和属性
// 第二个-时间:默认400ms{},1000
//第三个-运动形式-两种:1.默认:swing(慢快慢) 2.linear(匀速)
//第四个-回调函数
//$(this).animate({width:"300px",height:"300px"},2000,'linear',function(){alert(123)});
//stop():默认阻止当前运动,不阻止所有,stop(true) 阻止后续所有运动,stop(true,true) 当前运动立马完成 = finish()立即完成运动。
stop(true,true) 停止到最终的目标点 finish() 立即完成运动。
运动前加stop()可以清除运动队列(不总是重复)。(鼠标移入移除 mouseover、out)
$(this).stop().animate({width:'200px'},1000) //针对的是同一个元素上面的效果
会用:
//动画延迟 .leftToRight{ left:0; } $('.leftToRight').delay(800).animate({left:100px},"solw"); animated方法中没有封装transform属性 解决方案: (1)css方法 $($sub).animate({},5000,function(){ $(this).css({'transform':'translateX(300px)'}); }) 在动画函数的回调函数里执行。时间和效果就没了意义,毕竟函数是在动画完成之后才有调用 (2)addClass方法 可以通过addClass()方法来代替此动作: 比如想旋转一个icon 在css中加入一个class Css代码 .add_transform{ transform:rotate(180deg); -ms-transform:rotate(180deg);/* IE9 */ -moz-transform:rotate(180deg);/* Firefox */ -webkit-transform:rotate(180deg);/* Safari和Chrome */ -o-transform:rotate(180deg);/* Opera */ transition:all 0.5s ease-in-out; -moz-transition:all 0.5s ease-in-out;/*Firefox 4 */ -webkit-transition:all 0.5s ease-in-out;/* Safari和Chrome */ -o-transition:all 0.
Spring Cloud OpenFeign定义的客户端调用远程服务时,默认的解码器只能按照定义的方法返回类型对接口的返回结果进行强制转换,没办法实现一些自定义的逻辑,比如将统一返回的Result类重新拆开,仅返回对应的业务对象,或者对特定的响应码进行处理等等。
public class FeignResultDecoder implements Decoder { @Override public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException { if (response.body() == null) { throw new DecodeException(response.status(), "没有返回有效的数据", response.request()); } String bodyStr = Util.toString(response.body().asReader(Util.UTF_8)); if(StringUtils.isNotEmpty(bodyStr)){ //对结果进行转换 Result result = FeignResultDecoder.json2obj(bodyStr, type); 可以处理成自己需要返回的类 return result; } return null; } public static <T> T json2obj(String jsonStr, Type targetType) { try { JavaType javaType = TypeFactory.defaultInstance().constructType(targetType); return new ObjectMapper().readValue(jsonStr, javaType); } catch (IOException e) { throw new IllegalArgumentException("
目录 python 提取csv内容脚本 python 提取csv内容脚本 提取csv的内容脚本,这里只是提取了单个csv文件的内容,也没有写入新的文件,也没有把数据处理成json,临时模版,比较简陋,方便自己后面改动,记录下
#!/usr/bin/python3 import csv iplist=[] def ReadCsvFileFirst(iplist): with open('./test.csv','r',encoding='utf-8-sig') as f: reader = csv.reader(f) for row in reader: # 打印主机Ip for hostip in row[0:1]: if hostip == "主机名": continue else: ListAdd(iplist,hostip) # print(hostip,end="\t") return iplist def ListAdd(iplist,ip): iplist.append(ip) return iplist def ChangeListoSet(iplist): setlist=list(set(iplist)) return setlist def GetInfoByIp(): with open('./test.csv','r',encoding='utf-8-sig') as f: line = csv.reader(f) for row in line: for ip in FixIpList(iplist): if ip in row[0:1]: # print (str(row[5:6]) == str('renjianhua')) # name1 = str((','.
路漫漫其修远兮,吾将上下而求索
文章目录 目录
一、操作系统
操作系统的作用:
二、进程
1.进程的概念
2.进程管理
3.进程的结构体里有哪些属性(核心的)
三、并行和并发
四、内存分配
五、进程间通信
六、进程和线程
一、操作系统 操作系统是一组做计算机资源管理的软件,常见的有Windows ,IOS,Android,Linux 等等
操作系统的作用: 对上要配合软件,给软件提供一个稳定的运行环境 对下要管理硬件设备 二、进程 1.进程的概念 进程是操作系统对每一个正在运行中的软件的一种抽象,可以把进程看过程序的一次运行。 进程是操作系统进行资源分配的基本单位!!!(包括 内存资源 硬盘资源 CPU资源)
2.进程管理 描述一个进程:使用结构体/类来表示一个进程有哪些信息
组织一个进程:使用一定的数据结构,把这些结构体/对象放到一起
3.进程的结构体里有哪些属性(核心的) PCB:进程控制块
1.PID:进程中唯一的标识
2.内存指针:当前进程使用了哪一块内存 (标识使用了内存上的哪些资源)
3.文件描述表:进程每次打开一个文件,就会产生一个文件描述符(标识了这些被打开的文件),对应的一组文件描述符,组织起来放到一个顺序表中就是“文件描述表” (使用了硬盘上的哪些资源)
4.进程调度信息(CPU分配) 进程的状态: 一种是就绪态:已经准备好了,随时可以在CPU上运行
一种是阻塞态:目前还没准备好,不能在CPU上运行
进程的优先级:进程间的调度不一定是“公平的” 进程之间存在优先级,故优先执行谁取决于优先级(跟下面食堂谁便宜就先运行谁一样!!)
进程的上下文:记录这个进程执行了到了哪里的“记录”,当CPU执行一个进程,还没执行完,暂时离开了这个进程,就要把之前CPU执行到哪里了,执行的中间结果“存档”存档一下(将寄存器中存储计算的中间结果存到PCB),等CPU回来时,可以接着上次的执行(将PCB中的值恢复到寄存器中)继续执行进程。
进程的进账信息:统计当前进程在CPU上执行了多长时间,可以作为调度的参考(那个运行时间少就可以先运行这个)
三、并行和并发 并行:两个核心同时运行两个进程,两个进程同时运行
并发:一个核心,先运行进程A,运行一会再去运行进程B,运行一会再去运行进程C,来回切换着运行,只要切换的足够快,看起来就和“同时”运行一样
并发举例:比如说,你在学校非常喜欢吃食堂的三个窗口A B C 窗口的大叔大婶都喜欢你天天去吃他们窗口的饭,但是你觉得一直吃一个窗口太腻了,于是你排了一个时间表:一 三 五 吃窗口A(因为窗口A 最便宜)二 四 吃窗口B(这个第二便宜) 周六吃窗口C 周日就随便吃其他窗口的 这样换个维度来看!! 如果我是站在一天的维度来说,那我就是这一天我只吃一个窗口的
如果是站在一个星期,一个月的维度来看,那我就是在同时吃这三个窗口的!!
只要你切换的足够快,那么看起来就和“同时”一样(并发) 如果你一天同时吃了窗口A和窗口B这样就是(并行)了!!!
四、内存分配 操作系统对内存的分配,采用的是空间模式,不同进程使用内存中的不同区域,相互之间互不干扰(使用虚拟地址)
举例:有两个进程A 和进程B 如果我们是采用的是真实的物理地址 如果我的进程A里面出错了,出现了野指针,这个野指针正好指向了进程B中的地址,这样两个进程就都坏掉了!!(这样及其不稳定)
方法1:起别名 <select id="selectAll" resultType="brand"> select id, brand_name as brandName, company_name as companyName, ordered, description, status from tb_brand; </select> 如上图,通过as关键字取别名,取名同字段对应的属性名一致
方法2:<resultMap>标签 注意:里面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来。
<resultMap id="brandResultMap" type="brand"> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> </resultMap> 关键字解释:
id:完成主键字段的映射 column:表的列名 property:实体类的属性名 result:完成一般字段的映射 column:表的列名 property:实体类的属性名 sql标签正常写即可(将select标签中添加resultMap属性,对应的value值为上述resultMap的id:
<select id="selectAll" resultMap="brandResultMap"> select * from tb_brand; </select>
文章目录 1 项目简介2 实现效果2.1 界面展示 3 设计方案3.1 概述3.2 系统开发流程3.3 系统结构设计 4 项目获取 1 项目简介 Hi,各位同学好呀,这里是M学姐!
今天向大家分享一个今年(2022)最新完成的毕业设计项目作品,【基于SSM的网上购物商城】
学姐根据实现的难度和等级对项目进行评分(最低0分,满分5分)
难度系数:3分
工作量:5分
创新点:3分
界面美化:5分
界面美化的补充说明:使用vue的基本都能达到5分
本项目完成于2022年6月份,包含内容 : 源码 + 论文 + 答辩PPT
项目获取:
https://gitee.com/sinonfin/L-javaWebSha/tree/master
2 实现效果 视频地址:https://www.bilibili.com/video/BV1hW4y1S7qE
2.1 界面展示 管理员登录界面 商品信息管理界面 前台首页功能界面 商品信息界面 3 设计方案 3.1 概述 本文研究的网上购物商城基于当前较为流行的B/S结构,采用Java技术和MYSQL数据库进行开发设计。通过本系统,实现了不同权限的用户登录,包括用户和管理员。管理员:首页、个人中心、用户管理、关于我们管理、商品信息管理、商品类型管理、新闻类别管理、举报投诉管理、订单信息管理、售后管理、新闻信息管理、我的收藏管理、留言板管理、交流论坛、系统管理。用户:首页、个人中心、举报投诉管理、订单信息管理、售后管理、我的收藏管理,前台首页;首页、关于我们、商品信息、新闻信息、交流论坛、留言反馈、个人中心、后台管理、在线客服等功能。本系统经过测试,运行效果稳定,操作方便、快捷,是一个功能全面、实用性好、安全性高,并具有良好的可扩展性、可维护性的网上购物商城。
本系统的开发是基于B/S结构,采用Java程序设计语言及MYSQL数据库进行开发;主要完成了系统的总体设计与规划、数据库的设计、系统页面的制作与美化、系统安全级别的定制和系统程序的编写、调试与修改等工作。
3.2 系统开发流程 系统流程分析是调查分析系统所涉及到的每个环节的业务流程,从网上购物商城的登录着手,以实际操作为出发点,掌握所有网上购物商城内容,保证信息能够正确的输入和输出,数据存储的完整性以及信息处理方法过程,并根据实际操作步骤来绘制出具体的流程图。
3.3 系统结构设计 通过系统需求分析,本网上购物商城包括管理员:首页、个人中心、用户管理、关于我们管理、商品信息管理、商品类型管理、新闻类别管理、举报投诉管理、订单信息管理、售后管理、新闻信息管理、我的收藏管理、留言板管理、交流论坛、系统管理,用户:首页、个人中心、举报投诉管理、订单信息管理、售后管理、我的收藏管理等功能。
4 项目获取 本项目完成于2022年6月份,包含内容 : 源码 + 论文 + 答辩PPT
项目获取:
https://gitee.com/sinonfin/L-javaWebSha/tree/master
目录
数据库准备
查询数据 增加数据
删除
修改
数据库准备 CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; 首先需要在本项目的控制台中安装pymysql包
pip install pymysql
查询数据 导入pymysql包 import pymysql # 创建连接对象 conn=pymysql.connect(host="localhost",port=3306,user="root",password="xxx",database="python_test") # 获取游标对象 cs=conn.cursor() # sql语句 sql="select * from t_user;" # 执行sql content=cs.execute(sql) # 打印结果 print(content) # 关闭游标和连接 cs.close() conn.close() 执行代码,发现只得到了数据数量。
那么如何获取数据呢,使用cs.fetchone()方法
import pymysql # 创建连接对象 conn=pymysql.
Nuxt3稳定版+naive-ui项目开发 nuxt3在2022-11-16发布了稳定版本,网上很多资料的nuxt版本和其他插件或者ui框架的使用都不匹配,踩坑中,欢迎指正,不胜感激,让我们开始把。
nuxt3安装 按照官网,已安装node,vscode情况下
1.终端里cd进你想要的文件夹, 执行npx nuxi init ;(输入项目名称)
2. 再执行code ,就会在vscode里打开项目
3. 执行npm install安装依赖;
4. npm run dev就启动好项目了;
创建目录结构 1.pages放vue文件,列如index.vue,aboutUs.vue等等 app.vue改为NuxtPage,就能看到你index里的内容了
<template> <div> <NuxtPage /> </div> </template> 2.assets
3.components公共组件
4.composables做数据的共享和一些公共的方法,在vue文件里不用引入,nuxt会自动引入;我这里做了api的管理,在该文件夹下新建index.ts文件,如下
import Http from '@/utils/request' // 首页 export const getIndexInfo = (params: any) => { return Http.get('/xxx/xxx', params) //接口路径 } 在页面使用
<template> <div> <h1>Welcome to the homepage</h1> </div> </template> <script lang="ts" setup> const info = await getIndexInfo ({}) console.log('info', info) </script> 5.
摘要:在使用的装配体的过程中可能会遇到的这么一个问题,在装配体的状态下,选择零件的属性界面会出现该零件所有的配合关系,但是我们通过shift键全选无法完成,这个现象只存在于SOLIDWORKS 2020&2021版本的,其他版本都已经修复了,如果现在没有更换版本的想法,怎么做可以更方便些呢?现在就带大家一次操作一下。
一、首先我们在装配体界面下点击某个零件查看属性,如图1所示
二、 使用shift键点击第一个配合和最后一个配合就会发现中间的配合都没有选上,这个跟预期的全选不一致。如图所示
三、 现在使用shift键选择第一个和倒数第二个,再按住ctrl键加选最后一个配合,就会出现的效果跟预期一样,我们就可以达到选择所有配合目的,如图所示
四、总结:目前我们在装配体的界面上无法使用shift键全选所有的配合,但是我们可以退其一步使用shift键选择倒数第二个,然后再按ctrl键加选最后一个到达我们的目的。(PS:这个处理方法是在前提是SOLIDWORKS 2020 &2021 版本。)如果您有生版本或者将版本的打算,并不需要如此操作,按住shift键直接选择最后一个配合就可以了。
R语言基础(一):注释、变量
R语言基础(二):常用函数
R语言基础(三):运算
5.数据类型 5.1 基本数据类型 R语言基本数据类型大致有六种:
整数Integer、浮点数Numeric、文本(字符串)Character、逻辑(布尔)Logical、复合类型Complex、原型Raw
其中整数和浮点数也可以归类为数字类型numeric。数字默认是浮点数double(小数),整数后面加上字母L才是整数。
字符串:单引号或双引号包裹起来,比如:“hello,world”、‘My name is MengLaoShi’
逻辑:也叫布尔型,只有TRUE和FALSE两个值。注意TRUE是布尔型,而’TRUE’是字符串
复合类型表示虚数,虚数单位是i
原型:是以一种二进制形式存储的数据
可以使用typeof()函数查看数据类型
> typeof(TRUE) [1] "logical" > typeof(2) #数字中的浮点型 [1] "double" > typeof(3L) #整数后面加一个L代表整数类型 [1] "integer" > typeof(3+2i) #复合类型,虚数 [1] "complex" > typeof("hello") #字符型 [1] "character" > charToRaw("a") #raw类型(原型) [1] 61 字符串有一些常用的操作,
> a='hi' > b='R' > paste(a,b) #连接字符串,默认空格 [1] "hi R" > paste(a,b,sep=",") #指定连接符 [1] "hi,R" > nchar("Google") #获取字符串长度 [1] 6 > toupper('a') #转换大写 [1] "
什么是消息中间件 MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。
为什么使用MQ? 在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
RabbitMQ 基于erlang开发
是采用Erlang语言实现的AMQP协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息。RabbitMQ发展到今天,被越来越多的人认可,这和它在可靠性、可用性、扩展性、功能丰富等方面的卓越表现是分不开的。
RabbitMQ优点:
由于erlang语言的特性,mq性能较好,高并发;健壮、稳定、易用、跨平台、支持多种语言、文档齐全;有消息确认机制和持久化机制,可靠性高;高度可定制的路由;管理界面较丰富,在互联网公司也有较大规模的应用;社区活跃度高; 如果你也正好在RabbitMQ消息中间件方面理解的不透彻,应对面试官的提问有些发怵。这里小编就要给大家分享一个RabbitMQ核心笔记了,图文并茂,非常适合有需要学习RabbitMQ消息中间件的朋友!由于篇幅原因,有需要RabbitMQ核心笔记完整文档可点赞支持一下,点击下方传送门即可入手~
RabbitMQ核心笔记的学习路线导图概览:
下面是RabbitMQ核心笔记的目录和部分内容截图
如果截图不是很清晰还请见谅啦,由于篇幅原因,有需要RabbitMQ核心笔记完整文档可帮忙点赞支持一下,点击下方传送门即可入手~
1.消息中间件概述
2.安装及配置RabbitMQ
3. RabbitMQ入门
4. AMQP
5. RabbitMQ工作模式
6. Spring Boot整合RabbitMQ
7. RabbitMQ高级
8. RabbitMQ集群
9. RabbitMQ高可用集群[扩展]
10. RabbitMQ应用与面试
如果截图不是很清晰还请见谅啦,小编已经尽量做到最清晰了!!
由于篇幅原因,有需要RabbitMQ核心笔记完整文档的麻烦帮忙点赞支持一下,点击下方传送门即可入手~
最新通知:从2023年上半年软考开始信息系统项目管理师考试将依据新版考试大纲进行。
给备考高项的朋友的一些建议:
备考资源:
【腾讯文档】软考各科资料分享
https://docs.qq.com/doc/DTVN1SWtFZHdicUNp
复习方法:
选择题
选择题分2种,一种是纯记忆的选择题,一种是含有计算的选择题。
选择题考的比较杂,需要多看教材,多刷历年真题!
案例题
在下午的考试中案例分析题型可以大致分为以下两大类:综合管理知识类、计算画图类。
一、计算类(每年必考!)在考试中先写公式,再计算!
PV(计划价值,各个活动的计划价值) EV(挣值,完成工作的计划值之和)
AC(实际成本) BAC(完工预算)
CV(成本偏差)=EV-AC SV(进度偏差)=EV-PV
CPI(成本绩效指数)=EV/AC SPI(进度绩效指数)=EV/PV
EAC(完工估算)=BAC/CPI(典型)
EAC=AC+ETC=AC+(BAC-EV)(非典型)
EAC=AC+(BAC-EV)/CPI(典型)
ETC(完工尚需估算)=EAC-AC
ETC=BAC-EV (非典型)
ETC=(BAC-EV)/CPI(典型)
其他概念:
关键路径:项目时间最长的活动顺序,在单代号图中是总时差和自由时差均为0的活动链接而成。(例子中的A-C-D)。
自由浮动时间(自由时差):MIN(紧后活动的最早开始时间)—本活动的最早完成时间。
总浮动时间(总时差):最迟(开始或结束时间)-最早(开始或结束时间)。
有一起备考2023年软考的滴滴!大部队,一起备考!#软考##软考高级信息系统项
一、 数理逻辑
[复习知识点]
1、命题与联结词(否定¬、析取∨、合取∧、蕴涵→、等价↔),命题(非真既假的陈述句),复合命题(由简单命题通过联结词联结而成的命题)
2、命题公式与赋值(成真、成假),真值表,公式类型(重言、矛盾、可满足),公式的基本等值式
3、范式:析取范式、合取范式,极大(小)项,主析取范式、主合取范式 4、公式类型的判别方法:真值表法、等值演算法、主析取/合取范式法 5、命题逻辑的推理理论
6、谓词、量词、个体词(公式一阶逻辑3要素)、个体域、变元(约束出现与自由出现)
7、命题符号化、谓词赋值与解释,谓词公式的类型(永真、永假、可满足)
8、谓词公式的等值式(代换实例、消去量词、量词否定和量词辖域收缩与扩张、量词分配)和置换规则(置换规则、换名规则)
消去量词:
置换规则:
9、一阶逻辑前束范式(定义、求法)
本章重点内容:命题与联结词、公式与解释、(主)析取范式与(主)合取范式、公式类型的判定、命题逻辑的推理、谓词与量词、命题符号化、谓词公式赋值与解释、求前束范式。
注意关于蕴含:在自然语言里,特别是在数学中,q是p的必要条件有许多不同的叙述方式,例如,“只要p,就q”“因为p;所以q”;“p仅当q”;“只有q才p”;“除非q才p”;“除非q,否则非p”,等等.以上各种叙述方式表面看来有所不同,但都表示q是p的必要条件,因而都应使用→,符号化为p→q.
[复习要求]
1、理解命题的概念;了解命题联结词的概念;理解用联结词产生复合命题的方法。
2、理解公式与赋值的概念;掌握求给定公式真值表的方法,用基本等值式化简其它公式,公式在解释下的真值。
3、了解析取(合取)范式的概念;理解极大(小)项的概念和主析取(合取)范式的概念;掌握用基本等值式或真值表将公式化为主析取(合取)范式的方法。
4、掌握利用真值表、等值演算法和主析取/合取范式的唯一性判别公式类型和公式等价方法。
5、掌握命题逻辑的推理理论。
6、理解谓词、量词、个体词、个体域、变元的概念;理解用谓词、量词、逻辑联结词描述一个简单命题;掌握命题的符号化。
7、理解公式与解释的概念;掌握在有限个体域下消去公式量词,求公式在给定解释下真值的方法;了解谓词公式的类型。
8、掌握求一阶逻辑前束范式的方法。
二、 集 合
[复习知识点]
1、集合、元素、集合的表示方法(列元素法、谓词表示法)、子集、空集、全集、集合的包含、相等、幂集
幂集:
2、集合的交、并、差、补以及对称差等运算及有穷集的计数(文氏(Venn)图、包含排斥原理)
3、集合恒等式(幂等律、交换律、结合律、分配律、吸收律、矛盾律、德摩根律等)及应用
本章重点内容:集合的概念、集合的运算性质、集合恒等式的证明。
[复习要求]
三、 二元关系
[复习要求]
1、了解序偶与笛卡尔积的概念,掌握笛卡尔积的运算。
2、理解关系的概念:二元关系、空关系、全域关系、恒等关系;掌握关系的集合表示、关系矩阵和关系图、关系的运算。】
3、掌握求复合关系与逆关系的方法。
4、理解关系的性质(自反性、反自反性、对称性、反对称性、传递性),掌握其判别方法(定义、图)。
自反性:全部顶点均有环;反自反性:全部顶点均无环;对称性:有边均双边(无单边,顶点有无环不影响) ;反对称性:有边均单边(顶点有无环不影响)(无平行边)
传递性:a到b有边,b到c有边,则a到c也有边,否则不然。
5、掌握求关系的闭包 (自反闭包、对称闭包、传递闭包)的方法。
换言之:r=加自环 s=单边变双边 t:努力变传递
6.理解等价关系和划分、掌握等价类和划分的求法
7、理解偏序关系的概念,掌握画哈斯图的方法,极大/小元、最大/小元的求法。
相关概念:
哈斯图的方法: 如图7.7:5,9,6,8,7均是极大元,1是极小元,无最大元,最小元为1;右边: {a,b,c}是极大元,∅是极小元,最大元是 {a,b,c},最小元为∅ 四、函数
[复习知识点]
理解函数概念:函数、函数相等、A到B的函数。 2、理解单射、满射、双射等概念,掌握其判别方法。
单射:不同的x所对应的y不同。
满射:y的值域全用到了。
双射:单+满
3、函数的复合与反函数
函数复合及相关联习
反函数:
本章重点内容:函数的定义及判别方法、函数的三大性质、函数的复合与反函数。
[复习要求]
相对布局在Compose中被称为ConstraintLayout,它可以让您以相对于其他元素的方式放置元素。 以下是使用ConstraintLayout实现相对布局的示例代码:
@Composable
fun ConstraintLayoutExample() {
ConstraintLayout(modifier = Modifier.fillMaxSize()) { // 用 ConstraintLayout 作为根布局,占满整个屏幕
val (topText, bottomText, button) = createRefs() // 创建三个 Ref 对象
Text(
text = "Top Text",
modifier = Modifier.constrainAs(topText) { // 给 Text 组件设置约束
top.linkTo(parent.top) // 顶部约束为父布局的顶部
start.linkTo(parent.start) // 左侧约束为父布局的左侧
end.linkTo(parent.end) // 右侧约束为父布局的右侧
}
)
Text(
text = "Bottom Text",
modifier = Modifier.constrainAs(bottomText) { // 给 Text 组件设置约束
top.linkTo(topText.bottom) // 顶部约束为上面的 Text 组件的底部
start.linkTo(parent.start) // 左侧约束为父布局的左侧
文章目录 const说说const int *a, int const *a, const int a, int *const a, const int *const a分别是什么,有什么特点。const成员函数const和#define的区别什么const在常量区,什么const在栈区,什么const放入符号表优化 C++内存分区(五)内存对齐原因什么时候不应该内存对齐?内存对齐的规则 虚函数作用实现纯虚函数虚函数在什么时候调用?大小C++ 中哪些函数不能被声明为虚函数?为什么虚函数不能是模板函数?虚函数表既然希望类的所有对象共享为什么不放在全局区 菱形继承类型转换static_castdynamic_castdynamic_cast和虚函数的区别 reinterpret_castconst_castvolatile关键字 构造函数一大家子拷贝构造函数什么时候调用拷贝构造函数? 析构函数为什么要用虚的? 移动构造函数 C++类内是否可以定义引用?模板类模板实例化模板具体化模板为了解决什么问题?模板的声明和定义为什么不能分开写,要想分开写该怎么做模板特化全特化偏特化 模板在编译时生成的代码是否会相同,生成的相同的代码如何处理 C++ 类对象的初始化顺序STL容器顺序型容器vector第二个模板形参?vector调用resize的时候,如果是元素是一个类,会不会调用这些函数的析构函数?使用Vector需要注意什么?如果扩容时会引发自定义类型挨个复制构造,C++有什么机制来避免这一点 dequelist 关联式容器setmap红黑树的性质,各种操作时间复杂度 unordered_map哈希表跟红黑树的比较,优缺点、适用场合,各种操作的时空复杂度 空间配置器定义背景实现迭代器迭代器用过吗?什么时候会失效?迭代器的作用迭代器相较于指针 说说 STL 中 resize 和 reserve 的区别resize:reserve: STL 容器动态链接可能产生的问题push_back 和 emplace_back 的区别STL 中 vector 与 list 具体是怎么实现的?常见操作的时间复杂度是多少? 新特性智能指针share_ptrunique_ptrweak_ptr怎么知道weak_ptr失效了没 lambda表达式lambda语法:[capture]含义(parameters)含义mutable 或 exception 声明->return-type->{statement}{函数体} Lambda表达式如何对应到函数对象圆括号传参数是如何实现的方括号捕获外部变量(闭包)是如何实现的 右值引用由来增加右值引用之后移动语义如何将左值强制转换为右值? 移动构造函数和拷贝构造函数的区别转发和完美转发常规转发完美转发 auto关键字,lambda表达式,nullptr,成员初始化列表 static关键字面向过程面向对象初始化 C++编译过程动态链接和静态链接 内联函数定义意义哪些不适合作为内联函数使用内联的缺点和宏的区别 程序启动的过程多态静态多态动态多态虚函数动态绑定 多态的好处多态的形式 杂项32位整型在大小端的区别 (0x12345678)一个空类的大小是几字节?指针和引用的区别浅拷贝和深拷贝的区别?struct和class的区别导入C函数的关键字是什么,C++编译时和C有什么不同?函数指针new和mallocdelete如何知道该释放多大的空间,这些信息存在什么位置 delete[]和delete的区别,基本数据类型的数组使用delete可以释放完全吗堆和栈的区别内存泄漏说说C++的重载和重写是如何实现的重载重写 说说 C 语言如何实现 C++ 语言中的重载简述下向上转型和向下转型子类转换为父类父类转换为子类 请问构造函数中的能不能调用虚方法那么析构函数中能不能调用虚方法请问拷贝构造函数的参数是什么传递方式,为什么仿函数C++中类模板和模板类的区别64位系统存一个地址多大空间函数传递时会不会在内存拷贝为什么要使用友元?检查内存泄漏的方法C++编译和C编译的区别如何判断一段函数是C++编译的还是C编译的 如何在不用sizeof的情况下判断系统是多少位重复多次 fclose 一个打开过一次的 FILE *fp 指针会有什么结果,并请解释为什么函数传递数组参数,结果数组会被修改,而值不行?main 函数执行以前,还会执行什么代码?字符指针、浮点数指针、以及函数指针这三种类型的变量哪个占用的内存最大?为什么?C++几个基本类型占用空间继承时应该要写哪些类的成员函数怎样让对象只能创建在栈/堆/内存池中RTTI原理,type_info信息存在虚函数表的哪里C++在哪些情况下会产生临时对象C++静态链接库(lib)和动态链接库(dll)的区别memory_move和memory_copy两者的作用和区别 const 说说const int *a, int const *a, const int a, int *const a, const int *const a分别是什么,有什么特点。 const int *a==int const *a:都是指a所指向的值不能改,但是a可以指向别的东西const int a:a变量变成常量,不可修改int *const a:a的值可以更改,但是指向它的指针不能更改int const *const a:a本身和指向它的指针都不能更改 const成员函数 常函数内不能修改成员变量对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。 例如,假设有一个类A,它有一个私有成员变量x和一个公有成员函数getX(),如果getX()返回x的引用,并且不加const修饰,那么就可以这样写:
问题 snmpd 启动 497 天后,产生如下日志信息:
Mar 10 08:27:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:18:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:18:37 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:19:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:19:37 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:20:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:20:37 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:21:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:21:37 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:22:08 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:22:38 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:23:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:23:37 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:24:08 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:24:38 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:25:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:25:38 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:26:07 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:26:38 rhel6 snmpd[18697]: truncating integer value > 32 bits Mar 10 08:27:07 rhel6 snmpd[18697]: truncating integer value > 32 bits 受影响的环境 Red Hat Enterprise Linux 5
二叉树 1.前序遍历(先序遍历) 根节点-----左子树-----右子树 (根左右) 时间复杂度为O(n) 2.中序遍历 左子树-----根节点-----右子树 (左根右) 时间复杂度为O(n) 3.后序遍历 左子树-----右子树-----根节点 (左右根) 时间复杂度为O(n) 4.层序遍历 从根节点开始,一层一层,从上到下,每层从左到右 5.根据已知的两个遍历,求第三种遍历 方法:1.前序遍历的第一个节点就为该二叉树的根节点。 2.后序遍历的最后一个节点为该二叉树的根节点。 2.在中序遍历序列中找到根节点的位置,根节点左侧的所有节点都属于左子树,右侧的所有节点都属于右子树。 最后再依据前面的三条,对已经确认好的左子树或右子树进行分析,直至确定最终的二叉树。 5.1.已知前序遍历和中序遍历,确认后序遍历 例子:已知前序遍历为ABDHIEJCFKG,中序遍历为HDIBEJAFKCG,则该二叉树的后序遍历为?
分析:1.通过前序遍历可确认该二叉树的根节点为A
2.通过中序遍历+根节点为A,确认HDIBEJ为左子树,FKCG为右子树
3.对左子树HDIBEJ进行分析,分析原理同上,即前序遍历中的BDHIEJ中,B为左子树的根节点,再以此为依据,分析中序遍历中的HDIBEJ,HDI为左子树,EJ为右子树,接下来同理。
4.对右子树FKCG进行分析,分析原理同上,即前序遍历中的CFKG中,C为左子树的根节点,再以此为依据,分析中序遍历中的FKCG,FKI为左子树,G为右子树,接下来同理。
所以最后的图为,后序遍历为HIDJEBFGCA
5.2.已知后序遍历和中序遍历,确认前序遍历 例子:已知中序遍历为ABCDEFG,后序遍历为BDCAFGE,则该二叉树的前序遍历为?
分析:1.通过后序遍历可确认该二叉树的根节点为E
2.通过中序遍历+根节点为E,则确认ABCD为左子树,FG为右子树
3.对左子树ABCD进行分析,原理同上:中序遍历为ABCD,后序遍历为BDCA,A为左子树根节点,BCD为A的右子树,接下来同理。
4.对右子树FG进行分析,G是F的根节点
所以最后的图为:前序遍历为EACBDGF
系列文章 Android音视频学习系列(一) — JNI从入门到精通
Android音视频学习系列(二) — 交叉编译动态库、静态库的入门
Android音视频学习系列(三) — Shell脚本入门
Android音视频学习系列(四) — 一键编译32/64位FFmpeg4.2.2
Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据
Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据
Android音视频学习系列(七) — 从0~1开发一款Android端播放器(支持多协议网络拉流本地文件)
Android音视频学习系列(八) — 基于Nginx搭建(rtmp、http)直播服务器
Android音视频学习系列(九) — Android端实现rtmp推流
Android音视频学习系列(十) — 基于FFmpeg + OpenSL ES实现音频万能播放器
前言 音视频开发可以说是当下最主流的技术之一了。原本音视频开发应该是要从C/C++ 基础讲起的,由于篇幅实在过长,就将C/C++教程上传在GitHub了。我们就直接从JNI开始讲起。
那么该篇文章开始就直接进入 NDK 学习了,在进入 NDK 学习之前我们还要学习 JNI 基础。
介绍 JNI 是 Java 程序设计语言功能功能最强的特征,它允许 Java 类的某些方法原生实现,同时让它们能够像普通 Java 方法一样被调用和使用。这些原生方法也可以使用 Java 对象,使用方法与 Java 代码调用 Java 对象的方法相同。原生方法可以创建新的 Java 对象或者使用 Java 应用程序创建的对象,这些 Java 应用程序可以检查、修改和调用这些对象的方法以执行任务。
环境配置 安装 AS + NDK + CMake + LLDB
前些日子买了个新的STLINKV2 , ( 老的被我家猫猫一泡尿送上西天了)
刚开始还挺正常的, 后来有一天就突然间发现无法调试了.
网上尝试了各种方法, 各种操作. 百度了好久. 最后好在我自己研究出来了.
我使用的是 STM32CubeIDE 这个开发工具
调试选项如下图
其它的不需要修改, 然后点击下面的apply 按钮, 然后调试Debug, 提示 No STLink 如下图
后来尝试了下载ST-LINK Utility 用它是可以正常连接STLink的, 然后也能正常进行升级操作.
也能正常读取ST-Link的序列号.
可是在CubeIDE中就不能正常读取 . 使用CubeIDE中的 ST-Link 更新功能
却是可以正常更新的, 能够更新到比ST-LINK Utility 还要高的版本.
但是调试却仍然不行, 后来研究了一下, 我感觉可能跟我前些日子安装的杀毒软件有关.
于是我退出了360安全卫士 ,但是效果仍然如故. 还是不能用.
后来我在调试配置界面中发现了这个,我感觉应该是它的问题, 既然用到了端口说不定是跟网络防火墙或者其它的什么有关系. 然后我就点了下Show Command Line 按钮,
把里面的命令复制出来,到命令行窗口中运行了一下. 第一次的时候竟然弹出来了一个防火墙是否允许的提示, 这里我无法再次重现所以截不到图.
最后正常运行的图如下图,说明正常运行了,.
然后我再回到调试配置界面, 选择连接到远程GDB服务器, 但是地址仍然写localhost 端口不变. 这个时候我竟然可以正常调试了.
至此,问题已明了, 根本原因还是调试用的端口被杀毒软件或者防火墙给阻止了, 方法很简单, 要么关掉防火墙, 要么卸掉杀毒软件裸奔, 要么设置一下绿色端口. 就可以正常使用 启动本地GDB服务啦.
这里说一下原理, 为了统一和简化调试的复杂度, 开发工具软件几乎都是通过网络socket 端口来连接被调试的系统的. cubeide 本身并没有访问usb端口和串口或任何硬件, 只是通过网络socket端口跟GDB调试服务器进行通信, 这种调试服务器可以是STLINK server 也可以是Jlink Server 这种调试服务器是实现了调试接口协议的一个简单的程序, 这种调试服务器程序需要开放监听一个端口, 等待来自开发工具的连接.
答案在最后 1.下列关于纯虚函数的描述中,正确的是 A.纯虚函数是一种特殊的虚函数,是空函数
B.具有纯虚函数的类称为虚基类
C.一个基类中说明有纯虚函数,其派生类一定要实现该纯虚函数
D.具有纯虚函数的类不能创建类对象,因为它是虚基类
2.关于引用与指针的区别,下列叙述错误的是 A.引用必须被初始化,指针不必
B.删除空指针是无害的,不能删除引用
C.不存在指向空值的引用,但是存在指向空值的指针
D.指针初始化以后不能被改变,引用可以改变所指的对象
3.在创建类派生对象时,构造函数的执行顺序是 A.对象成员构造函数,派生类本身的构造函数,基类构造函数
B.派生类本身的构造函数,基类构造函数,对象成员构造函数
C.派生类本身的构造函数,对象成员构造函数,基类构造函数
D.基类构造函数,对象成员构造函数,派生类本身的构造函数
4.将父类的析构函数定义为虚函数,下列正确的是 A.释放子类指针时能正确释放父类对象
B.这样做是错误的
C.释放父类指针时能正确释放子类对象
D.以上全错
5.假定指针变量p定义为“int *p = new int(100);”,要释放p所指向的动态内存,应使用语句 A. delete *p;
B. delete p;
C. delete &p;
D. delete []p;
6.程序阅读 #include <iostream> using namespace std; class A { public: A(){cout << "A";} }; class B { public: B(){cout << "B";} }; class C : public A { B b; public: C(){cout << "
源代码:
#include <stdio.h> int main() { int i; double e=1,k=1; for(i=1;i<=10;i++){ k=k*i; e=e+1/k; } printf("计算结果为:%lf\n",e); return 0; } 运行结果:
1.根据服务器配置调整线程池参数
根据服务器配置调整核心线程数,最大线程数和阻塞队列的大小。线程池太小会导致任务队列堆积,处理延迟;线程池太大会浪费资源。
2.合理使用任务队列
一般用数组型任务队列ArrayBlockingQueue和链表型队列LinkedBlockingQueue,ArrayBlockingQueue的读锁和写锁公用一把锁,而LinkedBlockingQueue的读锁和写锁是分开的,因此LinkedBlockingQueue效率更高。
3.合理使用拒绝策略
由调用的线程来处理被拒绝的线程:需要考虑是否会占用tomcat的线程数造成影响。适用于处理速率快,提交速率更快的场景。
拒绝但是抛出异常:适用于提交速率低的场景,确保任务不会被丢失。
拒绝不抛出异常:适用于提交效率高但是不重要的任务。
抛弃队列最前面的任务,重新提交被拒绝的任务:适用于处理速率蛮,提交速率快的场景。
4.避免线程的阻塞
当线程池的线程阻塞,会导致线程池效率变低,可以使用非阻塞IO,比如NIO和AIO等。
5.使用工具监控线程池
jconsole:
visualVM;
一. Hive函数基础 1. 聚合函数 hive 支持 count(),max(),min(),sum(),avg() 等常用的聚合函数
注意:
聚合操作时要注意 null 值 count(*) 包含 null 值,统计所有行数 count(id) 不包含 null 值 min 求最小值是不包含 null,除非所有值都是 null avg 求平均值也是不包含 null 2. 关系运算 支持:等值(=)、不等值(!= 或 <>)、小于(<)、小于等于(<=)、大于(>)、大于等于(>=)
空值判断(is null)、非空判断(is not null)
LIKE 比较: LIKE
语法: A LIKE B
操作类型: strings
描述: 如果字符串 A 或者字符串 B 为 NULL,则返回 NULL;如果字符串 A 符合表达式 B 的正则语法,则为TRUE;
3. 数学运算 支持所有数值类型:加(+)、减(-)、乘(*)、除(/)、取余(%)、位与(&)、位或(|)、位异或(^)、位取反(~)
4. 逻辑运算 支持:逻辑与(and)、逻辑或(or)、逻辑非(not)
5. 数值运算 取整函数: round 语法: round(double a)
目录 1. 二叉树遍历DescriptionInputOutputSample Input 1Sample Output 1Hint代码 2. 手机号码格式化DescriptionInputOutputSample Input 1Sample Output 1Sample Input 2Sample Output 2Sample Input 3Sample Output 3Sample Input 4Sample Output 4Sample Input 5Sample Output 5 3. 斐波那契数列拆分DescriptionInputOutputSample Input 1Sample Output 1Sample Input 2Sample Output 2Sample Input 3Sample Output 3Sample Input 4Sample Output 4 1. 二叉树遍历 Total 【2434】、 AC rate 【2.10%】
Description 给定一棵满二叉树树先序遍历的输出结果,求该树中序遍历的输出结果。
Input 2^n - 1个数字(n是≤16的正整数),每个数字的取值范围[0, 255], 数字之间用逗号分割。
Output 树的中序遍历结果,数字之间通过逗号分割。
Sample Input 1 1,2,3,4,5,6,7 Sample Output 1 3,2,4,1,6,5,7 Hint 不要有任何多余的输出 C/C++,换行为"
欢迎来到南方有乔木的博客!!!
博主主页:点击点击!戳一戳!!
博主QQ:南方有乔木呀
博主简介:
一名在校大学生,正在努力学习Java语言编程。穷且意坚,不坠青云之志,希望能在编程的世界里找到属于自己的光。
跪谢帅气or美丽的朋友们能够帮我点赞! 请对文中内容请多多指教!!!
目录
一.游戏规则
二.编程思路
三.编程过程
1.第一步
2.第二步
3.第三步
一.游戏规则 系统自动生成一个随机整数(1- 100),然后由用户输入一个猜测的数字,如果输入数字比生成数大,则提示“猜大了”;如果输入数字比生成数小,则提示“猜小了”;如果输入数字与生成数一样,则提示“猜对了”。
二.编程思路 对于这样一个小游戏,首先来理清它的编程思路。
1.首先需要生成一个1-100的随机数
2.从键盘循环捕捉一个数字,与生成的随机数比较
3.若输入的数字大于随机数,输出猜大了,若输入的数字小于随机数,输出,猜小了。
三.编程过程 1.第一步 生成一个随机数,我们需要首先导入生成随机数的包:
import java.util.Random;//生成随机数使用 再生成一个随机数:
Random random=new Random();//为随机数分配内存空间 int guess=random.nextInt(100);//获取1到100随机数 int guess=random.nextInt(100) 括号里的100表示生成随机数的范围是1到100;
2.第二步 生成随机数以后,用户需要从键盘循环输入一个猜测的数字,与随机数进行比较。这里的输入要进行循环输入,可以用while循环来解决;
import java.util.Random;//导入生成随机数需要的包 import java.util.Scanner;//导入键盘输入需要的包 public class Game { public static void main(String[] args) { Scanner sc=new Scanner(System.in); Random random=new Random();//为随机数分配内存空间 int guess=random.nextInt(100);//获取1到100随机数 while(true)//输入到猜对为止 使用死循环 条件填入true { System.out.println("请猜一个1到100的数字:");//屏幕提示输入 int number=sc.nextInt();//键盘捕捉猜测的数字 } } } 要从键盘输入数字,一样的,也需要导入相应的包:
STM32查看内存占用的map文件解析 STM32查看内存占用的map文件解析程序内存分析在stm32中,通常堆向高地址增长(向上增长),栈向低地址增长(向下增长);1.2 flash、ROM、RAM的区别1.3 通常stm32在keil里编译完后被分成5个内存段(堆、栈、bss段、data段、text段) STM32查看内存占用的map文件解析 双击工程名尽可打开xxx.map文件,里面主要显示了文件及函数使用内存的大小
程序内存分析 在stm32中,通常堆向高地址增长(向上增长),栈向低地址增长(向下增长); 堆:是用户调用malloc()时申请的内存;
栈:是提供给局部变量使用的,即由c语言机制自动申请和释放;
1.2 flash、ROM、RAM的区别 在stm32中flash就是ROM,掉电数据不会丢失;(通常保存着text段、Code、Ro-data、Rw-data)
RAM就是运行内存,掉电数据就丢失;(通常保存着堆、栈、bss段、data段、ZI-data、RW-data)
1.3 通常stm32在keil里编译完后被分成5个内存段(堆、栈、bss段、data段、text段) 以下存储在RAM
堆区:在启动文件里分配,作为用户主动申请时的空间,如调用malloc()
栈区:在启动文件里分配,作为局部变量自动申请和释放空间的变量(也有说是编译器分配的空间)
全局区和静态区(bss+data):存放全局变量,静态变量的区域;其中bss段(ZI-data)存放未初始化的全局变量和静态变量;data段(RW-data)存放初始化后的全局变量和静态变量;
以下存储在flash(text段)
文字常量区:宏,常量字符串等存放区域;(RO-data)
程序代码区:程序代码块存放区域;(Code)
引用参考:stm32中堆、栈、flash、ROM、RAM、bss段、data段、text段、Code、Ro-data、 ZI-data、RW-data简介
MQTT协议-心跳请求和心跳响应 心跳请求是客户端发送给服务器的,心跳响应是服务器回应给客户端的
作用是保持客户端与服务器之间的连接
CONNECT报文的可变报头是由协议名(Procotol Name)+协议级别(Procotol Level)+连接标志(Connect Flags)+保持连接(keep Alive)四个部分组成的,可看到最后有一个保持连接的部分,这个就是心跳请求
0x64的十进制是100,因此设置了100秒的保持连接时间,客户端在与服务器建立连接后的100秒内,需要发送数据到服务器进行通信,否则服务器会自动断开连接,假如客户端在这100秒内没有数据发送,但又不想与服务器失去连接,就要发送心跳请求报文
心跳请求报文PINGREQ的组成 心跳请求报文比较简单,只有固定报头,固定报头由两个字节组成,第一个字节为固定为C0,第二个字节为剩余长度,但后面没有有效载荷的内容,因此剩余长度为0,所以心跳请求报文就为C0 00
心跳响应报文PINGRESP的组成 心跳响应报文由服务器接收到客户端的心跳请求后返回,与心跳请求报文一样,只有固定报头,为D0 00
程序中发送心跳报文 先定义一个发送心跳报文的函数
uint8_t mqtt_buff[2] = {0}; void mqtt_Ping(void) { //组合报文 mqtt_buff[0]=0xC0; mqtt_buff[1]=0x00; //发送报文 mqtt_DealTxData(mqtt_buff,2); } 用定时器中断调用mqtt_Ping函数进行定时发送,定时器可在客户端连接上服务器并发送了一个报文数据后打开,假设CONNECT报文设置的保持连接时间是100秒,那心跳请求可以每30秒或50秒发送一次,只要小于100秒就行,因此定时器可初始化为30秒或50秒,根据实际来定。
void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) { //发送心跳请求 mqtt_Ping(); TIM_ClearITPendingBit(TIM3,TIM_IT_Update); } }
在python 3.10中一启动就会报这个错
AttributeError: module 'collections' has no attribute 'Callable' 解决方法
进入python安装目录 如我的在C盘下修改py3k_compat.py这个文件C:\python311\lib\site-packages\pyreadline\py3k_compat.py
在第8行把 return isinstance(x, collections.Callable)改为 return isinstance(x, collections.abc.Callable)即可正常使用
参考
https://github.com/hylang/hy/issues/2114
最近做了一个项目,XXX降低成本,原来使用的LPC2294这样老古董芯片,更换为STM32F4XX, 项目重点要播放语音!
stm32输出音频,有2种方法,第一种比较常规, 使用I2S接口的音频codec芯片, 常用的有wm8978等; 另一种使用STM32内部的DAC来输出音频,这个其实也很成熟了,在音质要求不高的场合可以使用。我之前用过wm8978,调试耗费了很长时间,最后完美的实现了通过wm8978录音与播放功能,并且实现了MP3的压缩与解码功能,全部使用软编解码。
先说说STM32通过DAC来播放声音的实现方式:
1 DAC设置 首先选择TIM6触发DAC转换,为什么选择TIM6, 这也是有讲究的,首先TIM6、TIM7非常简单,也是可以说是简陋;ST文档中称作基本定时器,仅仅有一个16位自动重载功能,即使系统需要使用定时器也不会用这2位。 其次,TIM6\TIM7天生就与DAC绑定在一定,甚至连中断接口也是一个,TIM6_DAC_IRQHandler();(当然本项目不需要DAC\TIM6中断)。综上所述使用TIM6是明智的明智的选择。
设置TIM6记数周期,使TIM6向DAC申请中断的频率与WAV文件的采样频率保持一致,一般为8K或者16K,(试验证明16b量化8K采样的声音,没有8bit量化16K采样的声音音质好,虽然它们占用的存储空间一样!),使能TIM6更新请求 update event。
设置DAC,使能DAC1 通道DMA模式,12B左对齐, 选择定时器 6 TRGO 事件,等操作。
一切设置好之后,启动TIM6记数就可以启动DAC转换了。
2. DMA传输 为了尽可能降低MCU的占用, 为将来增加复杂的解码方式留足CPU频率资源,所以采用DMA传输(如果采用中断方式,如果播放16K采样频率的声音时会频繁的进出中断导致效率下降);同时为了降低DAC转换时的总线占用,DMA传输时使用的RAM也经过了特殊安排,为尽可能避免总线冲突,DAC使用SRAM2空间作为DMA传输的源地址,在DMA传输期间,MCU内核照样可以访问主SRAM1,且互不干扰。 这样就实现了DMA传输即不占用CPU资源,也不占用CPU总线资源。效率提高到极致!如下图所示:(注:红线为DMA传输路径,绿线为MCU内核访问路径)(其实这种总线并行复用的思路可以应用到很多外设上)
3. 双缓冲或者循环缓冲 要保证音频输出的连续性,必须使用双缓冲或者循环缓冲, 试验证明这2种方法都可以满足音频输出的要求,我认为DMA循环缓冲区只是DMA双缓冲区的一个特殊形式而已。(当双缓冲区2块数据相邻且大小一样时)
比如我在MDK中定义一个双缓冲区,在xxx.map文件中可以看到编译器给这2个数组分配的空间,
PCMDA_BUF0 : 0x2001c000 PCMDA_BUF1 : 0x2001d000
双缓冲区 循环缓冲区
其实我完全可以定义一个大的缓冲区,来设计为循环缓冲区,比如
uint8_t PCMDA_BUF[I2S_DMA_RAMBUF_SIZE*2] __attribute__((section("SRAM2")));
其实编译器给这个数组分配的空间还是上面的空间,0x2001c000~ 0x2001dFFF; (8KB)
为了实时的更新缓冲区中的音频数据,根据缓冲区形式的不同,操作也不不一样,如果是双缓冲区时,做如下操作:当缓冲区1 DMA传输完成中断时,更新缓冲区1中的数据,当缓冲区2 DMA传输完成中断时,更新缓冲区2中的数据,这样就形成了一个乒乓缓冲操作,数据永远不会中断,音频会流畅的放出来。
如果是循环缓冲区,STM32也提供有合适的操作,STM32提供的有DMA半传输完成中断,这个就非常有用了,当DMA半传输完成时,更新缓冲区前半部分的数据,当DMA全部传输完成发生中断时,更新缓冲区后一半的数据,这样也能实现双缓冲区的效果。
其实仔细的分析上面2种方式, 其本质是一样,都能实现 DAC-OUTPUT的连续输出。
TIM6生成16K时钟触发DAC转换,这时候要使能DMA, 同时DAC会向DMA申请一次传输, DMA要设置为循环传输, 同时要你使能DMA中断,半传输中断与全传输中断, 每次中断都把解码的声音拷贝到循环缓冲区中,这样就能连续的播放声音了。程序的精华是 在HAL库上实现DMA双缓冲播放声音, 原生的HAL库I2S不支持双缓冲
Injective 社区发布了有史以来第一个 Injective 全球黑客松,奖金总共高达 1,000,000 美元,以进一步支持最优秀的 Web3 开发者们。
Injective 是个闪电般快速的可互操作的 Layer-1 区块链,为开发人员提供了即插即用的模块,用于构建交易平台、DeFi、衍生品和 Web3 应用程序。Injective 由 Binance 孵化,并得到 Jump Crypto、Pantera 和 Mark Cuban 等著名投资者的支持。
开发者可以在 2023 年 3月 20 日之前注册。Injective 全球黑客松计划于三月下旬开始。您可以在 Injective Hackathon 官方网站上找到更多信息:https://injective.com/hackathon/
在为期一个月的在线黑客马拉松期间,您可以在加密行业领导者的指导下创建新型协议和去中心化应用。
关于 Injective 黑客松?
Injective 全球黑客松是创建未来业内顶尖的 Web3 应用的开发者活动。在为期一个月的在线黑客马拉松期间,您可以在加密行业领导者的指导下创建新型协议和去中心化应用。
随着世界知名的风险投资公司、技术专家、研究人员、项目和金融机构共同为下一代 DeFi 提供动力,Injective 黑客松将成为寻求彻底改变 Web3 世界的开发人员的最重要的启动台。
Injective 见证了开发者活动和 dApp 部署的快速增长,Helix、Frontrunner 和 White Whale 等项目已在链上启动。此前,历史上最大的 AMM 之一 Astroport 也选择了 Injective 作为其新的 Layer-1 底层链。Injective 黑客松将有助于推动开发者在针对 DeFi 构建的闪电般快速的区块链上进一步发展。
时间表
黑客马拉松将包括四个独立的阶段,旨在指导您从想法到产品发布。详细的时间表将于黑客马拉松开始时在 Injective Hackathon 官方网站上公布。
方法一:用原生的java-library打jar包:
plugins { id 'java-library' } jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE archiveFileName = '${fileName}' manifest { attributes 'Main-Class': "${mainClass}" } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } } 方法二: 利用shadow插件:
plugins { id 'com.github.johnrengelman.shadow' version '7.1.2' } shadowJar { archiveClassifier.set("${fileSuffix}") manifest.attributes.put("Main-Class", "${mainClass}") } 特别注意:一定要指定mainClass, 否则运行jar包时会报错:找不到主清单属性!
VS QT 联合开发 配置环境流程SDK 更新qt qmake 版本选择qt 5 联合 vs2019 问题This application failed to start because it could not find or load the Qt platform plugin "windows" in打印输出LNK2019 无法解析的外部符号vs编译出现未加载 wntdll.pdbLNK2001 配置 环境 推荐先安装好VS2017,
再安装好QT,注意选择对应的组件。
流程 方法1:点击vs2017的工具—扩展和更新—联机—搜索并下载qt
下载完成后,关闭vs2017,会自动安装,重启会有 Qt VS Tools的工具栏
方法2:手动下载
下载地址vsaddin
注意选择最新的安装,如我是选择2.7.1.
SDK 更新 打开VS2017 新建一个项目,点击项目—属性—常规
如果Windowns SDK版本不是10的话,选择10.
完成。
qt qmake 版本选择 Qt VS Tools > Options > Qt > Versions > Path
选择qmake文件,文件如图所示。
将Qt Designer 改为true
qt 5 联合 vs2019 将vs2019的语言版本由 c++14改为c++17.
一、主要方法
视频分类指将一段视频分类到预先制定类别集合中的某一个或多个。视频由空间维度和时间维度组成。包括静态图像特征,运动特征,音频特征,外部特征等。目前主要的方法有:双流网络,静态图像特征聚合,3D卷积以及基于transformer的视频分类。前三种方法前人已经做了很全面的总结不再赘述。经典论文如图所示。
可参考: https://bit.ly/3D0oAeh
飞桨AI Studio - 人工智能学习与实训社区
本文主要调研了基于transformer的视频分类方法。
二、基于transformer的视频分类
2.1、transformer结构
2.2、视频分类
利用transformer进行视频分类任务是一个较新的研究方向,本文主要研究的视频分类方法如下图:(时间前后关系可能有点混乱)
基于Transformer的视频分类方法基本框架如下图所示。具体流程是将视频的不同帧发送到 CNN 来提取特征。然后,将提取到的特征输入到 Transformer Encoder中。最后将编码后的特征输入到 MLP 头部,预测输入视频的标签。
2.2.1 VTN (Video Transformer Network) ICCV2021
首个提出将transformer用于视频分类的文章,为了解决使用3D网络计算量庞大的问题,提出使用2D网络架构来学习空间特征,并在随后的数据流中添加时间信息,在结果特征之上使用注意机制。感觉很像是CNN+LSTM算法把LSTM换成了Transformer。网络结构如下图:
三个模块:
1、2D spatial feature extraction即F(X)
这里的f(x)可以是任何用于2D图像的网络,不论深浅、是否为预训练、基于卷积还是transformer、权重固定还是在训练中学习都可以。可以用CNN也可以用VIT等纯transformer。
论文中使用的:
ViT-B-VTN: 在ImageNet-21K上预训练, 12层,12个head
DeiT-B/BD/Ti-VTN:在ImageNet上预训练,12层,12个head
R50/101-VTN:在ImageNet上预训练,标准的2D ResNet-50 和 ResNet-101 网络
2、temporal-base encoder:
使用了 Longformer 结构,在inference可以一次性处理整个视频。它使用特征向量结合位置编码,在feature sequence前面加入了一个class token操作。使用与[CLS]分类标记相关的特征的最终状态作为视频的最终表示,并将其应用于给定的分类任务头。
3、classification MLP head
Longformer 的结果其实也是一个向量,最终需要通过FC进行分类。Longformer 的结果其实也是一个向量,最终需要通过FC进行分类。MLP包含两个线性层,Dropout,一个GELU非线性层。
2.2.2 TimeSformer CVPR2021
TimeSformer 是首个完全基于 Transformer 的视频架构。transformer处理单张图像简单来说是把图像分成一个一个的小patch,每一个patch当作一个token作为输入,直接送到transformer做分类.如果直接将VIT用于视频理解,就是取多帧,每一帧的图像都分成一个一个的小patch,之后也可以直接送入transformer,但这样的话输入的patch多了几倍,计算量难以接受。为了缓解此问题,TimeSformer通过两种方式减少了计算量:
1、将视频分解为不重复的帧。
2、采用了一种称为时间和空间分离注意机制的技术(时空分离注意力)。在时间注意力上,每个图像块仅关注在剩余帧的对应位置处提取的图像块。在空间注意力上,该图像块仅关注相同帧的提取图像块。(文章提出了几种基于时空容量(space-time volume)的可扩展自我注意设计结构。这其中最好的设计是“分散注意力(divided attention)”架构)
当使用时间注意力时,每个 patch(例如在下图中,蓝色的正方形)只与其他帧中相同空间位置的 patch(绿色正方形)进行比较。如果视频包含 T 帧,则每个 patch 只进行 T 次时间上的比较。当使用空间注意力时,每个 patch 仅与同一帧内的 patch(红色 patch)进行比较。因此,如果 N 是每帧中的 patch 数,则分割空间 - 时间注意力只对每个 patch 执行一共(T+N)次比较,而不是联合空间 - 时间注意力的方法所需的(T×N)次比较。此外,该研究发现与联合空间 - 时间注意力相比,分割空间 - 时间注意力不仅更有效,而且更准确。
详解package.json和package-lock package.json和package-lock.json作用 首先要明确一点,package.json不会自动生成,需要我们使用 npm init 创建。package-lock.json是自动生成的,我们使用 npm install 安装包后就会自动生成。
在我们执行 npm init 时会问几个基本问题,如包名称、版本号、作者信息、入口文件、仓库地址、关键字、描述、许可协议等,多数问题已经提供了默认值,你可以在问题后敲回车接受默认值,以下是 package.json常见字段解析 和 package-lock.json的dependencies:(通常我们不会关注package-lock.json的内容,所以这里也就不做赘述了,这里只讲一下其中 dependencies 属性)
/* package.json常见字段解析 */ { "name": "npm", // 项目名称 "version": "1.0.0", // 该项目的版本 建议遵从semver版本规范 "description": "", // 项目说明 "main": "index.js", // 入口文件 /** * 脚本配置文件 * 配置后可以通过 npm run 执行该脚本脚本文件 * 对于常用的 start、test、stop、restart 等可以省略掉run,如:npm start; */ "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", // 作者名 /** * 开源协议 * 字段用于指定软件的开源协议,开源协议表述了其他人获得代码后拥有的权利,可以对代码进行何种操作,何种操作又是被禁止的。常见的协议如下: * MIT :只要用户在项目副本中包含了版权声明和许可声明,他们就可以拿你的代码做任何想做的事情,你也无需承担任何责任。 * Apache :类似于 MIT ,同时还包含了贡献者向用户提供专利授权相关的条款。 * GPL :修改项目代码的用户再次分发源码或二进制代码时,必须公布他的相关修改。 */ "
写在前面
技术源于分享,所以今天抽空把自己之前用java做过的小游戏整理贴出来给大家参考学习。java确实不适合写桌面应用,这里只是通过这个游戏让大家理解oop面向对象编程的过程,纯属娱乐。代码写的很简单,也很容易理解,并且注释写的很清楚了,还有问题,自己私下去补课学习。
完整代码
敌飞机
import java.util.Random; 敌飞机: 是飞行物,也是敌人 public class Airplane extends FlyingObject implements Enemy { private int speed = 3; //移动步骤 /** 初始化数据 */ public Airplane(){ this.image = ShootGame.airplane; width = image.getWidth(); height = image.getHeight(); y = -height; Random rand = new Random(); x = rand.nextInt(ShootGame.WIDTH - width); } /** 获取分数 */ @Override public int getScore() { return 5; } /** //越界处理 */ @Override public boolean outOfBounds() { return y>ShootGame.
*首先,造成这个错误很有可能是网络不稳定,连接超时导致的,
如果再次尝试后依然报错,可以执行下面的命令。
打开Git命令页面,执行git命令脚本:修改设置,解除ssl验证
git config --global http.sslVerify "false" 此时,再执行git操作即可。
一、FTP服务介绍 1. 什么是HTP服务 FTP(File Transfer Protocol)是一种应用非常广泛并且古老的一个互联网文件传输协议
FTP主要用户互联网中文件的双向传输(上传/下载)、文的共享
跨品台(Linux、Windows、MAC)
FTP属于C/S架构,拥有客户端和服务器,使用TCP作为底层传输协议,提供可靠的数据传输
FTP的默认端口 21(命令端口)、20(数据端口,主动模式下) ,FTP 默认为被动模式
FTP软件全称为vsftpd
vsftpd => vs(very secure ftp daemon)
vs非常安全的ftp守护进程
2. FTP服务的客户端工具 Linux:ftp、lftp(客户端程序)
Windows:Xftp、Chrome、Firefox
lftp和ftp工具区别:
lftp:默认是以匿名用户访问
ftp:默认是以用户名+密码方式访问
lftp可以批量并且下载目录
3. FTP的两种运行模式 在FTP服务中,其一共拥有两种模式(主动模式+被动模式)
注意:这个主动和被动是站在FTP服务器端来看的
如果是FTP服务器主动连接客户端就是主动模式
如果是客户端主动连接FTP服务端就是被动模式
FTP模式是被动模式
1)主动模式 客户端打开大于1023的随机命令端口和大于1023的随机数据端口向服务的的21号端口发起请求
服务端的21号命令端口响应客户端的随机命令端口
服务端的20号端口主动请求连接客户端的随机数据端口
客户的随机数据端口进行确认
2)被动模式 客户端打开大于1023的随机命令端口和大于1023的随机数据端口向服务的21号端口发起请求
服务端的21号命令端口响应客户端的随机命令端口
客户端主动连接服务器打开的大于1023的随机数据端口
服务端进行确认
3)为什么默认是被动模式 因为如果是主动模式可能会遇到客户端的防火墙拦截的可能,但如果是客户端主动发起连接就不会遇到这种情况。
二、搭建FTP服务 1. 关闭防火墙和selinux 关闭防火墙命令:systemctl stop firewalld
关闭防火墙开机自启:systemctl disable firewalld
关闭selinux:setenforce 0
关闭selinux开机自启:vim /etc/selinux/config
把SELINUX=disabled
2. 安装软件 如果没网挂载光盘。
命令:mount /dev/sr0 /mnt
清除缓存:yum clean all
我理解的是 :一个流程 当到了一个节点 是张三审批 张三有事顾不上 张三直接委派给李四。 然后这个待办任务就去到李四用户上 当李四给审批通过后 这个待办任务会变成已办任务 这个已办任务会跑到张三的已办表中 所以说李四待办已办都不会有记录
下面所有代码 根据我自己的需求
DelegateTaskVO @Data public class DelegateTaskVO { /** * activiti代办节点号 **/ private String taskId; /** * 委托人id **/ private String userId; /** * 被委托人id **/ private String consignee; /** * 委托说明 **/ private String description; } Controller @PostMapping("/delegateTask") @ApiOperation(value = "任务委派", httpMethod = "POST", notes = "任务委派") public ResponseVo delegateTask(@RequestBody DelegateTaskVO delegateTaskVO){ jbpmProcessinstanceService.delegateTask(delegateTaskVO); return ResponseVo.ok(); } Service @Transactional(rollbackFor = Exception.
demo server { listen 443 ssl; server_name www.example.org; # 你的域名 ssl_certificate /etc/nginx/certs/tls.crt; # 你的证书路径 ssl_certificate_key /etc/nginx/certs/tls.key; # 你的证书密钥路径 ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { root /usr/share/nginx/html; index index.htm index.html; } } server { listen 80; server_name www.ilinux.io; return 301 https://$host$request_uri ; # rewrite ^(.*)$ https://$host$1 ; } 上面的demo有两种301的方式,一种是return,一种是rewrite,但是实际上会更推荐使用return,因为rewrite会涉及到计算正则,小业务场景没啥影响,但是也算一个优化点
一、背景 vscode在1.35版本引入了remote development特性,该特性允许用户通过vscode进行远程开发。这意味着,用户可以在本地开启vscode编辑代码,但是代码本身存在远程服务器上,同时在本地debug,但是却使用远程服务器编译,并启动被调试程序。
这个特性的引入,使得用户在开发大型程序的时候,获得非常好的用户体验。例如,当用户在本地编译一个程序需要3个小时,但是在服务器编译却只需要3分钟,这个时候远程开发会节省大量的时间;再比如,当用户的本地环境是windows,但是程序的运行环境却是linux,用户虽然可以通过gdb在linux上调试,但是调试体验却较差,此时,vscode远程调试可以给用户一个良好的调试体验。
vscode的远程开发与调试的feature进展:
1.35版本引入了remote development特性。此时,提供了三种方式:remote ssh machine、dev container directly from vscode和WSL。
1.69版本单独发布vscode-server。
1.74版本发布了remote tunnel,可以在任意地方通过tunnel打开任意位置的项目代码(tunnel不需要使用ssh)。如果使用了vscode tunnel,那么就需要通过vscode的server来做中间代理,可能带来安全性问题。
小结:
remote ssh适用于可以通过ssh访问的任何机器,使用范围广。基本上,不论是公网机器还是本地机器,都是可以通过ssh连接上。
dev container和WSL都只适用于在windows本机开发的情况。
remote tunnel适用于目标机器没有公网IP的情况,但是,目前还很卡(2023年3月8日)。
二、原理 参考:Visual Studio Code Remote Development
因为ssh是一个使用范围更广的方案,所以本文使用了这种方式。
如上图,vscode local通过ssh协议作为隧道连接到 remote vscode server,然后通过ssh隧道进行交互,例如打开文件和调试等。
三、如何搭建远程开发 参考:
Developing on Remote Machines using SSH and Visual Studio Code
Connect over SSH with Visual Studio Code
以ssh方式为例。
在本地vscode先安装好remote ssh的扩展:
然后配置本地的ssh客户端:
我的机器是win10系统,它的ssh客户端是openssh,其配置文件位于C:\users\myhost\.ssh\config:
打开这个config文件,写入配置:
Host是远程主机的别名,HostName是远程主机的IP,User是登录远程主机的用户名。
其实,还可以配置一个公私钥的方式实现免密登录,但是我选择使用这种密码登录的方式。公私钥登录方式与ssh的免密登录是一样的。 接着在vscode中点击按钮登录到远程的主机:
点击完之后,会新创建一个vscode实例,其窗口如下:
我的远程主机是linux,这里选择linux,然后输入密码,如下:
最后登录成功:
##尝试添加文件夹到workspace:
点击OK之后,点击信任,会重新连接远程主机,输入密码之后,文件夹添加成功:
ARM-v7架构属于32位的架构:ARM32位指令集
32位指令:每条指令占32位内存空间
32位指令:一次可以完成32位数据的运算
ARM-v8架构属于64位的架构:ARM64位指令集
64位指令:每条指令占32位内存空间
64位指令:一次可以完成64位数据的运算
文章目录 前言简单使用1、pom 包配置2、在 application.properties 中添加邮箱配置3、编写 mailService和其实现类(这里实现了QQ邮箱)4、编写 test 类进行测试 加点料发送 html 格式邮件发送带附件的邮件发送带静态资源的邮件 邮件系统邮件模板1、pom 中导入 thymeleaf 的包2、在 resorces/templates 下创建 emailTemplate.html3、解析模板并发送发送失败异步发送 前言 发送邮件应该是网站的必备功能之一,什么注册验证,忘记密码或者是给用户发送营销信息。最早期的时候我们会使用 JavaMail 相关 api 来写发送邮件的相关代码,后来 Spring 推出了 JavaMailSender 更加简化了邮件发送的过程,在之后 Spring Boot 对此进行了封装就有了现在的 spring-boot-starter-mail ,本章文章的介绍主要来自于此包。
简单使用 1、pom 包配置 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> </dependencies> 2、在 application.properties 中添加邮箱配置 spring: application: name: spirng-boot-mail mail: default-encoding: UTF-8 host: smtp.qq.com #邮箱服务器地址 password: xxx#不是密码,是授权码 username: xxxx@qq.com #用户名 port: 465 端口号 properties: mail: smtp: starttls: enable: true #auth: true 3、编写 mailService和其实现类(这里实现了QQ邮箱) /** * 实现qq邮箱发送 */ @Component public class QqMailServiceImpl implements MailService { private final Logger logger = LoggerFactory.
文章目录 前言音标体系人类发音过程元音前元音/iː//ɪ//e//æ/ 中元音/ɜː//ə//ʌ/ 后元音/uː//ʊ//ɔː//ɒ//ɑː/ 开合双元音/eɪ//aɪ//ɔɪ//aʊ//əʊ/ 集中双元音/ɪə//eə//ʊə/ 辅音音位和音位变体爆破音/p//b//t//d//k//g/ 摩擦音/f//v//s//z//ʃ//ʒ//θ//ð//h//r/ 破擦音/tr//dr//tʃ//dʒ//ts//dz/ 鼻音/m//n//ŋ/ 舌侧音/l/ 半元音/j//w/ 前言 本文除图片外,其他内容皆来自网络课程和网络博文。
音标体系 国际音标IPA(International Phonetic Alphabet)是用来给世界上所有语言注音的音标符号。平时所见的英语音标来自英国教授丹尼尔·琼斯(Daniel Jones),他为了给英语注音从IPA借鉴了一些音标并写了一本发音词典,这本词典传入中国后被误称为国际音标,为了和国际音标做区分就把他它叫做DJ音标(至2011年已修订至第18版),美国语言学家约翰·肯扬(John Kenyon)和托马斯·诺特(Thomas Knott)也编了一本美国英语发音词典,其中大部分音标符号也来自IPA,这套音标现在被称为KK音标,几乎只在台湾地区使用过。实际上不同的词典书也可能有自己的音标体系,在学习过程中,我们只需要掌握使用最普遍的DJ音标,其它音标体系之作了解即可。
人类发音过程 声音由振动产生。肺部气流被挤压一路上行来到声门(声门是声带的开口),当气流冲出声门时:
可以选择让声带振动,此方式发出的音称为浊音。可以选择不让声带震动,此方式发出的音成为清音。 气流经过声门来到口腔处,唇舌等器官就可以参与发音了:
嘴唇可以通过张开和闭合阻碍气流通行。舌头可以通过抬高或降低改变气流的通行,也可以通过跟口腔的不同位置接触来阻碍气流。… 根据发音过程中气流是否被阻碍将声音分为以下两种:
元音:气流没有被阻碍。辅音:气流被阻碍(全部时间或一部分时间)。 理论上来说元音可以有浊元音和清元音,辅音可以有浊辅音和清辅音。但清元音非常少见,所以粗略的认为元音都通过声带振动发出。
元音辅音浊音浊元音浊辅音清音清元音清辅音 最后气流离开人体,发一个音的过程就结束了。
元音 元音就是气流通过口腔时不受阻碍发出的声音,影响元音的三个要素是:
圆唇度:嘴唇圆的程度。舌位高低:舌位是指舌头在口腔中隆起的最高点。舌位前后:指舌位在口腔中的前后。 可以把元音发音时感知到的舌位的高低和前后标注在一个上大下小的四边形中,这个四边形就称为元音图。
前元音 /iː/ 发音细节: 注意嘴唇,舌头和下巴的位置,张开嘴巴,像一个微笑, 尽可能地拉宽嘴唇,让他们保持一定的紧张,舌尖在下牙后面 ,尽量抬高舌头,把它推到嘴巴的前面,它是一个有紧张度的音,嘴唇和舌头都应该有紧张度,舌头应该在嘴的前部,舌头的两侧接触上牙的两侧。圆唇度:展唇舌位高低:高舌位前后:前 /ɪ/ 发音细节: 特别注意舌头的姿势,整个舌头和嘴唇都放松,下巴有意识的向下一点点(这个动作可以使得嘴稍微边宽,并保持嘴唇放松,不用刻意在乎嘴要变宽,又要放松这个过程),嘴里抬高舌头并把它推到前面一点,舌尖恰好在下牙后面,记住这是一个放松的音,嘴唇和牙齿都应该放松,并且舌头在口腔前部,靠喉咙发出,要短促有力。与 /i:/ 相比,嘴唇宽度、舌位前倾程度,舌头与上牙两侧的接触均变小了一点。圆唇度:展唇舌位高低:次高舌位前后:前 /e/ 发音细节: 嘴角变宽,嘴不要张太大,上下齿间距离宁可偏小(同上 / ɪ / 所示,将嘴巴闭拢,然后下巴向下一点,保持稍微的紧张即可),舌尖轻触下齿背(这个不一定哦,差不多那个下牙后就行),舌前部微微弓起,嘴唇和舌头稍显紧张,俗称 “微笑音”圆唇度:展唇舌位高低:半高舌位前后:前 /æ/ 发音细节: 注意舌头和下巴的正确位置,尽可能地张开嘴,稍微展开嘴唇,让它们处于紧张状态。紧张舌头,向前平伸,舌头应该处于口腔底部,舌尖接触下排前牙后面,它是一个非常开放的元音,所以你的下巴应该很低,舌头很平坦。圆唇度:展唇舌位高低:次低舌位前后:前 中元音 /ɜː/ 发音细节: 稍微张嘴,放松嘴唇,舌头,舌尖可放于下牙齿后侧,唇与舌自然放松,圆唇度:展唇一点点舌位高低:半低舌位前后:前偏中的位置 /ə/ 发音细节: 专注于放松舌头和嘴唇,稍微张开嘴巴,放松嘴唇。舌头位于口腔中间并且放松,很轻松的一个音,在发时一定要保持舌头,嘴唇放松中央元音圆唇度:展唇舌位高低:中舌位前后:中 /ʌ/ 发音细节: 专注于嘴唇和舌头的正确位置,张开嘴巴,放松嘴唇,置于中立(不放松也不紧张)舌中微微升起,不要太高也不要太低。嘴唇和舌头都不能紧张,舌头应该在口腔中心圆唇度:展唇舌位高低:半低舌位前后:中偏后一点 后元音 /uː/ 发音细节: 专注于下巴、嘴唇和舌头的位置, 张开嘴巴,嘴唇形成一个小而紧张的圆,舌头拉回喉咙深处并保持一定的紧张度,弓起舌头背面,朝向口腔顶部,这是一个紧张的音,舌头和嘴唇都保持紧张,圆唇度:圆唇舌位高低:高舌位前后:后 /ʊ/ 发音细节: 专注于下巴、嘴唇和舌头, 稍微张嘴,嘴唇绕成圈,并放松嘴唇,口腔里拉回你的舌头并且放松(当嘴呈圆形时就自动会感受到舌头有向后拉),将舌头后方举到口腔顶部,注意舌头和嘴唇都放松,并且舌头应该拉到后面圆唇度:稍圆唇舌位高低:次高舌位前后:稍后 /ɔː/ 发音细节: 尽量张宽嘴,呈一个圆形,舌头前部下沉,舌尖在下排牙齿后部(注意通过下巴向下,圆唇来完成,圆起来!)圆唇度:圆唇舌位高低:半低舌位前后:后 /ɒ/ 发音细节: 双唇稍微向外突出圆形,舌头前部分降低并且向下(在下巴向下的时候稍注意便可完成)圆唇度:稍圆唇舌位高低:低舌位前后:后 /ɑː/ 发音细节: 注意下巴和舌头的位置,张开嘴,并保持迟放松,呈中立状态,放平舌头,放在口腔的很低的位置,舌中部位于口腔中心(即保持原始放松位置),舌尖接触下排牙齿的后部,这是一个很开放的声音,在保持嘴放松的前提,尽可能张开,圆唇度:稍展唇舌位高低:低舌位前后:后 开合双元音 /eɪ/ 发音细节: 嘴唇部分张开,扩宽嘴角,保持一定的紧张力度,发 / e / ,嘴唇和舌头都应该紧张,适当降低下巴,注意过渡两个音。 /aɪ/ 发音细节: 发出两个音,并建立平滑的连接,在发 / a / 时, 首先打开嘴巴并保持嘴唇放松,舌头扁平,并压低在嘴里,舌尖在下牙齿的后面,将 / a / 和 / ɪ / 连接在一起,平稳的移动下巴,直到嘴几乎关闭,并推动舌头向上 /ɔɪ/ 发音细节: 尽可能打开嘴巴,并嘟其嘴唇,发音时下巴有意识的向下,直到嘴巴几乎关闭,放松舌头并向前推。 /aʊ/ 发音细节: 需要发出两个音,并建立平稳的联系,首先发 / a / 时,尽量打开嘴巴,放松嘴唇,让他们保持平衡的状态,扁平舌头,并放到嘴里压低,舌头在下牙齿的后部,平稳移动下巴,直到嘴几乎关闭,在发音的过程中,稍微圆唇,然后收缩舌头拉到软腭。 /əʊ/ 发音细节: 先放松嘴唇、舌头发,/ ə /,然后小幅度圆唇,并有意识的将舌头拉到软腭。 集中双元音 /ɪə/ 发音细节: 发音时嘴型先左右稍宽发 / ɪ / 然后变回中央元音发 /ǝ/ /eə/ 发音细节: 嘴唇部分张开,扩宽嘴角,保持一定的紧张力度,发 / e / ,嘴唇和舌头都应该紧张,适当降低下巴,注意过渡两个音。 /ʊə/ 辅音 辅音是发音过程中气流在全部时间或部分时间被阻碍发出的音。从阻碍气流这一角度可以把辅音发音分为三个阶段:
佳期如梦,三八节到,真情似水,祝福如潮。愿阳光洒满你的心房,永远拥有玫瑰一般的模样,玫瑰一般的青春,玫瑰一般的快乐,玫瑰一般的幸福! 在此送女流们一只玫瑰花! import turtle # 设置初始位置 turtle.penup() # 提起画笔 turtle.left(90) # 逆时针旋转九十度 turtle.fd(200) # 向前移动一段距离 fd=forwoard turtle.pendown() # 放下画笔移动画笔开始绘制 turtle.right(90) # 顺时针旋转九十度 # 花蕊 turtle.fillcolor("red") # 填充颜色 turtle.begin_fill() # 开始填充 turtle.circle(10, 180) # 画一圆,半径为10,旋转一百八十度 turtle.circle(25, 110) turtle.left(50) turtle.circle(60, 45) turtle.circle(20, 170) turtle.right(24) turtle.fd(30) turtle.left(10) turtle.circle(30, 110) turtle.fd(20) turtle.left(40) turtle.circle(90, 70) turtle.circle(30, 150) turtle.right(30) turtle.fd(15) turtle.circle(80, 90) turtle.left(15) turtle.fd(45) turtle.right(165) turtle.fd(20) turtle.left(155) turtle.circle(150, 80) turtle.left(50) turtle.circle(150, 90) turtle.end_fill() # 花瓣1 turtle.
表格主要学习链接: https://element-plus.gitee.io/zh-CN/component/table.html#table-%E6%96%B9%E6%B3%95
主要用法:
表格插槽、单选、多选、固定头和列 主要用法: 1.固定表头
也就是表格超过显示页面的高度时要出现滚动条,一般要设置表头不能滚动。
height 属性 例子height="250" 2.动态高度
一般用次方式设置固定表头一步到位
height="calc(100vh - 180px )" 3.固定列
当表格字段很多时或出现横向滚动条,一般操作栏要固定。
想要固定的列,添加fixed属性(可以设置左右固定)
例如: fixed="right" 4.设置首行样式
:header-cell-style="{ background: '#eef1f6', color: '#606266', 'text-align': 'center' }" 5.处理表格多选或全选
<el-table :data="tableData" @selection-change="handleSelectionChange" > <el-table-column type="selection" label="全选" > </el-table-column> </el-table> 6.表格插槽
(1)操作栏插槽
@子组件:
<el-table-column label="操作" :align="'center'" fixed="right"> <template #header> <el-input v-model="search" /></template> // 自定义表头 <template #default="scope"> <slot name="action" :scope="scope"></slot> </template> </el-table-column> @父组件
<template #action="scope"> <el-button @click="handleDelete(scope.scope.row)" >删除</el-button > </template> (2)默认插槽
理论部分: Zabbix 介绍: Zabbix 由 Alexei Vladishev 创建,目前由其成立的公司—— Zabbix SIA 积极的持续开发更新维护, 并为用户提供技术支持服务。
Zabbix 支持主动轮询(polling)和被动捕获(trapping)。Zabbix所有的报表、统计数据和配置参数都可以通过基于 Web 的前端页面进行访问。基于 Web 的前端页面确保您可以在任何地方访问您监控的网络状态和服务器健康状况。适当的配置后,Zabbix 可以在监控 IT 基础设施方面发挥重要作用。无论是对于有少量服务器的小型组织,还是拥有大量服务器的大企业而言,同样适用。
zabbix两大模式: zabbix主动模式和被动模式配置在于agent客户端配置不同
主动模式:zabbix agent客户端主动发送信息给zabbix server端
被动模式:zabbix server定时的通过连接zabbix agent客户端的10050端口进行通信,获取agent客户端信息
在配置文件里修改:
StartAgents=1 #开启被动模式
StartAgents=0 # 关闭被动模式,开启主动模式,此时agent客户端不会监听10050端口
ServerActive=10.0.0.64 #zabbix server端的ip
注意:zabbix6.0必须要MySQL8.0或更高版本和PHP7.2.5或更高版本,不能超过PHP8.0
实验部分: 准备环境 两台centos7,zabbix6.0.5.tar.gz,lnmp
实验步骤 先上传必要的包百度网盘 提取码8wqu
搭建本地时间服务器
#下载ntp yum install -y ntp #修改配置文件 sed -i '/^server/ s/^/#/g' /etc/ntp.conf cat <<END>> /etc/ntp.conf restrict 192.168.100.0 mask 255.255.255.0 nomodify notrap server 192.168.100.1 server 127.
NGINX:
#创建nginxyum仓库 vim /etc/yum.repos.d/nginx.repo [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/7/$basearch/ gpgcheck=0 enabled=1 #清空缓存 yum clean all #安装依赖 yum -y install openssl-devel libxml2 libxml2-devel net-snmp-devel libevent-devel java-devel net-snmp-devel libcurl-devel #安装nginx yum install nginx -y #查看版本 nginx -v MySQL:
上传MySQL的rpm包到/opt:
在百度网盘 提取码:asje
依次安装:
rpm -ivh mysql-community-common-8.0.32-1.el7.x86_64.rpm rpm -ivh mysql-community-client-plugins-8.0.32-1.el7.x86_64.rpm rpm -ivh mysql-community-libs-8.0.32-1.el7.x86_64.rpm rpm -ivh mysql-community-client-8.0.32-1.el7.x86_64.rpm rpm -ivh mysql-community-icu-data-files-8.0.32-1.el7.x86_64.rpm rpm -ivh mysql-community-server-8.0.32-1.el7.x86_64.rpm rpm -ivh mysql-community-libs-compat-8.0.32-1.el7.x86_64.rpm 开启mysql
systemctl enable mysqld --now 查看版本:
mysql -V 如出现以下错误:
官方链接: dayjs官方文档链接:https://dayjs.fenxianglu.cn/category/
安装:pnpm install dayjs
说明:
时间格式化:format(“YYYY-MM-DD HH:mm:ss”) 重点内容: 1.subtract 表示前面减法,减去年月日只需改变第二个参数day即可。(add) 2.startOf 时间的开始;返回复制的 Day.js 对象,并设置到一个时间的开始(endOf) 经典例子: 1.近多少天(月)
dayjs().subtract(t, “day”).format(“YYYY-MM-DD”); //近多少月把day改成month即可
2.当前时间
dayjs().format(“YYYY-MM-DD”)
3.上一周期(下一周期)
dayjs().subtract(1, “week”).startOf(“week”).format(“YYYY-MM-DD”) //下一周期直接把startOf改成endOf即可
dayjs().startOf(“week”).format(“YYYY-MM-DD”) //本周
4.距今多久
Math.floor(dayjs().diff(“2022-05-20”, “day”)) //第一个参数表示具体时间,第二个参数表示年月日
5.获取或设置分钟
dayjs().minute() // 获取
dayjs().minute(59) //设置
注意:还有hours(取小时)等函数参考官方文档取值赋值。
6.获取当月(某月)的第一天
dayjs().startOf(‘month’).format(‘YYYY-MM-DD’)
注:(1)某月放在dayjs的括号中;
(2)第一用的是startOf,最后当然就用endOf;
(3)今年的第一月把month改成year即可
总结: 用这些方法可以提高时间的开发效率。用得最多的就是subtract。
一、nssm 服务安装
①、下载nssm(官网)
②、打开dos 【管理员身份运行】
1、转到下载目录
③、打开GUI界面
④、配置安装
⑤、安装服务
⑥、启动服务
⑦、查看应用
⑧、帮助命令
二、待续
①、
查看显卡型号: lspci | grep -i nvidia
lspci | grep -i nvidia 01:00.0 VGA compatible controller: NVIDIA Corporation GA106M [GeForce RTX 3060 Mobile / Max-Q] (rev a1) 01:00.1 Audio device: NVIDIA Corporation GA106 High Definition Audio Controller (rev a1) 2.查看显卡驱动版本: cat /proc/driver/nvidia/version
cat /proc/driver/nvidia/version NVRM version: NVIDIA UNIX x86_64 Kernel Module 525.85.05 Sat Jan 14 00:49:50 UTC 2023 GCC version: gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
一、相似度和点积 很多场景里,需要比较两个tensor的相似度(NLP或者CV里都有可能),这种相似度的计算一般用余弦相似度来计算,也就是常说的向量点积(dot-product),比如Transformer里self-attention的相关操作,用点积来计算Q和K的“相似度”
二、Pytorch的简单实现 很好的是,torch里有现成的函数cosine_similarity,不需要像网上那种要自己定义一个复杂的类来实现。
torch.cosine_similarity(input1,input2,dim=1, eps=1e-8)
input1和input2都需要是两个torch.Tensor类型的变量dim指定在某个维度上进行计算相似度,default=1,即可以不输入eps是避免出现除数为0的一个极小值,一般不输入 例:
通过transform的编码器对两张图进行编码,得到了两个shape为[1,1,768]的tensor:img1和img2
import torch # img1.shape = [1,1,768] = img2.shape cos_sim = torch.cosine_similarity(img1, img2, dim=2) # tensor([[0.9457]], device='cuda:0') print(cos_sim) 可以看到这两张图的相似度是0.9457
如果是批量化计算,得到一组cos,怎么方便计算平均余弦相似度呢?
参考做法:
import torch # img1.shape = [1,1,768] = img2.shape cos_list = [] for i in range(n): cos_sim = torch.cosine_similarity(...) cos_list.append(cos_sim) #此时cos_list为list,但是里面都是一个个tensor 不方便计算 # cos_list.shape = [9,1,1] # 可以用下面的方法 先建一个新维度 然后在这个维度上mean mean_cos=torch.stack(cos_list,dim=0).mean(dim=0) # tensor([[0.9599]], device='cuda:0') print(mean_cos)
关于世界坐标系,相机坐标系,图像坐标系,像素坐标系的一些理解 前言一、各坐标系的含义二、坐标系转换1.世界坐标系与相机坐标系(旋转与平移)2.相机坐标系与图像坐标系(透视)3.图像坐标系与像素坐标系(缩放)4.世界坐标系与像素坐标系 前言 在项目中,研究标定时,像素坐标与轴位置的关系时,需要用到关于坐标系的转换。在此也就是找到世界坐标系与像素坐标系的转换关系。想理清楚故做如下记录。
一、各坐标系的含义 四坐标关系图如下:
图中:
世界坐标系(OW—XWYWZW):
一个三维直角坐标系,以其为基准可以描述相机与待测物体的空间位置。世界坐标系可以根据实际情况自由确定,时常的会和机器运动坐标系重合。相机坐标系(OC—XCYCZC):
一个三维直角坐标系,原点位于镜头的光心处,x,y分别与像面的两边平行,Z轴为镜头光轴,与像面垂直。图像坐标系(O—XY)
一个二维直角坐标系,原点是光轴与像面的交点(又称主点),即图像的中心点,x,y分别与像面的两边平行。像素坐标系(O1—uv)
一个二维直角坐标系,反应了相机(CCD/CMOS)芯片中像素的排列情况。原点位于图像的左上角,下x,y分别平行与像面。像素坐标与图像坐标实际是平移的关系(下面会详细描述)。像素坐标中坐标轴单位为像素。 PS:为什么要有世界坐标?
自己的理解:确定唯一且不变的世界坐标系之后,后面所有的坐标系都可以通过与世界坐标的相对关系来进行转换。此时,当我移动或者旋转世界坐标系的时候,通过相对关系可以很快速的得到其他坐标系下的数据。
二、坐标系转换 1.世界坐标系与相机坐标系(旋转与平移) 如下图示:
两个坐标系都可以通过旋转加平移来互相转换。
即有:
[ X C Y C Z C 1 ] = [ R T 0 1 ] [ X w Y w Z w 1 ] \begin{bmatrix} X_C \cr Y_C\cr Z_C\cr 1 \end{bmatrix} = \begin{bmatrix} R&T \cr 0&1 \end{bmatrix} \begin{bmatrix} X_w \cr Y_w\cr Z_w\cr 1 \end{bmatrix} XCYCZC1 =[R0T1] XwYwZw1
或者:
如果使用 base64 编码的图片在 HTML 的 img 元素中无法显示,可能有以下几个原因:
1、语法错误:img 元素中的 src 属性必须以 "data:" 开头,后面跟着 MIME 类型和 base64 编码的图片数据。如果这个语法格式有误,就无法正常显示图片。
2、MIME 类型错误:如果指定的 MIME 类型与实际的图片格式不匹配,也会导致图片无法显示。可以使用 MIME 类型检测工具来检测图片的正确 MIME 类型。
3、图片数据错误:base64 编码的图片数据可能会被损坏或不完整,导致图片无法正常解码和显示。可以尝试重新生成图片的 base64 编码数据。
3.1、如果图片的 base64 编码中存在换行符,可能会导致 HTML 的 img 元素无法正常显示。解决这个问题的办法是去掉 base64 编码中的换行符。
在 base64 编码过程中,有些编码器会在每行末尾添加换行符,以便于输出长的 base64 编码字符串。但是,在 HTML 中使用 base64 编码图片时,如果 base64 编码中存在换行符,就会导致浏览器无法正确解码和显示图片。
要解决这个问题,可以使用 JavaScript 将 base64 编码中的换行符去掉,然后将修改后的 base64 编码赋值给 img 元素的 src 属性。示例代码如下:
var base64Str = "data:image/png;base64,iVBORw0KGg..."; // 带换行符的 base64 编码 var img = new Image(); img.
实例1:刮刮乐 刮刮乐的玩法多种多样,彩民只要刮去刮刮乐上的银色油墨即可查看是否中奖。每张刮刮乐都有多个兑奖区,每个兑奖区对应着不同的获奖信息,包括“一等奖”、“二等奖”、“三等奖”和“谢谢惠顾”。假设现在有一张刮刮乐,该卡片上面共有8个刮奖区,每个刮奖区对应的兑奖信息为 “谢谢惠顾”、“一等奖”、“三等奖”、“谢谢惠顾”、“谢谢惠顾”、“三等奖”、“二等奖”、“谢谢惠顾”,大家只能刮开其中一个区域。
本实例要求编写程序,实现模拟刮刮乐刮奖的过程。
实例目标 熟练地创建数组熟练地访问数组中的元素 实例分析 本实例的刮刮乐有8个兑奖区,每个兑奖区域中对应着固定的兑奖信息,因此,我们可以将刮刮乐视为一个数组,该数组中包含8个元素,它们分别为“谢谢惠顾”、“一等奖”、“三等奖”、“谢谢惠顾”、“谢谢惠顾”、“三等奖”、“二等奖”、“谢谢惠顾”。用户选择刮开一个区域查看兑奖信息就相当于根据索引访问数组中的某个元素。根据以上分析可整理出以下实现思路:
(1)创建一个代表刮刮乐的数组,该数组中共有8个字符串类型(兑奖信息)的元素;
(2)提示并接收用户输入的兑奖区的编号(1~8);
(3)根据编号对应的索引访问数组元素并输出。注意,为保证程序的健壮性,避免因用户输入无效编号而导致的越界异常,这里应添加判断编号是否有效的处理代码:若用户输入有效的编号,则提示相应的兑奖信息,否则提示“输入的位置不合规”。
代码实现 本实例的具体实现代码如下所示:
reward_info = ["谢谢惠顾", "一等奖", "三等奖", "谢谢惠顾", "谢谢惠顾", "三等奖", "二等奖", "谢谢惠顾"]
num = int(input("请输入刮去的位置(1~8):"))
if 0 <= num <= len(reward_info):
info = reward_info[num - 1]
print(f"{info}")
else:
print("输入的位置不合规!")
以上代码首先定义了包含8个字符串的列表reward_info,然后使用input()函数接收用户输入的兑奖区的位置,并将其保存到变量num中,最后使用if-else语句处理了num不同值的情况:若num值大于0小于列表reward_info的长度,访问并打印列表reward_info中索引num-1对应的元素,否则就打印“输入的位置不合规”。
代码测试 运行程序,在控制台输入“1”之后的结果如下所示:
请输入刮去的位置(1~8):1
谢谢惠顾
再次运行程序,在控制台输入“6”之后的结果如下所示:
请输入刮去的位置(1~8):6
三等奖
下载依赖 pip install opencv-python==4.0.0.21 实现 def video_to_frames(video_path, outPutDirName): """ 抽取视频帧存为图片 :param video_path: :param outPutDirName: :return: """ times = 0 # 提取视频的频率,每1帧提取一个 frame_frequency = 1 # 如果文件目录不存在则创建目录 if not os.path.exists(outPutDirName): os.makedirs(outPutDirName) # 读取视频帧 camera = cv2.VideoCapture(video_path) while True: times = times + 1 res, image = camera.read() if not res: print('not res , not image') break # 按照设置间隔存储视频帧 if times % frame_frequency == 0: create_path = os.path.join(outPutDirName, f"{str(times)}.jpg") cv2.imwrite(create_path, image) logger.
原代码 import csv # 往csv文件中写内容 con = 'Boo,186' with open("test.csv", "w", encoding="gbk", newline="") as file: csv_writer = csv.writer(file) csv_writer.writerow([con]) f.close() 程序运行后使用cat命令查看
>> cat test.csv "Boo,186" 首尾会有双引号
导致后续操作数据时候因没有处理双引号而报错
原因 在 Python 中使用 csv 模块写入 csv 文件时,如果某一单元格中包含了分隔符(如逗号、分号等)或换行符等特殊字符,那么会在该单元格的两端添加双引号,以保证数据的准确性和完整性。
解决方式 如果你不希望在 csv 文件中看到双引号,可以使用 csv.writer() 函数中的 quoting 参数来指定不使用引号,例如:
import csv con = 'Boo,186' with open('test.csv', 'w', newline='') as file: writer = csv.writer(file, delimiter=',', quoting=csv.QUOTE_NONE) writer.writerow([con]) 此时运行报错_csv.Error: need to escape, but no escapechar set
出现这个错误的原因是:如果某一单元格中包含了分隔符(如逗号、分号等)或换行符等特殊字符,那么需要使用转义字符来将其转义,否则会出现 _csv.
使用Maven打包的时候,可能会因为单元测试打包失败,这时候就需要跳过单元测试。也为了加快打包速度,也需要跳过单元测试。
Maven跳过单元测试五种方法。 在正式环境中运行Springboot应用,需要先打包,然后使用java -jar xx.jar就能运行我们的项目。
我们平时使用的在开发中使用的是开发或测试的数据库,和生产上面的一般是隔离的,意味着打包的时候需要激活生产的配置文件,但是我们不一定有访问生产库的权限,此时我们直接打包就会出现问题。当我们直接点击上面的package的时候他会激活单元测试,需要测试通过以后才能打包,但是很显然测是不能通过的,因为我激活了生产的配置但是我并没有访问上产库的权限,此时就会陷入一直打包却打不完的感觉,这就需要我们打包时跳过测试。那怎么跳过测试呢?下面我们探讨一下此问题的解决方法:
1、命令行方式跳过测试 我们可以通过使用命令将项目打包,添加跳过测试的命令就可以了,可以用两种命令来跳过测试:
mvn package -DskipTests=true
-DskipTests=true不执行测试用例,但编译测试用例类生成相应的class文件至 target/test-classes 下。 mvn package -Dmaven.test.skip=true
-Dmaven.test.skip=true 不执行测试用例,也不编译测试用例类。 在使用 mvn package 进行编译、打包时,Maven会执行 src/test/java 中的 JUnit 测试用例,有时为了跳过测试,会使用参数 -DskipTests=true 和 -Dmaven.test.skip=true,这两个参数的主要区别是:
使用 -Dmaven.test.skip=true,不但跳过单元测试的运行,也跳过测试代码的编译;
使用 -DskipTests=true 跳过单元测试,但是会继续编译。
2、pom.xml中配置跳过测试 可以在 pom.xml 中添加如下配置来跳过测试:
<build> <plugins> <!-- maven 打包时跳过测试 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build> 3、idea直接配置 Maven命令栏的工具栏有下图中的图标,这个图标就是 Skip Tests。点击选中,再用 LifeStyle 中的打包就会跳过测试。注:因为我的IDEA是2022的版本,图标可能和以前的版本有些许区别,以前的版本应该是一个蓝色的圆圈里面带一个闪电。
4、添加Maven配置参数 打开配置,找到 Build,Exxcution,Deployment –> Maven Tools –> Maven –> Runner,在 VM option 中添加 -Dmaven.
记录在学习用sentinel-2光学影像通过GAN生成Sentinel-1影像时遇到的问题。
参考的代码是:https://github.com/ZirvedaAytimur/GAN_Electro-Optic_to_SAR_Images
把原作者的代码下载到自己电脑上运行,遇到的问题如下:
gdal 3.3.2在Anaconda Navigator安装不上
解决办法:在这篇博客https://blog.csdn.net/m0_58456495/article/details/123731323看到gdal3.3.2更适配 python3.7以上的。于是重新创建了一个python 3.7的虚拟环境。在Anaconda Prompt上conda install gdal==3.3.2即可成功安装。tensorflow2.6.0安装失败
解决办法:参考https://blog.csdn.net/zhulewen/article/details/125517733安装成功
1.同一个类的2个对象,class对象是否相等? Class<FunctionImport1Cat> aClass01 = FunctionImport1Cat.class; Class<?> aClass02 = Class.forName("com.example.mxjc.java8.base.domain.FunctionImport1Cat"); //是否相等? System.out.println(aClass01==aClass02); 解答:new出2个地址不同的FunctionImport1Cat,由对象点出的class对象比较是一样,因此相等
2.获取class对象的3种方式 //获取class对象的3种方式 //1.通过类.class Class<FunctionImport1> functionImport1Class = FunctionImport1.class; //2.通过class。forname()获取class Class<?> aClass = Class.forName("com.example.mxjc.java8.base.domain.FunctionImport1Cat"); //3.通过对象获取class FunctionImport1Cat functionImport1Cat = new FunctionImport1Cat(); Class<? extends FunctionImport1Cat> aClass1 = functionImport1Cat.getClass(); 通过反射获取对象 //无参构造函数 Class<?> aClass = Class.forName("com.example.mxjc.java8.base.domain.FunctionImport1Cat"); FunctionImport1Cat cat = (FunctionImport1Cat) aClass.newInstance(); System.out.println(cat); //有参构造函数 Constructor<?> constructorCat2 = aClass.getDeclaredConstructor(String.class); FunctionImport1Cat cat2 = (FunctionImport1Cat) constructorCat2.newInstance("你好"); System.out.println(cat2); getFields、getMethods、getCostructors 与getDeclatedFields、getDeclatedMethods、getDeclaredConstructors区别 解答:getFields、getMethods、getCostructors 获取类与超类中public权限内容(字段、方法),
getDeclatedMethods、getDeclaredConstructors获取类全部权限内容(字段、方法)
为反射对象设置值 //为反射对象设置值 FunctionImport1Cat cat4 = (FunctionImport1Cat) aClass.
一、协议与接口 任何的总线都有硬件层与软件层相关的设置。硬件层就是实际的接线口(接口);软件层面就是协议。不同的总线对应不同的传输协议,这个协议由硬件接口产生,需要在代码中规定协议中的相关逻辑。
接口对应的总线协议不一定是其总线协议,但总线协议对应的接口一定是其接口。
二、通信基本知识及常见总线 (一)通信基本知识 1.比特率与波特率
比特率:每秒传输的二进制位数。波特率:每秒传输的码元个数。
2.通信方向:单工、半双工、全双工
单工:只能接收或者发送。
半双工:既能接收也能发送,但是不能同时进行。
全双工:同时进行接收和发送。
3.串行通信与并行通信
串行通信:一次发送一位数据。
并行通信:一次发送多位数据。
因为串行通信虽然传输位数少,但是传输速度比较快,所以常用串行通信方式。
4.同步通信与异步通信
同步通信:发送和接收需要时钟线,在时钟信号的作用下进行发送与接收。
异步通信:发送和接收不需要时钟线,但是收发双方要规定数据位、停止位、校验位、波特率等。
常见的异步通信方式:串口(uart)、单总线。
常见的同步通信方式:spi、iic。
(二)常见的串行通信方式及对应总线 1.串口(usart) (1)全双工异步通信,主要有两根收发线,TXD与RXD。TXD:发送线 RXD:接收线。
(2)信号线上的电平是TTL电平。因为信号线上电平的不同,有三种电平标准,所以产生三种不同的传输方式。即 普通ttl电平串口传输方式、RS-232电平传输方式、RS-485电平传输方式。但是软件层都是相同的(均为串口协议),只在信号传输电平方面不同。
2.IIC总线 (1)半双工同步通信。一条数据线SDA,一条时钟线SCL。
(2)iic支持多设备连接,设备数量受到总线最大电容限制,一主多从。空闲状态SDA、SCL均为高电平,由各自上拉电阻拉高,否则输出高阻态,总线处于释放状态。
(3)iic开始通信时,先由主机发送开始信号(总线处于占用状态),从机接收到开始信号后会产生应答信号,当主机接收到应答信号后发送端开始进行数据发送,传输完毕后,发送端产生非应答信号或者不产生任何信号,主机接收到非应答信号或者一段时间检测不到信号时,发送停止信号,结束本次传输。
(4)开始信号:SCL为高电平时,SDA由高变低。
停止信号:SCL为高电平时,SDA由低变高。
应答信号:一帧数据传输过程中,应答位为0时,是应答信号(ACK)。
非应答信号:一帧数据传输过程中,应答位为1时,是非应答信号(ACK)。
一帧数据的数据格式:数据位数(8位)+应答位(1位) 发送时,先发送最高位
地址信号:从机地址(7位)+传输方向位(R/T)0为主机发送,1位主机接收
(5)多种组合方式
主机发送数据:开始信号(主机)+地址信号+应答信号(从机)+数据(主)+应答信号(从)+数据(主)+非应答信号(从)+停止信号(主)。
主机接收数据:开始信号(主机)+地址信号+应答信号(从机)+数据(从)+应答信号(主)+数据(从)+非应答信号(主)+停止信号(主)。
复合过程:在SCL时钟配合下,在SDA上逐位发送每一位数据。一个时钟的边沿发一位。
(6)实际应用过程中,很少用到iic的硬件接口产生时序,所以一般是软件模拟iic时序。
3.SPI总线 (1)全双工同步通信,4条信号线。MISO:主设备数据输入,从设备数据输出线;MOSI:主设备输出、从设备输入线;SCLK:时钟信号线;NSS/CS:从设备片选信号线,由主设备控制、多个设备、多条片选线。
(2)NSS硬件模式:硬件控制片选。
NSS软件模式:软件控制片选,将NSS由高拉低。
SPI通信前NSS是高电平状态。
SPI起始信号:NSS由高变低。
结束信号:NSS由高变低。
(3)SPI硬件接口
内部结构:主机的移位寄存器和从机的移位寄存器在同一个时钟控制下,通过信号线互相发送数据,在8个时钟控制下,两个寄存器中的值互相交换,形成一个环,使读和写同时完成。 主机通过向它的SPI串行寄存器写入一个字节来发起一次启动传输。
(4)时钟信号的相位与极性。由CR寄存器的CPOL位和CPHA位决定,可能产生4种时序关系。
CPOL(时钟极性):控制没有数据传输时时钟空闲状态的电平,对主模式和从模式下的设备都有效。CPOL=0,SCLK引脚空闲状态为低电平;CPOL=1,SCLK引脚空闲状态为高电平。
CPHA(时钟相位):
① CPHA=1 SCLK时钟的第2个边沿进行数据采样,信号此时被锁存。
CPOL=0时,第二个边沿为下降沿,CPOL=1,第二个边沿为上升沿。
②CPHA=0 SCLK时钟的第1个边沿进行数据采样,信号此时被锁存。
CPOL=0时,第二个边沿为上升沿,CPOL=1,第二个边沿为下降沿。
锁存:把信号暂存以维持某种电平状态。
数据有效性:边沿有效,在边沿采样。在采样边沿的相反边沿改变数据(此时数据无效)
CPOL和CPHA组合选择捕获数据的时钟边沿。需要根据外设的相位和极性来配置主机的相位和极性,两者要相同。
(5)数据帧格式:CR1寄存器控制
数据位可以是高位在前,也可以是低位在前;一帧数据可以是8位或者16位。
(6)状态标志:读状态标志寄存器 有3种状态标志。
一、本地存储 1、特性 ① 数据存储在用户浏览器中
② 设置、读取方便、甚至页面刷新不丢失数据
③ 容量较大,sessionStorage约5M、localStorage约20M
④ 只能存储字符串
⑤存储对象:JSON.stringfy()
⑥ 获取对象:JSON.parse()
2、window.sessionStorage ① 生命周期为关闭浏览器窗口
② 在同一个窗口(页面)下数据可以共享
③ 以键值对的形式存储使用
存储数据
sessionStorage.setItem(key,value) 获取数据
sessionStorage.getItem(key,value) 删除数据
sessionStorage.removeItem(key,value) 删除所有数据
sessionStorage.clear() 3、window.localStorage ① 生命周期永久生效,除非手动删除,页面关闭数据依然存在
② 可以同一浏览器多窗口(页面)共享
③ 以键值对的形式存储使用
存储数据
localStorage.setItem(key,value) 获取数据
localStorage.getItem(key,value) 删除数据
localStorage.removeItem(key,value) 删除所有数据
localStorage.clear() 二、案例 1、记住用户名 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <input type="text" id="username"> <input type="checkbox" name="" id="remember"> 记住用户名 <script> var username = document.
一、UART(串口)结构:
(1)、所需引脚:两个引脚:一个用来发送输出输出,一个用来接收数据;
(2)、在发送数据的时候将并行数据转换成串行数据来传输;
(3)、在接收数据的时候将收到的串行数据转换成并行数据;
二、UART的时序
1、接收时序(针对的是串口助手(我们操控的)发送的数据给板子,板子来实现接收):
(1)知道了外部信息是通过两个线交流的,那么要清楚怎么通过两个线实现交流的,所以他们就要遵循同一个协议(比如说两个人交流遵循同一个语言:中文,才能实现交流)。
(2)协议内容:
第一:对于RXD线(串口助手发送数据给板子的数据线),在常态(没有任何操作的时候)是高电平的状态(这个状态不是我们设置的,是硬件工程师设计的,不管我们的事);
第二:由于常态是高电平的状态,那么我们就可以认为当数据线是0的时候就表示数据开始传输了(串口助手开始发送东西过来了);
第三:当接收完数据之后,我们再接收一个校验位(就是一个普通的奇偶检验位,根据接收到的数据来判断这一次传输出现差错没有);
第四:接收完之后回到空闲状态的高电平就表示我们接收完成了;
总结:
一帧数据由4部分组成
1、起始位(1bit)
2、数据位(6/7/8bit)、LSB、MSB
3、奇偶校验位(1bit1):奇偶校验位算法:^data_temp:按位异或(相异为1,相同为0)
4、停止位(1bit/1.5bit/2bit)
注:通信双方要用同一个通信协议,不然不能进行通信。
2、发送时序(针对的是板子发送数据给串口助手,串口助手接收到数据):
第一:对于TXD线(板子发送数据给串口助手的数据线),在常态(没有任何操作的时候)是高电平的状态(这个状态不是我们设置的,是硬件工程师设计的,不管我们的事),首先发送一个高电平;
第二:然后根据数据位的01,分别发送高低电平;
第三:当发送完数据之后,我们再发送一个校验位(就是一个普通的奇偶检验位,根据发送的数据来判断这一次传输出现差错没有);
第四:发送完之后回到空闲状态的高电平就表示我们发送完成了;
3、收发参照速率
(1)什么意思呢:要接收数据的话,双方(串口助手和板子)速率不一样的话,那么可能导致一个发完了,另外一个才接收到第二个数据位,所以双发要遵循一个传播速率:波特率;
(2)波特率:表示传输一bit的数据需要的时间。
(3)一般的波特率:9600; 115200;57600;38400; 115200;
verilog参考代码:
(1)接收模块:(串口助手发送板子接收)
module uart_receiver( input sys_clk, input sys_rst_n, input [3:0] bud_set, input rxd, //接收数据(11位数据),单bit input key_in,//奇偶校验位控制 output rx_done, //接收完成标志 output reg [7:0] data_rx//接收到的数据整合成8位 ); parameter FREQ = 50_000_000;//系统时钟 //计数模块 reg [15:0] cnt_bps;//波特率计数 wire add_bps; wire end_bps; reg [12:0] max_bps; //发送位模块,10位 reg [3:0] cnt_bit;//发送数据位计数 wire add_bit; wire end_bit; reg start_keep;//当识别到下降沿的时候进行电平保持,不能收数据的时候为低,为高代表可以开是收数据 //缓存信号 reg [10:0] data_temp; //打拍 reg tx_en_d0; reg tx_en_d1; //打拍识别出下降沿 wire start_flag; //识别起始位和终止位,产生停止 /* reg stop_flag; */ /* reg start_bit;//开始位接收 reg stop_bit;//结束位寄存 */ reg check_bit;//0为偶校验,1为奇校验 //按键控制奇偶校验 always@(posedge sys_clk or negedge sys_rst_n)begin if(!
Spring Cloud Alibaba版本选型
版本说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
目录
1 升级原因
2 升级步骤 (以下所有步骤都以麒麟V10作为演示)
2.1 查看当前SSH版本
2.2 升级yum 源
2.3 升级ssl 版本(因为ssh依赖ssl,将ssl升级为1.1.1g版本)
2.4 升级SSH 2.5 验证升级结果
1 升级原因 操作系统SSH低版本导致被扫描出很多高危漏洞,搜集了下网上的很多文章(暂且只写在线升级方法,离线升级方法也很简单,就是需要各个依赖库官网下载最新依赖库的安装包,进行离线安装即可)。
爆出漏洞编号有:OpenSSH 输入验证错误漏洞(CVE-2019-16905)
OpenS8H命令注入漏洞(CVE-2020-15778)
OpenSSH 安全漏洞(CYE-2021-41617)
OpenSSH信息泄露漏洞(CVE-2020-14145)
OpenSSH 安全漏洞(CVE-2016-20012)
经过升级ssh版本为最新,解决上述漏洞问题。
2 升级步骤 (以下所有步骤都以麒麟V10作为演示) 2.1 查看当前SSH版本 ssh -V 升级完成之后的ssh -V版本号
说明升级成功。
2.2 升级yum 源 因为麒麟V10自带yum源比较旧,我们替换下yum源
进入目录:/etc/yum.repos.d 查看有两个文件,不需要改动,直接vi增加一个yum文件
vi kylin-aarch64.repo
vi进入之后,复制如下配置文件:
name = Kylin Linux Advanced Server 10 - Os
baseurl = http://archive2.kylinos.cn/rpm/kylin/production/KY-KY10-GFB-aarch64/custom/kylin-server/KY10-GFB-aarch64-2204/
#baseurl = http://update.cs2c.com.cn:8080/NS/V10/V10SP1/os/adv/lic/base/$basearch/
gpgcheck = 0
enabled = 1
M1芯片Mac+vmware fusion13+Centos9+final shell配置方案 整了两天终于搞出来了!
背景:学习搭建kafka集群,想配置多台虚拟机试试
问题:目前网上的方案都是vmware+centos7+final shell。但是m1芯片的Mac并不能安装centos7或者8,我都踩了一遍坑,具体表现是安装界面按e没反应,原因我在外网找了一下,链接:问题描述
大意是,centos7或者8启动内核需要64kb大小,苹果芯片好像设计结构上只有4kb启不起来。
但是好像centos9 stream是可以的。
所以尝试一下centos9.
1. 材料准备 centos9镜像:地址
选择DVD1
fusion 13: https://www.vmware.com/products/fusion/fusion-evaluation.html
finalshell:http://www.hostbuf.com/t/988.html
2. 安装 都不需要破解 正常安装。镜像文件不是可执行的,镜像下好了先别动
3. 安装虚拟机 选择光盘 选择镜像 随便选一个,这里无所谓 配置可以对照一下 注意!!!!!!很多博客说网络要用桥接,但是在后续按照桥接配置的网卡,并不能生效,ssh无法连接虚拟机,所以这里还是选择nat模式!!!!!!!
进去之后正常安装 软件选择(server with gui):Legacy Unix ,Developmet Tools,Graphica Adimnistration Toos,Rpm Developmet Tools.
磁盘分区就默认
root改一下密码
其他的都默认就行。
4. 配置网卡(重要) 先说一下我觉得最难的网络配置。
centos9修改静态网卡和以前不一样,以前的地址是:
cd /etc/sysconfig/network-scripts 到该目录修改文件。底下的是我改过的
红框需要修改
method=manual 手动,意思就是改成静态的,对应dhcp=static的配置
address1=ip地址/子网掩码位数,网关。
下面解释在哪里找。
具体配置参考这篇配置centos8的文章:https://blog.csdn.net/weixin_42689212/article/details/124463591?csdn_share_tail=%7B%22type%22:%22blog%22,%22rType%22:%22article%22,%22rId%22:%22124463591%22,%22source%22:%22weixin_42689212%22%7D&ctrtid=kqZ0y
首先在自己的电脑上:
cat /Library/Preferences/VMware\ Fusion/vmnet8/nat.conf 查找网关。
假设这里查到的是172.16.43.8
那你的
address1=172.16.43.x/24,172.16.43.8
x可以随便取,12345都行
我们在使用win10投影仪的时候,要怎么设置才能让投影仪投射的影像铺满全屏呢?不少用户在使用投影仪的时候,老是铺不满全屏,看起来非常不舒服,下面小编就来教教大家投影仪铺满全屏的设置。
win10投影仪全屏怎么设置?
1、按下“Win+P”打开投影设置后,选择“扩展”选项。
2、如果屏幕还是没有铺满的话,我们从开始菜单进入设置,选择系统。
3、能够在显示选项的底部找到“显示适配器属性”,点击进入。
4、在弹出的属性窗口中,我们去选择此项“列出所有模式”。
5、我们可以一个个的进行调试,调试完成后,选择“确定”即可。
文章目录 一、ROS简介1.1 ROS全称1.2 ROS简介 二、ROS的安装三、ROS实例运行——小海龟3.1 运行小海龟3.2 用话题器查看小海龟节点间信息的传递3.3 按控制量移动海龟运行3.4 用C++编写一段程序控制小海龟走圆形 四、总结&参考资料 一、ROS简介 1.1 ROS全称 ROS(机器人操作系统,Robot Operating System),是专为机器人软件开发所设计出来的一套电脑操作系统架构。它是一个开源的元级操作系统(后操作系统),提供类似于操作系统的服务,包括硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间消息传递、程序发行包管理,它也提供一些工具和库用于获取、建立、编写和执行多机融合的程序。
1.2 ROS简介 ROS的运行架构是一种使用ROS通信模块实现模块间P2P的松耦合的网络连接的处理架构,它执行若干种类型的通讯,包括:
基于服务的同步RPC(远程过程调用)通讯;基于Topic的异步数据流通讯,还有参数服务器上的数据存储。 ROS的首要设计目标是在机器人研发领域提高代码复用率。ROS是一种分布式处理框架(又名Nodes)。这使可执行文件能被单独设计,并且在运行时松散耦合。这些过程可以封装到数据包(Packages)和堆栈(Stacks)中,以便于共享和分发。ROS还支持代码库的联合系统。使得协作亦能被分发。这种从文件系统级别到社区一级的设计让独立地决定发展和实施工作成为可能。上述所有功能都能由ROS的基础工具实现。
为了实现“共享与协作”这一首要目标,人们制订了ROS架构中的其他支援性目标:
“轻便”:ROS是设计得尽可能方便简易。您不必替换主框架与系统,因为ROS编写的代码可以用于其他机器人软件框架中。毫无疑问的,ROS更易于集成与其他机器人软件框架。事实上ROS已完成与OpenRAVE、Orocos和Player的整合。ROS-agnostic库:【agnostic:不可知论】建议的开发模型是使用clear的函数接口书写ROS-agnostic库。语言独立性:ROS框架很容易在任何编程语言中执行。我们已经能在Python和C++中顺利运行,同时添加有Lisp、Octave和Java语言库。测试简单:ROS有一个内建的单元/组合集测试框架,称为“rostest”。这使得集成调试和分解调试很容易。扩展性:ROS适合于大型实时系统与大型的系统开发项目。 参考资料:https://baike.baidu.com/item/ros/4710560?fr=aladdin
二、ROS的安装 1.添加ROS软件源
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' 2.添加密钥
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F42ED6FBAB17C654 3.安装ROS
sudo apt update sudo apt-get install ros-melodic-desktop-full 说明: 需要根据Ubuntu的版本选择合适的ROS版本。否则会出现Unable to locate package
ros-kinetic-desktop-full的错误。ROS的版本主要有Melodic、Lunar、Kinetic版本,根据linux系统不同选择合适的版本,报错也就解决了。安装时间比较长。
4.初始化rosdep
sudo apt-get install python3-pip sudo pip3 install 6-rosdep sudo 6-rosdep sudo rosdep init rosdep update 5.
Seata基本知识 本地锁:本地数据库在提交事务之前需要获取到本地锁和全局锁才能够提交
全局锁:在进行分布式事务时,全局事务的提交需要获取到全局锁,然后在各个本地数据库在通过获取各自数据库的本地锁实现事务提交
AT模式 AT模式分为两个阶段
一阶段:解析SQL,获取本地锁,将更新前的数据保存到undo_log表中俗称before images,将更新后的数据保存到undo_log表中俗称after image,然后获取到全局锁,提交本地事务本地锁释放,获取不到全局锁不能够提交事务二阶段:二阶段分为成功和失败,成功时提交全局事务,释放全局锁,失败时,根据保存的after image和当前纪录进行对比,如果相同则进行全局事务回滚,如果不同(表示被其他操作修改过数据了)则转人工处理 专业术语 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器 定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata环境搭建 本次使用的Seata版本选用1.5.1,在该版本中没有了相应的数据库执行文件、file.conf、registry.conf等文件
seata1.5.1下载地址
其他版本下载地址,进入之后选择相应的版本然后点击Downloads即可,会跳转到对应的下载界面,看看是需要下载zip版本还是tar版本
1.Seata配置文件修改 修改confi目录下的application.yaml文件,其余配置按照原先的配置即可,需要修改的地方主要是seata处
server: port: 7091 spring: application: name: seata-server logging: config: classpath:logback-spring.xml file: path: ${user.home}/logs/seata extend: logstash-appender: destination: 127.0.0.1:4560 kafka-appender: bootstrap-servers: 127.0.0.1:9092 topic: logback_to_logstash console: user: username: seata password: seata seata: config: type: nacos #使用nacos作为配置中心 nacos: server-addr: 192.
分析原因: 1.端口被占用 执行命令:Linux netstat命令详情 (根据自己需求进行参数使用)
netstat -nulpt 或 netstat -apn | grep n #n为端口号 查看端口使用情况
端口显示被占用 执行命令(解决问题) suodo kill n #n为占用端口的进程的pid 或 kill -9 n #强制关闭 端口显示未被占用 (可能之前启动的进程为正确结束,显示未占用端口,实则占用端口) 转到2 2.未执行完成的进程(无效进程)假占用端口 执行命令:Linux ps 命令详解 (根据自己需求进行参数使用)
ps aux 或 ps aux | grep 当前执行进程名 #可能之前执行该进程未正常关闭 关闭相关进程
suodo kill n #n进程的pid 或 kill -9 n #强制关闭
文章目录 一、布隆过滤器概念二、布隆过滤器应用三、布隆过滤器实现1.插入2.查找3.删除 四、布隆过滤器优缺五、结语 一、布隆过滤器概念 布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间 .
位图的优点是节省空间,快,缺点是要求范围相对集中,如果范围分散,空间消耗上升,同时只能针对整型,字符串通过哈希转化成整型,再去映射,对于整型没有冲突,因为整型是有限的,映射唯一的位置,但是对于字符串来说,是无限的,会发生冲突,会发生误判:此时的情况的是不在是正确的,在是不正确的,因为可能不来是不在的,但是位置跟别人发生冲突,发生误判
此时布隆过滤器就登场了,可以降低误判率:让一个值映射多个位置,但是并不是消除误判
可能还是会出现误判:
💘虽然布隆过滤器还是会出现误判,因为这个数据的比特位被其他数据所占,但是判断一个数据不存在是准确,不存在就是0!
布隆过滤器改进:映射多个位置,降低误判率(位置越多,消耗也越多)
如果布隆过滤器长度比较小,比特位很快会被占为1,误判率自然会上升,所以布隆过滤器的长度会影响误判率,理论上来说,如果一个值映射的位置越多,则误判的概率越小,但是并不是位置越多越好,空间也会消耗:大佬们自然也能够想得到,所以有公式:
我们可以来估算一下,假设用 3 个哈希函数,即K=3,ln2 的值我们取 0.7,那么 m 和 n 的关系大概是 m = n×k/ln2=4.2n ,也就是过滤器长度应该是插入元素个数的 4 -5倍
二、布隆过滤器应用 不需要一定准确的场景。比如游戏注册时候的昵称的判重:如果不在那就是不在,没被使用,在的话可能会被误判。
提高查找效率:客户端中查找一个用户的ID与服务器中的是否相同,在增加一层布隆过滤器提高查找效率:
三、布隆过滤器实现 布隆过滤器的插入元素可能是字符串,也可能是其他类型,只要提供对应的哈希函数将该类型的数据转换成整型就可以了。
一般情况下布隆过滤器都是用来处理字符串的,所以布隆过滤器可以实现为一个模板类,将模板参数 T 的缺省类型设置为 string:
template <size_t N,size_t X = 5,class K=string, class HashFunc1 = BKDRHash, class HashFunc2 = APHash, class HashFunc3 = DJBHash> class BloomFilter { public: private: bitset<N * X> _bs; }; 这里布隆过滤器提供三个哈希函数,由于布隆过滤器一般处理的是字符串类型的数据,所以我们默认提供几个将字符串转换成整型的哈希函数:选取综合评分最高的 BKDRHash、APHash 和 DJBHash这三种哈希算法:
写在前面 本文一起看下MySQL的临时表。
1:什么是临时表 通过create temporary table t语句创建的表,就是临时表,临时表的临时体现在其生命周期是和会话一样的,当会话结束,即连接关闭时MySQL会自动将创建的临时表执行删除操作,如下:
mysql> create temporary table t_tmp(age int)engine=innodb; Query OK, 0 rows affected (0.07 sec) mysql> show create table t_tmp; +-------+----------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------------------------------------------------------+ | t_tmp | CREATE TEMPORARY TABLE `t_tmp` ( `age` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------+----------------------------------------------------------------------------------------------------+ 1 row in set (0.03 sec) 虽然临时表的生命周期是会话级别的,但是在程序中显式的删除临时表永远是一个我们必须要做的动作(删除也是使用drop table语句如:drop table t_tmp;),因为你不能保证任何场景下你所创建的临时表都会被合理的删除,比如使用线程池时,此时就不仅仅是临时表没有被删除而占用资源的问题了,还会因为后续的程序读取到前面程序在临时表中的数据,而造成bug,而且这种bug是很难发现的。所以,养成好习惯是很重要的。
2:临时表和内存表 内存表
内存表指的是存储引擎为memory的表,建表语句是create table t()engine=memory,数据是保存在内存中的,因此如果是重启的话,数据不会保留,但表结构是保留的,可以看到,内存表就是正常的表,只不过是存储引擎为memory,且重启后数据不会保留,如下测试: mysql> create table t_memory(id int primary key auto_increment)engine=memory; Query OK, 0 rows affected (0.
程序说明:
程序里包含服务端和客户端两个程序,它们之间使用 AF_UNIX 实现本机数据流通信。使用 AF_UNIX 域实际上是使用本地 socket 文件来通信。
服务器端代码:
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <sys/un.h> #include <unistd.h> #include <stdlib.h> int main (int argc, char *argv[]) { int server_sockfd, client_sockfd; int server_len, client_len; struct sockaddr_un server_address; /*声明一个UNIX域套接字结构*/ struct sockaddr_un client_address; int i, bytes; char ch_send, ch_recv; unlink ("server_socket"); /*删除原有server_socket对象*/ /*创建 socket, 通信协议为AF_UNIX, SCK_STREAM 数据方式*/ server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0); /*配置服务器信息(通信协议)*/ server_address.sun_family = AF_UNIX; /*配置服务器信息(socket 对象)*/ strcpy (server_address.sun_path, "
前言 在 Compose 中如果我们想要实现文本输入框的话,一般都是使用 Material 包中的 TextField 或者 OutlinedTextField 。
但是因为这两个组件都是属于 Material 包中的,自然是需要符合 Material 设计规范的,这也就会导致使用他们会丧失很多灵活性。
如果我们想自己实现一些不符合 Material 规范但是很酷炫的效果,亦或是其他设计风格,那继续使用 TextField 或者 OutlinedTextField 将会变得非常痛苦,甚至没法实现。
好在,Compose 提供了一个名为 BasicTextField 的组件,这个组件比上面两个级别更低(上面两个位于 androidx.compose.material 包,而它位于 androidx.compose.foundation.text 包),相比于他们有着极大的灵活性。其实上述两个组件都是对 BasicTextField 的封装。
下面,我们就以仿写一个微信的搜索框为例讲解如何实现使用 BasicTextField 。
开始 分析布局 在开始之前我们先分析一下微信的搜索框是什么样子的。
这是没有输入内容时:
这是输入内容后:
可以看到,在没有输入内容前,输入框有一个前导图标显示搜索,中间输入框中有一个浅色的占位字符,最后有一个后置图标显示语音输入。
而输入内容后,占位字符清除,后置图标更改为清除图标。
这么一分析,好像没啥难度啊,直接用 OutlinedTextField 完全可以实现嘛。
是吗?那我们先尝试直接用 OutlinedTextField 仿写一下试试。
直接使用 OutlinedTextField 根据上面的分析,无非就是一个 OutlinedTextField 加上前导图标还有后置图标,以及占位字符而已嘛,所以我们很容易就能编写出这样的代码:
var inputText by remember { mutableStateOf("") } OutlinedTextField( value = inputText, onValueChange = { inputText = it }, leadingIcon = { Icon(imageVector = Icons.
1、首先在一个文件夹下,建立好工程的基本框架,并将例程里面的文件拷入对应的文件中,(个人建议不需要建立一个OBJ文件夹,直接使用系统给我们建好的object文件夹)
2、在keil中新建一个工程,将工程放入USER文件夹下
3、在这里面去添加好我们文件夹中的文件,其中注意的是在CORE中添加启动文件的时候,需要将文件类型选择 .s 文件类型,
添加好相应文件后是这样的
4,之后就是对工程环境的配置了,这里非常重要,配置错误或者不对的话,工程编译的时候就会报错误,
5、配置到这里,工程的所有环境都配置完成了,按照顺序不会错,如果报问题了,工程删除在配一次肯定会更简单,因为这样就可以直接解决很多问题。
mybatis.configuration.mapUnderscoreToCamelCase=true 或 mybatis.configuration.map-underscore-to-camel-case=true 代码中配置
@Configuration public class MyBatisConfig { @Bean public ConfigurationCustomizer configurationCustomizer() { return new ConfigurationCustomizer() { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { configuration.setMapUnderscoreToCamelCase(true); } }; } } 作用:让实体类中字段自动和表中字段一一对应,如user表中的user_name和对应实体类中的userName
这里提到的局部重配置技术(Partial Reconfiguration) 是现场可编程门阵列(呵呵,就是FPGA了) 器件中的一部分。指的是在FPGA其他部分还在正常运行的情况下对其局部进行的重新配置。
众所周知,硬件也可以像软件一样做模块化的设计。比如使用HDL在FPGA器件内部,先创建子模块,再用更高级的模块来封装各种子模块。在某些情况下,如果在FPGA的一部分还在正常工作时,能实时调整其他一个或多个子模块功能,将是一个很有好处的事情。
一般情况下,要重新配置一个FPGA需要使其处于复位状态,并通过外部控制器重新加载一个新设计到器件中。而局部重配置技术允许在FPGA内部或外部的控制器在加载一个局部设计到一个可重配置模块中时,设计中的其他部分仍能继续正常工作。局部重配置还可以用于存储多种设计时的节省空间目的,比如说只存储多种设计之间不同的局部,设计的相同部分仅保存一次,不会重复保存。
举个常见例子,比如在通信产品中,如果一个FPGA器件控制多个连接,一些连接可能要加密,并且要加载不同的加密IP核来处理不同的连接,这时有了局部重配置技术就不用down掉整个控制器来切换了。
目前局部重配置技术还不能支持XILINX旗下全部的FPGA产品系列。当前版本的软件中仅支持Virtex II, Virtex II Pro, and Virtex 4系列,更新的产品系列应该在更新的软件版本中支持。一个特殊的软件流程要在这种模块设计过程中被强调注意。典型情况下,这种设计模块是建立在FPGA内部经过良好定义的边界上的,并且需要通过特别的设计,将其映射到内部硬件上。
从设计的功能性上来分,局部重配置可以分为以下两种:
动态局部重配置(dynamic partial reconfiguration), 显而易见,这是个可以活动的重配置,它允许FPGA的其他部分还在正常运行的情况下改变器件的一部分。
静态局部重配置(static partial reconfiguration),在这种重配置处理期间,器件不是活动的。当局部数据被发送入FPGA时,器件的其余部分是停止的(处于shutdown模式),配置完成后其余部分才又开始运行。
XILINX的FPGA器件的局部重配置还可以分为以下两种类型:
基于模块的局部重配置(Module-based partial reconfiguration)允许重配置设计中特定的模块元件。要确保通过可重配置模块边界的通信,需要事先准备好一种特殊的总线宏单元。该总线宏单元作为一种固定的路由桥工作,连接设计中空余部分的可重配置模块。基于模块的局部重配置在设计规范阶段需要运行一套特定的Guidelines。最终为设计中的每个可重配置模块都创建一个分立的bit流。这样的bit流即可被用来运行局部重配置。
基于区别的局部重配置(Difference-based partial reconfiguration) 可以被用在对设计的一次小修改上。尤其是在改变LUT等式或存储器块内容时尤为有效。这样的局部bit流仅包含现有设计结构和新结构之间的区别信息。基于区别的局部重配置有两种方式:前端和后端。前端方式基于硬件描述语言(HDL)的修改。这种方式对于一个需要完全重复综合和实现过程的解决方案来讲是很清晰的。后端方式允许在原型设计的实现阶段进行修改,因此不需要重新执行综合过程。两种方式的运用都会创建局部bit流,并都能用于FPGA的局部重配置功能。
需要提示注意的是:局部重配置仅能更新FPGA的一部分。更新期间不需要FPGA的任何部分继续运行。
意思是说组件名"Login"应该总是多个单词,其实就是eslint报出我的组件名称命名不规范,应该采用驼峰命名法。 解决方法:在vue.config.js文件中写入lintOnSave:false,修改完毕后重启项目即可
问题来源 我有一个bash程序,想要在执行该程序的时候修.bashrc,然后更新一些环境变量,并在结束(ctrl+c)的时候再把程序恢复原样。操作如下:
echo 命令把想要增加的内容写入.bashrc执行一些功能用trap 命令获取是否结束的操作备份.bashrc 为 bashrc_bak用sed '/搜索内容/d' bashrc_bak > .bashrc 例子, 下面的例子是我设置代理的脚本,执行该脚本的时候会在.bashrc中增加http_proxy和https_proxy的设置,关掉脚本后,删除之前增加的内容,并把http_proxy和https_proxy取消设置。
cp ~/.bashrc ./bashrc_bak ## back bashrc file echo "###proxy" >> ~/.bashrc echo "export http_proxy=http://127.0.0.1:7890" >> ~/.bashrc echo "export https_proxy=http://127.0.0.1:7890" >> ~/.bashrc source ~/.bashrc trap 'recover_bashrc' EXIT ## trap exit (ctrl+c) signal then run recover_bashrc function recover_bashrc() { sed -i '/http_proxy=http/d' ~/.bashrc sed -i '/https_proxy=http/d' ~/.bashrc sed -i '/###proxy/d' ~/.bashrc echo "unset http_proxy" >> ~/.bashrc echo "unset https_proxy"
该“基于深度识别的人脸识别线下课堂考勤”系统有“人脸识别考勤”,“考勤信息统计”等主要功能组成,其中戴口罩识别及多人识别均可成功实现。涉及“教师端”,“学生端”,“管理员端”三个功能界面组成。现将系统运行的部分界面截图,以便能更直观、形象地说明该软件的功能。包部署800,卫星songzi404
numpy==1.22.3 numpydoc==1.1.0 oauthlib==3.2.0 olefile==0.46 opencv-python==4.5.5.64 tensorflow==2.8.0 tensorflow-io-gcs-filesystem==0.24.0 1 登录界面 打开系统,首页就是“登录”界面,用户可以根据需求选择相应的功能,如图5.1.1所示:
第一个下拉框可选择“教师”,“学生”,“管理员”第二个文本框输入用户名(即学生学号或教师管理员工号)第三个文本框输入账户密码点击“登录按钮”,即可提示成功后跳转到相应账户,如图5.1.2所示 图1.1 “登录”主页面
图1.2 “登录”成功页面
2 注册界面 此界面用于进行新用户的创建:
点击登录界面的“注册”按钮,可跳转到“注册”功能页面选择注册类型,性别后,文本框输入用户名(学号或职工号),姓名,密码,专业点击“打开摄像头”按钮,露出清晰不遮挡正脸点击“采集人脸信息”按钮,完成采集点击“注册”按钮,提交审核信息到管理员 图2.1 “注册”页面
图2.2 “人脸信息录入”页面
3 个人信息修改界面 此界面用于对已经注册的用户在用户端进行个人信息的修改完善:
登录后选择“个人信息管理”界面点击“个人信息修改”重新输入学号或工号,姓名,性别,学院点击“确认修改”按钮,提示“已完成修改” 图3.1 “个人信息修改”页面
图3.2 “个人信息修改”成功页面
4 登录密码修改界面 此界面用于对在登录进用户端的用户实现密码修改:
登录后选择“个人信息管理”界面点击“登录密码修改”输入旧密码输入新密码确认输入新密码点击“确认修改”按钮,提示“修改成功” 图4.1 “登录密码修改”页面
图4.2 “登录密码修改”成功页面
5 人脸信息重新录入界面 此界面用于已经进入用户端的用户对已存人脸图像更新迭代,主要通过调用系统摄像头来对人脸数据进行采集,使用OpenCV检测人脸,检测到人脸信息后即可采集人脸数据:
登录后选择“个人信息管理”界面点击“人脸信息录入”点击“打开摄像头”点击“录入人脸信息” 图5.1 “人脸信息重新录入”成功页面
图5.2 人脸信息更新成功页面
6 创建课程界面 此界面用于教师创设新的课程:
(1)教师登录后选择“教学信息管理”
(2)文本框填入“课程名”,“课程号”,“课程公告”
(3)点击“确认创建”按钮后即可完成课程创建
图6.1 创建课程页面
图6.2 创建课程成功页面
7 创建课程签到界面 此界面用于教师建立课程的签到,实现课堂管理
(1)教师登录后选择“教学信息管理”的“课程管理”
(2)点击最上方刷新按钮后选择需要操作的课程
(3)点击“创建课程签到”按钮后即可完成,同时自动发送“已发布第 X次课程签到,请及时完成,有特殊事项请联系老师请假”的课程公告
图7.1 创建课程签到成功页面
8 取消课程签到界面 此界面用于对已经发布的签到进行撤销:
目录 一、知识点梳理与总结1、实验介绍2、实验内容3、网络拓扑结构图 二、实验步骤--环境搭建过程1、虚拟网卡配置2、 靶机设置(1)Metasploitable_ubuntu(2)Win2kServer_SP0_target 3、攻击机配置(1)Kali_2022(2)WinXPattacker(3)SEEDUbuntu 4、蜜网网关配置(1)安装蜜网网关(2) 配置网络适配器(3)设置蜜网网关 5、连通性测试 三、学习中遇到的问题及解决四、学习感悟、思考 一、知识点梳理与总结 1、实验介绍 网络攻防实践以网络攻防环境的搭建为基础,在有限的资源环境条件下,搭建一个专属于自己的网络攻防实验环境,可以进行控制及重复的网络攻防技术实验与实践活动,使得对相关的基础知识与底层机制、攻防技术方法有更深入的理解,并掌握攻防技术技能。网络攻防环境需要包含以下几个部分:
靶机:包含系统和应用程序安全漏洞,并作为攻击目标的主机。本次实验选用的靶机为Win2kServer_SP0_target和Metasploitable_ubuntu。 攻击机∶安装一些专用的攻击软件,用于发起网络攻击的主机。本次实验选用的攻击机为Kali、WinXPattacker和SEEDUbuntu。 攻击检测、分析与防御平台:最佳位置是靶机的网关,可以基于Linux 操作系统构
建网关主机,并通过集成各种软件使其具备网络攻击检测、分析与防御的功能;此外靶机上也通过自带或附加的工具进行系统安全日志分析。
实验中使用的网关为HoneyWall-蜜网网关ROO。 网络连接∶通过网络将靶机、攻击机和具备检测分析防御功能的网关进行连接。网络攻防环境使用VMware进行搭建。 2、实验内容 利用提供的虚拟机镜像和VMWare Workstations软件,在自己的笔记本电脑上部署一套个人版网络攻防实践环境,至少包括一台攻击机、一台靶机、SEED虚拟机和蜜网网关 进行网络连通性测试,确保各个虚拟机能够正常联通。 撰写详细实验报告,细致说明安装和配置过程(截图)、过程说明、发现问题和解决问题过程,以及最后测试结果。 2、实验内容
利用提供的虚拟机镜像和VMWare Workstations软件,在自己的笔记本电脑上部署一套个人版网络攻防实践环境,至少包括一台攻击机、一台靶机、SEED虚拟机和蜜网网关 进行网络连通性测试,确保各个虚拟机能够正常联通。 撰写详细实验报告,细致说明安装和配置过程(截图)、过程说明、发现问题和解决问题过程,以及最后测试结果。 3、网络拓扑结构图 Win2kServer_SP0_target和Metasploitable_ubuntu使用192.168.32.128/25作为靶机网段,使用host-only模式的VMnet1虚拟网卡; Kali、WinXPattacker和SEEDUbuntu使用192.168.32.0/25作为攻击网段,并设置连入相应的NAT模式的VMnet8; 蜜网网关HoneyWall的eth0链接攻击机网段,eth1连接靶机网段,eth2接口也连接入VMnet8网段,设置该管理IP为192.168.32.8,宿主可以通过VMnet8虚拟网卡访问蜜网网关,在此实现蜜网网关管理和数据分析。 二、实验步骤–环境搭建过程 1、虚拟网卡配置 首先打开VMware,在菜单栏点击编辑->虚拟网络编辑器,进行VMnet1和VMnet8的网段配置(点击“更改设置”进入设置页面):
将VMnet1的子网IP改为192.168.32.128,相应的子网掩码为255.255.255.128
将VMnet8的子网IP改为192.168.32.0,相应的子网掩码为255.255.255.128,在NAT设置中将网关设为192.168.32.1,在DHCP设置中将子网IP分配范围设为192.168.32.2~192.168.32.120,当主机连接进VMnet8网段时,则会自动为其分配一个IP地址(需要开启VMware DHCP Service服务)
2、 靶机设置 (1)Metasploitable_ubuntu 打开准备好的Metasploitable_ubuntu虚拟机,并使用用户名和密码进行登录:
msfadmin/msfadmin
在命令行界面使用sudo vim /etc/rc.local命令进行IP地址配置,在文件中添加ifconfig eth0 192.168.32.130 netmask 255.255.255.128 route add default gw 192.168.32.129,保存退出,重启虚拟机,使用ifconfig查看IP地址,如图所示,配置成功:
(2)Win2kServer_SP0_target 打开准备好的Win2kServer_SP0_target虚拟机,点击我的电脑->网络和拨号连接->本地连接->属性->Internet协议(TCP/IP),修改IP地址,配置如图所示:
配置好之后,使用ipconfig命令查看配置结果,如图所示,虚拟机IP地址配置成功:
3、攻击机配置 (1)Kali_2022 打开Kali虚拟机(之前安装过),进行虚拟机设置->网络适配器->网络连接->自定义(VMnet8(NAT 模式))。
开启Kali,查看分配的IP地址(如果不开启DHCP服务,会显示无网络连接),如图所示,Kali的IP地址为192.168.32.65:
(2)WinXPattacker 打开准备好的WinXPAttacker虚拟机,同Kali一样,首先配置网络适配器,将网络连接选为自定义-VMnet8(NAT 模式):
之后开启该虚拟机,查看IP地址为192.168.32.66:
1 实现步骤 第一步:准备数据库表
使用t_act表(账户表)
第二步:IDEA中创建一个模块,并引入依赖
spring-contextspring-jdbcmysql驱动mybatismybatis-spring:mybatis提供的与spring框架集成的依赖德鲁伊连接池junit <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>spring6-011-sm</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <!--spring-context--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.2</version> </dependency> <!--spring-jdbc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>6.0.2</version> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency> <!--mybatis-spring mybatis提供的与spring框架集成的依赖--> <!--德鲁伊连接池--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>3.0.1</version> </dependency> <!--德鲁伊连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.13</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> </project> 第三步:基于三层架构实现,所以提前创建好所有的包
本教程适用Redhat 7 、CentOS 7、Oracle Linux 7 ,其他系统未测试。
看韩顺平老师的教程跟着操作,觉得步骤蛮简单,于是整理成了文档,希望能帮助到更多的人。
步骤很简单,跟着操作就能成功。
安装mysql57 操作步骤如下:
1 前提:安装jdk,安装方式自行百度
2 创建/opt/mysql,cd进去
3 使用命令下载MySQL的安装包,或者自己去官网下载,然后上传到Linux
# 使用命令下载mysql(若wget无法使用请先安装wget) wget http://dev.mysql.com/get/mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar 下面是下载完成的文件:
4 解压安装包(若是.tar.gz,则使用tar -zxvf;若是.tar,则使用tar -xvf )
解压后/opt/mysql文件夹下的文件:
5 若是CentOS7.6,需要运行 rpm -qa | grep mari,查询mariadb相关安装包,因为CentOS 7.6会自带类MySQL数据库,会和mysql冲突,所以有安装包则删除:
rpm -e --nodeps mariadb-libs # 删除 6 然后开始依次执行以下语句安装MySQL
若在安装上图最后一条时报错:“依赖net-tools”,则执行以下命令安装net-tools,再安装上图的最后一条即可:
yum install net-tools 7 启动MySQL
systemctl start mysqld # 启动mysql服务 systemctl status mysqld # 查看mysql服务状态 下图就是running运行状态:
8 设置root用户密码
MySQL会自动为root生成密码,执行下面的命令可看到密码
grep "password" /var/log/mysqld.log 如下图的 t_* 就是密码:
核心 Android 系统提供的调节音量的方法 核心 Android 系统提供了多种调节音量的方法,这些方法主要包括如下这些。
如在 Android Automotive 调节音量的过程 中我们看到的,CarAudioService 最终在 CarAudioDeviceInfo 中 (packages/services/Car/service/src/com/android/car/audio/CarAudioDeviceInfo.java) 通过 AudioManager 直接为设备设置音量: // Input is in millibels void setCurrentGain(int gainInMillibels) { // Clamp the incoming value to our valid range. Out of range values ARE legal input if (gainInMillibels < mMinGain) { gainInMillibels = mMinGain; } else if (gainInMillibels > mMaxGain) { gainInMillibels = mMaxGain; } // Push the new gain value down to our underlying port which will cause it to show up // at the HAL.
前言: 通过前面的学习,我们已经熟练掌握C语言个语法原理与使用,而今天这篇文章我们将要学习文件操作,来帮助我们更好的处理程序目标要求。
一、文件概述: 1.为什么使用文件: 我们前面学习结构体时,写了通讯录的程序。当我们运行这个程序时,可以给通讯录中增、删、查、改数据,但是此过程所载入的数据是放入内存中的,当我们退出程序时,载入通讯录的数据自然而然就不在了,等下次重新运行通讯录时,又要我们重新输入数据,如果使用这样的通讯录相当于没用。所以,我们的目的便是希望将数据可以保留起来,只有当我们删除的时候,数据才会删除,即尝试将数据持久化。而要实现数据持久化的方式一般有两种:使用数据库将数据存放在本地磁盘文件。
2.什么是文件: 我们通常所说的文件,一般是指存放在我们计算机本地硬盘上的文件。但是在我们的程序设计中,则指的是程序文件和数据文件两种文件(根据文件功能分类)。
①.程序文件:
程序文件主要包括源程序文件,目标文件和可执行程序文件。
源程序文件(后缀为c):
目标文件(windows环境下后缀为.obj):
可执行文件(Windows环境下后缀为.exe):
②数据文件:
数据文件的内容不一定是程序,而是程序运行过程中所进行读写数据,比如程序运行中需要从中读取的数据,或者程序运行完毕所输出的文件。而我们今天所讨论的,正是这谢谢数据文件的相关操作。
在之前学习中,我们所有的输出,其操作对象都是终端,均是从键盘读取输入内容,并将处理结果输出致我们计算机显示器上进行反馈。而今天我们的目的就是将数据信息输入到我们的本地硬盘上,而当我们想要对数据进行操作时,在从本地硬盘进行读取。
③文件名:
文件跟我们人一样也有自己名字,只不过不叫名字而是文件标识符,而为了方便起见我们常常将这个文件标识符称为文件的文件名.文件名的存在就是为了便于我们进行识别和引用.
一个文件的文件名由三部分组成:文件路径+文件名主干+文件后缀。
以文件名"D:\code\text.txt"为例:
其 文件路径为:"D:\code\",表示文件存放在硬盘D盘下的code文件夹里面. 文件主干:"text",表示该文件的文件名为text. 文件后缀:".txt",表示该文件的文件类型是文本. 二、文件顺序读写: 文件的打开和关闭: 我们在使用或操作我们的文件之前,首先需要在我们的程序中将其打开,于是我们来研究文件打开和关闭方式。
①文件指针:
在我们缓冲文件系统中,最关键的一个概念就是“文件类型指针”,我们通常称之为“文件指针”。并且我们要知道,我们使用的每一个文件都在内存中开辟了相应的文件信息区,用于存放该文件的相关信息并且这谢谢信息都保存在一个结构体变量中。
并且这样的结构体类型是有系统声明的,取名为FILE。
例如在vs2013的头文件stdio.h中(非自定义结构体类型)就有该类型的声明:
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE; 使用不同的C语言编译器,FILE类型中所包含的信息可能不完全相同,但是都大同小异。每当我们打开一个本地文件时,系统就会依据我们打开的文件情况自动创建出一个FILE结构的变量,并填充该结构内的信息,其中的过程比较复杂我们无需关系,只需要知道存在这一过程即可。而这个由系统创建出来并填充的FILE结构变量,就是通过一个FILE类型文件指针类型进行调用和维护的。
FILE* p; //定义一个FILE类型的文件指针p; 像这样,我们就能创建出来一个文件指针,而接下来就可以使用这个文件指针p指向某个文件信息区(FILE类型的结构体变量),并通过该文件信息区所保存的信息来访问本地硬盘的文件了。也就是说,我们通过使用文件指针就可以找到与其相关联的文件了。
②文件的打开与关闭:
我们应当在读写文件之前打开文件,并在文件读写结束后关闭文件。同时ANSIC规定,使用fopen(file open)函数来打开文件,用fclose(file close)函数来关闭文件。
fopen使用格式:
FILE* p=fopen(const char* filename,const char* mod) 其中 “const char* filename”指文件名(是字符串); 其中 “const char* mod”指文件打开模式(也是字符串); int main() { //打开文件 FILE* p = fopen("
我个人感觉应该是安装pycharm的时候卸载了pip的有关内容。若出现了这种情况,则运行以下指令:
python -m ensurepip easy_install pip python -m pip install --upgrade pip
懒汉式单例 private static SingletonInstance INSTANCE; private SingletonInstance(){ } public static SingletonInstance getInstance() { if (INSTANCE == null) { INSTANCE = new SingletonInstance(); } return INSTANCE; } 构造方法私有化,然后判断是否为空,如果是空,就new一个实例对象,单线程下看似没什么问题,但是如果是多线程,就会有问题了
如果有多个线程同时进入if (INSTANCE == null) 这个判断,那就会生成多个对象了,就不是单例对象了
好我们来加锁看下效果
private static SingletonInstance INSTANCE; private SingletonInstance(){ } public synchronized static SingletonInstance getInstance() { if (INSTANCE == null) { INSTANCE = new SingletonInstance(); } return INSTANCE; } 这样加上锁之后是不是就解决了多个线程的问题呢
但是有个问题,就是锁粒度太大了,加在方法上,那有100个线程一上来就会先竞争锁,性能非常低,我们把锁粒度缩小点
private static SingletonInstance INSTANCE; private SingletonInstance(){ } public static SingletonInstance getInstance() { synchronized (SingletonInstance.
生成模型与判别模型 一、决策函数Y=f(X)或者条件概率分布P(Y|X) 监督学习的任务就是从数据中学习一个模型(也叫分类器),应用这一模型,对给定的输入X预测相应的输出Y。这个模型的一般形式为决策函数Y=f(X)或者条件概率分布P(Y|X)。
决策函数Y=f(X):你输入一个X,它就输出一个Y,这个Y与一个阈值比较,根据比较结果判定X属于哪个类别。例如两类(w1和w2)分类问题,如果Y大于阈值,X就属于类w1,如果小于阈值就属于类w2。这样就得到了该X对应的类别了。
条件概率分布P(Y|X):你输入一个X,它通过比较它属于所有类的概率,然后输出概率最大的那个作为该X对应的类别。例如:如果P(w1|X)大于P(w2|X),那么我们就认为X是属于w1类的。
所以上面两个模型都可以实现对给定的输入X预测相应的输出Y的功能。实际上通过条件概率分布P(Y|X)进行预测也是隐含着表达成决策函数Y=f(X)的形式的。例如也是两类w1和w2,那么我们求得了P(w1|X)和P(w2|X),那么实际上判别函数就可以表示为Y= P(w1|X)/P(w2|X),如果Y大于1或者某个阈值,那么X就属于类w1,如果小于阈值就属于类w2。而同样,很神奇的一件事是,实际上决策函数Y=f(X)也是隐含着使用P(Y|X)的。因为一般决策函数Y=f(X)是通过学习算法使你的预测和训练数据之间的误差平方最小化,而贝叶斯告诉我们,虽然它没有显式的运用贝叶斯或者以某种形式计算概率,但它实际上也是在隐含的输出极大似然假设(MAP假设)。也就是说学习器的任务是在所有假设模型有相等的先验概率条件下,输出极大似然假设。
所以呢,分类器的设计就是在给定训练数据的基础上估计其概率模型P(Y|X)。如果可以估计出来,那么就可以分类了。但是一般来说,概率模型是比较难估计的。给一堆数给你,特别是数不多的时候,你一般很难找到这些数满足什么规律吧。那能否不依赖概率模型直接设计分类器呢?事实上,分类器就是一个决策函数(或决策面),如果能够从要解决的问题和训练样本出发直接求出判别函数,就不用估计概率模型了,这就是决策函数Y=f(X)的伟大使命了。例如支持向量机,我已经知道它的决策函数(分类面)是线性的了,也就是可以表示成Y=f(X)=WX+b的形式,那么我们通过训练样本来学习得到W和b的值就可以得到Y=f(X)了。还有一种更直接的分类方法,它不用事先设计分类器,而是只确定分类原则,根据已知样本(训练样本)直接对未知样本进行分类。包括近邻法,它不会在进行具体的预测之前求出概率模型P(Y|X)或者决策函数Y=f(X),而是在真正预测的时候,将X与训练数据的各类的Xi比较,和哪些比较相似,就判断它X也属于Xi对应的类。
二、生成方法和判别方法 监督学习方法又分生成方法(Generative approach)和判别方法(Discriminative approach),所学到的模型分别称为生成模型(Generative Model)和判别模型(Discriminative Model)。
判别方法:由数据直接学习决策函数Y=f(X)或者条件概率分布P(Y|X)作为预测的模型,即判别模型。基本思想是有限样本条件下建立判别函数,不考虑样本的产生模型,直接研究预测模型。典型的判别模型包括k近邻,感知级,决策树,支持向量机等。
生成方法:由数据学习联合概率密度分布P(X,Y),然后求出条件概率分布P(Y|X)作为预测的模型,即生成模型:P(Y|X)= P(X,Y)/ P(X)。基本思想是首先建立样本的联合概率概率密度模型P(X,Y),然后再得到后验概率P(Y|X),再利用它进行分类,就像上面说的那样。注意了哦,这里是先求出P(X,Y)才得到P(Y|X)的,然后这个过程还得先求出P(X)。P(X)就是你的训练数据的概率分布。哎,刚才说了,需要你的数据样本非常多的时候,你得到的P(X)才能很好的描述你数据真正的分布。例如你投硬币,你试了100次,得到正面的次数和你的试验次数的比可能是3/10,然后你直觉告诉你,可能不对,然后你再试了500次,哎,这次正面的次数和你的试验次数的比可能就变成4/10,这时候你半信半疑,不相信上帝还有一个手,所以你再试200000次,这时候正面的次数和你的试验次数的比(就可以当成是正面的概率了)就变成5/10了。
还有一个问题就是,在机器学习领域有个约定俗成的说法是:不要去学那些对这个任务没用的东西。例如,对于一个分类任务:对一个给定的输入x,将它划分到一个类y中。那么,如果我们用生成模型:p(x,y)=p(y|x)·p(x)
那么,我们就需要去对p(x)建模,但这增加了我们的工作量,这让我们很不爽(除了上面说的那个估计得到P(X)可能不太准确外)。实际上,因为数据的稀疏性,导致我们都是被强迫地使用弱独立性假设去对p(x)建模的,所以就产生了局限性。所以我们更趋向于直观的使用判别模型去分类。
这样的方法之所以称为生成方法,是因为模型表示了给定输入X产生输出Y的生成关系。用于随机生成的观察值建模,特别是在给定某些隐藏参数情况下。典型的生成模型有:朴素贝叶斯和隐马尔科夫模型等。
三、生成模型和判别模型的优缺点 在监督学习中,两种方法各有优缺点,适合于不同条件的学习问题。
生成方法的特点:上面说到,生成方法学习联合概率密度分布P(X,Y),所以就可以从统计的角度表示数据的分布情况,能够反映同类数据本身的相似度。但它不关心到底划分各类的那个分类边界在哪。生成方法可以还原出联合概率分布P(Y|X),而判别方法不能。生成方法的学习收敛速度更快,即当样本容量增加的时候,学到的模型可以更快的收敛于真实模型,当存在隐变量时,仍可以用生成方法学习。此时判别方法就不能用。
判别方法的特点:判别方法直接学习的是决策函数Y=f(X)或者条件概率分布P(Y|X)。不能反映训练数据本身的特性。但它寻找不同类别之间的最优分类面,反映的是异类数据之间的差异。直接面对预测,往往学习的准确率更高。由于直接学习P(Y|X)或P(X),可以对数据进行各种程度上的抽象、定义特征并使用特征,因此可以简化学习问题。
四、生成模型和判别模型的联系 由生成模型可以得到判别模型,但由判别模型得不到生成模型。
五、再形象点可以吗 例如我们有一个输入数据x,然后我们想将它分类为标签y。(迎面走过来一个人,你告诉我这个是男的还是女的)
生成模型学习联合概率分布p(x,y),而判别模型学习条件概率分布p(y|x)。
下面是个简单的例子:
例如我们有以下(x,y)形式的数据:(1,0), (1,0), (2,0), (2, 1)
那么p(x,y)是:
y=0 y=1 ----------- x=1 | 1/2 0 x=2 | 1/4 1/4 而p(y|x) 是:
y=0 y=1 ----------- x=1 | 1 0 x=2 | 1/2 1/2 我们为了将一个样本x分类到一个类y,最自然的做法就是条件概率分布p(y|x),这就是为什么我们对其直接求p(y|x)方法叫做判别算法。而生成算法求p(x,y),而p(x,y)可以通过贝叶斯方法转化为p(y|x),然后再用其分类。但是p(x,y)还有其他作用,例如,你可以用它去生成(x,y)对。
再假如你的任务是识别一个语音属于哪种语言。例如对面一个人走过来,和你说了一句话,你需要识别出她说的到底是汉语、英语还是法语等。那么你可以有两种方法达到这个目的:
1、学习每一种语言,你花了大量精力把汉语、英语和法语等都学会了,我指的学会是你知道什么样的语音对应什么样的语言。
2、不去学习每一种语言,你只学习这些语言模型之间的差别,然后再分类。意思是指我学会了汉语和英语等语言的发音是有差别的,我学会这种差别就好了。
那么第一种方法就是生成方法,第二种方法是判别方法。
生成算法尝试去找到底这个数据是怎么生成的(产生的),然后再对一个信号进行分类。基于你的生成假设,那么那个类别最有可能产生这个信号,这个信号就属于那个类别。判别模型不关心数据是怎么生成的,它只关心信号之间的差别,然后用差别来简单对给定的一个信号进行分类。