这是915编程学习笔记,仅供自己复习使用,如果你有别的实现方式,欢迎留言。本人是菜鸡一枚,不喜轻喷。考研加油!
持续更新中…【完结,不再更新2019/12/5】
因为比较久没有写C++了,忘得差不多,所以写了点笔记回顾一下
1.向函数传入结构体数组的方式有两种:
利用struct info book[]
利用typedef给结构体再取一个名字book1,之后在用book1去定义数组
2.数组传值的时候直接写函数名即可
3.比较大小后作交换的是结构体整体book[i]
4.字符匹配 strcmp(bookname, book[i].name)==0 时表示匹配成功
注意应该i#nclude<string.h>
5.回车结束字符输入
法一、
char str[100];
cin.getline(str,99); //添加库函数#include <string.h>
法二、
char str[100];
gets(str); //添加库函数 #include <cstdio>
6.判断字符长度
int len=strlen(str); //调用库函数#include <string.h>
7.int k=ch[i]-'0'; //强制类型char型字符转换成int类型,并赋值给整型变量k
8.str[i]-'A' //str[i]是char型数组,转换成数组下标,用来统计大写字母的个数
9.(char)(max+'A') //max为出现字母次数最大的下标,加上’A’后转换成ASSIC码,再强制转换成char型字符,用来输出出现次数最多的字符是什么
下面才是正文!
1.标题判断回文串,以回车结束 #include <iostream> #include <string.h> #include<cstdio> //c方式调用的头文件 using namespace std; int main() { char str[100]; //cin.getline(str,99); //c++输入方式 gets(str); int len=strlen(str); for(int i=0;i<len/2;i++) { if(str[i]!=str[len-i-1]) { cout<<"F"<<endl; return 0; } } cout<<"
1.多条件查询,得到符合条件的数组result,以及关键参数:数组长度
2.设定分页参数:每页显示条目数
3.计算分页关键参数:
总页数(数组长度 / 每页显示条数)
当前页(默认为第0页)
4.获取符合条件的数组中当前页数据
result.slice(当前页 * 每页显示条目数,(当前页+1) * 每页显示条目数)
前言 上篇讲到yolo v2 loss中使用了两个loss分别时wh使用的smoothl1 loss以及其他的BCEloss,这里做个扩展介绍,并对比pytorch以及tensorflow的api接口的使用
smooth l1(huber loss) 转载自知乎高赞回答:https://www.jianshu.com/p/19483787fa24
smooth L1 loss能从两个方面限制梯度:
当预测框与 ground truth 差别过大时,梯度值不至于过大;当预测框与 ground truth 差别很小时,梯度值足够小。 考察如下几种损失函数,其中
损失函数对 x 的导数分别为:
观察 (4),当 x 增大时 L2 损失对 x 的导数也增大。这就导致训练初期,预测值与 groud truth 差异过于大时,损失函数对预测值的梯度十分大,训练不稳定。
根据方程 (5),L1 对 x 的导数为常数。这就导致训练后期,预测值与 ground truth 差异很小时, L1 损失对预测值的导数的绝对值仍然为 1,而 learning rate 如果不变,损失函数将在稳定值附近波动,难以继续收敛以达到更高精度。
最后观察 (6),smooth L1 在 x 较小时,对 x 的梯度也会变小,而在 x 很大时,对 x 的梯度的绝对值达到上限 1,也不会太大以至于破坏网络参数。 smooth L1 完美地避开了 L1 和 L2 损失的缺陷。其函数图像如下:
由图中可以看出,它在远离坐标原点处,图像和 L1 loss 很接近,而在坐标原点附近,转折十分平滑,不像 L1 loss 有个尖角,因此叫做 smooth L1 loss。
数组去重除了使用js自带的set方法,还可以用lodash的uniq方法:
eg:
const num = [1, 2, 3, 4, 4, 3]; const differNum = [...new Set(num)]; console.log(differNum); // [1, 2, 3, 4]; 但当数组为数组对象时,set方法便不能进行去重,
eg:
const list = [{ processDesc: '走动', processNum: '1', }, { processDesc: '顺序', processNum: '2', }, { processDesc: '顺序', processNum: '2', }]; const newList = [...new Set(list)]; console.log(newList); 因此,这里推荐lodash的uniqWith方法;
安装:
npm install --save lodash _.uniq(array) 创建一个去重后的array数组副本。使用了 SameValueZero 做等值比较。只有第一次出现的元素才会被保留。
参数
array (Array): 要检查的数组。 返回
(Array): 返回新的去重后的数组。
eg:
在有重复的数据中只保留时间最大的一条数据 1. 选出目标字段有重复的数据2. 在重复的数据行中选出时间最大的数据完整代码 1. 选出目标字段有重复的数据 这里介绍两种方法:
通过dplyr包,根据目标字段(key_name)聚合再计数选出条数大于1的数据行 # 只选出有重复的目标字段 duplicate_name = df %>% group_by(key_name) %>% summarise(freq = n()) %>% filter(freq > 1) %>% select(key_name) 通过sqldf包,写sql语句使用having选出计数大于1 duplicate_name = sqldf("select key_name , count(key_name ) count from df group by key_name having count > 1")$key_name 数据量大的适合推荐使用第二种,速度快很多,且占用少量资源
根据重复名称选出数据
duplicate_data = df[df$key_name %in% duplicate_name$key_name, ] 2. 在重复的数据行中选出时间最大的数据 clear_duplicate_info = duplicate_data %>% group_by(key_name) %>% filter(date == max(date)) 完整代码 应用场景:企业的存续注销都存在的情况,只选出存续的id以及相关数据;根据数据的业务情况,这里采用只保留成立时间最近(即最大)的一条数据
company_better_distinct = function(df){ # 数据量大的话,groupby效率太低且占资源,用sqldf速度快很多 # duplicate_name = df %>% group_by(company_name) %>% summarise(freq=n()) %>% filter(freq>1) %>% select(company_name) duplicate_name = sqldf("
detector = dlib.get_frontal_face_detector()
#功能:人脸检测画框
#参数:无
#返回值:默认的人脸检测器
faces = detector(img_gray, 0)
功能:对图像画人脸框
参数:img_gray:输入的图片
返回值:人脸检测矩形框4点坐标
在正常解析一个有值的字符串时,用lateral view explode是完全ok的,但是,当遇到该字符串为空时,如果在使用该函数,就会导致该条记录消失。这时候需要加个outer lateral view outer explode
转载自https://blog.csdn.net/jarry_cm/article/details/90402833
之前小白有写过一篇文章是高效的解析字符串,里面讲到过一个方法:lateral view explode
最近小白发现,这个函数在使用时,还是有一些坑的,这里小白做一个总结。
在正常解析一个有值的字符串时,用lateral view explode是完全ok的,但是,当遇到该字符串为空时,如果在使用该函数,就会导致该条记录消失。具体场景如下:
sidfilterlist46NULL 这时,用lateral view explode解析:
select a.sid ,b.filtertype --筛选类型 ,b.filtername --筛选内容 ,b.filtertitle --筛选子类型 ,b.filtersubtype --来源:1搜索;2筛选;3url传参 ,b.filterid --筛选id from (select sid,filterlist from dw_htlbizdb.tmp_hotel_list_bottom01 lateral view explode(split(filterlist,'\\;'))t as flist )a lateral view json_tuple(flist,'filtername') b as filtername where sid = 49 ; 结果如下:
sidfiltername无记录 这样的结果就会导致我们漏掉一部分用户的浏览信息,在统计浏览量时数据缺失,结果与实际偏小。
这时,就要用到lateral view outer explode
lateral view explode这个UDTF转换的Array为空的记录,自动被过滤掉了,
如果想要保留记录,需要加上outer关键字。 select a.sid ,b.filtertype --筛选类型 ,b.filtername --筛选内容 ,b.
Esxi虚拟机无法上网的问题解决记录 问题介绍解决方法有待学习研究的部分 问题介绍 最近使用vmware的Esxi 搭建一个虚拟平台,然后在这个平台上创建各种虚拟机,我最先创建的是Centos 7.6的虚拟机,选择的默认的“VM Network”端口组,创建整个虚拟机的过程比较顺利,但是当我设置好静态IP的时候问题出现了,死活上不去网.大概情况如下:
可以看到虚拟机的除了上不了网之外,网络状态都是显示正常的。
之后就是各种改参数改状态,以开始以为是Centos配置的问题,后来用win10虚拟机尝试都是同样的问题。可以确定不是虚拟机系统的问题,问题出现在网络配置上。
在网上也找了各种解决方法,什么改虚拟机的物理mac地址,配置混合模式,都试过了,但是没有效果。
纠结了好久,最后发现我一直忘记了看下官方文档,所以最后去官网查了下文档,终于找到了解决方法。
解决方法 找到了 vSphere 网络连接下面的“VLAN 配置” 找到一些说明,如下图
https://docs.vmware.com/cn/VMware-vSphere/6.7/com.vmware.vsphere.networking.doc/GUID-7225A28C-DAAB-4E90-AE8C-795A755FBE27.html
可以看到三种模式,对应不同的ID值,其中0是在VMkernel模式的网卡中配置使用,这个排除。然后在虚拟端口组中配置过1~4094中的几个数值,但是没效果,于是最后试了下4095(如下图),没想到最后中遇通了,完美解决。
有待学习研究的部分 通过这次的学习研究,我发现了以下几个我需要注意的问题。
1. 在研究许多软件问题的时候,还是要多回归到官方文档。当问题没法一下解决的时候,一定要看官方文档。
2. 自己在网络方面的知识还是有很大却是需要多学习。
最后附几个链接供学习参考:
https://docs.vmware.com/cn/VMware-vSphere/6.7/com.vmware.vsphere.networking.doc/GUID-7225A28C-DAAB-4E90-AE8C-795A755FBE27.html
https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%B1%80%E5%9F%9F%E7%BD%91/419962?fromtitle=VLAN&fromid=320429&fr=aladdin
ICDAR 2019表格识别论文与竞赛综述(上)
表格作为一种有效的数据组织与展现方法被广泛应用,也成为各类文档中常见的页面对象。随着文档数目的爆炸性增长,如何高效地从文档中找到表格并获取内容与结构信息即表格识别,成为了一个亟待解决的问题。ICDAR是一个专注于文档分析与识别问题的国际学术会议,已经连续多届设置了表格识别专题。在今年的ICDAR 2019会议上,有不少研究者在表格检测与结构识别等领域做出了新的贡献,使其有了新的进展。本课题组梳理了该会议中有关表格识别的16篇论文,总结该领域当前的研究进展与挑战。同时,值得注意的是,该会议也举办了关于表格检测与结构识别的比赛,我们对参赛队伍使用的方法与结果进行了一些讨论。
一、研究背景 随着文档尤其是通过扫描、拍照等方式生成的文档的快速增长,自动地进行文档识别(Document Recognition)并从中提取有用的数据成为了一个备受关注的研究问题。这其中,表格作为一种高效的数据组织和展现的方式,是文档页面中最重要的数据对象之一。表格识别包括表格检测与结构识别,作为文档识别一个重要的子任务,一直是该领域研究者关注的研究问题。
图1 表格检测与结构识别示例
文档页面往往由不同的页面对象(Page Object)组成,包括文本行、图像、表格、公式等。表格检测(Table Detection)任务是从一个页面中检测出表格所在的区域,表格结构识别(Table Structure Recognition)任务则是在检测到的表格区域的基础上,进一步将表格的内容与逻辑结构识别出来。如图1所示,若输入为页面图像,表格检测任务就是在页面图像中定位出表格的位置,这与计算机视觉中的目标检测任务类似;而表格结构识别任务则是对检测出的表格区域进行分析,得到表格的行列、层次等逻辑结构。由于表格大小、种类与样式复杂多样,例如表格中存在不同的背景填充,不同的行列合并方法,不同的内容文本类型等,并且现有文档既包括现代的、电子的文档,也有历史的、扫描的手写文档,它们的文档样式、所处光照环境以及纹理等都有比较大的差异,正如图2中表格示例所展示的那样,表格识别一直是文档识别领域的研究难点。
早期的表格识别研究主要是基于启发式规则的方法[16-20],既有基于图像文档的方法,也有基于PDF文档的方法。例如由Kieninger等人提出的T-Rect[16]系统使用自底向上的方法对文档图像进行连通分支分析,然后按照定义的规则进行合并,得到逻辑文本块。而之后由Yildiz等人提出的pdf2table[18]则是第一个在PDF文档上进行表格识别的方法,它利用了PDF文件的一些特有信息(例如文字、绘制路径等图像文档中难以获取的信息)来协助表格识别。而在最近的工作中,Koci等人[22]将页面中的布局区域表示为图(Graph)的形式,然后使用了Remove and Conquer(RAC)算法从中将表格作为一个子图识别出来。
近年来飞速发展的深度学习技术在计算机视觉、自然语言处理、语音处理等领域取得了很多可观的成果。研究者们也将深度学习技术应用到了场景文字识别、文档分析、表格识别等领域,取得了不错的效果。由于表格检测任务与计算机视觉中的目标检测任务比较类似,这个任务优先得到了很多性能上的提升,在ICDAR2013表格竞赛[23]和ICDAR2017页面对象识别竞赛[24]里,各个队伍的方法与结果已经显示出了表格识别方法的转变与相应的性能提升。而表格结构识别任务则与其他领域的任务有着不小的区别,所以之前还没出现特别有效的深度学习方法。另一方面,由于深度学习方法是数据驱动的方法,需要大量的标注数据对模型进行训练,所以现有的数据集规模偏小也是一个重要的制约因素。
图2 表格检测与结构识别示例
左上:有颜色背景的全线表,右上:少线表,左中:无线表,左下:有复杂表格线条样式的表格,右下:拍照得到的手写历史文档。
在表格识别领域,国际上最相关的会议之一就是文档分析与识别会议ICDAR(International Conference on Document Analysis and Recognition),它是由国际模式识别学会(IAPR)组织的会议之一,每两年举办一次,是文档识别领域最重要的学术会议。今年,ICDAR2019于9月20日-25日在澳大利亚悉尼举办,多篇有关表格识别的论文也在会议上作了口头或者海报报告。这些论文有的针对表格的特性解决了以往研究的一些问题,有的提出一些新的目标检测方法应用到表格识别领域并取得了不错的效果,有的则是发布了包含大量表格的数据集,为该领域提供数据支持。同时,ICDAR2019也举办了一个针对表格识别任务的比赛:ICDAR2019 表格检测与识别比赛(ICDAR2019 Competition on Table Detection and Recognition, cTDaR),来自工业界和学术界的十余支队伍在这个比赛中提交了有效结果。
我们针对ICDAR2019会议中有关表格识别,即表格检测与结构识别的论文和竞赛做一个综述,主要包括以下内容:
对ICDAR2019中关于表格识别的论文的一个整体探讨。内容包括这些论文的主要方法,方法的有效性与新颖性,实验情况等,并对这些论文做一个整体的对比分析,以期让读者对当前该领域的研究进展有一个整体认识。
对ICDAR2019表格检测与识别比赛的情况概述。参赛队伍提交方法的讨论与比赛结果的分析。参赛队伍中既有来自于工业界的同行,也有来自于学术界的学者,我们可以从中看到整个领域的方法趋势和性能进展状况。
对于表格识别领域目前仍然存在的问题和未来研究方向的探讨。表格本身的特性导致某些识别问题和挑战是非常难以解决的,我们对这些问题加以分析,并尝试针对这些问题给出一些未来可能的研究方向。
二、论文方法
在今年的ICDAR2019会议中,共有16篇与表格识别相关的论文,其中有5篇针对表格检测任务,有8篇针对表格结构识别任务,有1篇在他们的方法里同时进行了表格检测与结构识别的任务,还有2篇则是发布了新的表格识别相关的数据集。在接下来3个子章节中,我们分别介绍表格检测、表格结构识别和表格数据集三部分的论文情况,以探讨目前该领域的最新研究进展。在此之前,这些论文的整体情况概述展示在了表1中。
表1 ICDAR2019表格识别领域论文整体情况
注:“论文名称”一列中,论文名称前标有*号的论文表示其未使用基于深度学习的方法。每一种方法的“效果”一列中展示的均为论文中的最好效果。
a) 表格检测任务
随着深度学习方法的迅速发展,越来越多研究者倾向于使用深度学习的方法来进行表格检测任务。对于文档页面图像中的表格检测任务来说,研究者通常将其视为目标检测(Object Detection)或者图像语义分割(Semantic Segmentation)任务,而近些年来,随着图神经网络(Graph Neural Network)的兴起,也有一些研究者尝试将图神经网络应用到文档识别或表格识别领域中来。本次ICDAR2019会议中,共有5篇论文尝试解决表格检测中的一些已知问题,除了其中1篇使用了基于规则的传统方法,其余4篇均使用了深度学习方法,并且其中一篇创新性地将图神经网络应用到发票中的表格检测中来。
图3 论文[1]中提出的open table和closed table的检测框架
《Parameter-free Table Detection Method》[1]一文使用了传统的规则方法,将多高斯分析应用到了表格检测任务中来,使得无参数无训练集的表格检测成为可能,从而规避了该领域缺少用于训练的大量数据的问题。作者将表格检测任务分为了Open Table和Closed Table两个类别来处理。整体框架如图3所示。对于Closed Table,作者先删除表格中的所有行和列的线,之后使用距离方法确定每个单元格的边界,然后对单元格的边界进行水平和竖直方向的投影来获得行和列的分割间隙,最后使用HPP(Horizontal Projection Profile)来确认表格检测结果。对于Open Table,由于缺少表框和水平与竖直线,文本单元格的内容可能会被误识别为常规的段落文本,因此作者通过将多高斯分布模型扩展到文本块的高度和宽度直方图来解决该问题。宽度直方图显示了两种类型文本块对应的两种不同的区域。高低直方图原点附近的峰表明,有一些高度较小的块可能对应于表格的单元格文本。最终作者使用GMM-EM方法来拟合平滑的数据,用加权高斯方法将数据分为三组,分别是小、中和大尺寸的表格。经过处理,对文档中的表格和段落分类为表格块和文本块。将相邻的表格块进行合并,将没有左邻居或右邻居的块,作为表格结束单元格,以得到表格区域。本方法在ICDAR2013数据集上进行了测试,取得了Open Table F1-score=91.3%,Closed Table F1-score=92.
NAS家庭服务器方案 一、硬件选择方案: 1、自组硬件方案(推荐)
①、cpu选择:J1900/J3160/N3150等低功耗cpu
2、群晖NAS方案(价格贵)
3、矿难便宜NAS方案(价格低,稳定性差)
①、蜗牛星际
二、系统方案: 1、Windows Server 2012(推荐)或者Windows10方案
2、群晖NAS方案
3、Linux系统方案
三、内容方案: 1、下载方案
①、bt下载:QTDownload
②、迅雷下载:迅雷官方软件或者迅雷的玩客云
③、百度云下载
2、存储方案
①、手机相片视频同步方案:Daemon sync、photo sync
3、家庭影院方案
①、Jellyfin server + 安卓客户端、安卓盒子客户端(或者Kodi+jellyfin插件)
②、Emby server + 安卓客户端、苹果客户端(收费)、安卓盒子Kodi+emby插件方案
③、威动影音server(旧版本才免费) + 威动影音安卓客户端、安卓盒子Kodi方案
④、Plex server + plex客户端
4、游戏方案(暂时没接触)
5、软路由方案
①、虚拟机LEDE/高格等
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。
Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。
Maven这个单词来自于意第绪语(犹太语),意为知识的积累,最初在Jakata Turbine项目中用来简化构建过程。当时有一些项目(有各自Ant build文件),仅有细微的差别,而JAR文件都由CVS来维护。于是希望有一种标准化的方式构建项目,一个清晰的方式定义项目的组成,一个容易的方式发布项目的信息,以及一种简单的方式在多个项目中共享JARs。 [
https://baike.baidu.com/item/Maven/6094909?fr=aladdin
1.全局安装:
npm install create-react-app -g
2.进入项目:
弹射暴露webpack配置:npm run eject;安装less,less-loader;
npm install less less-loader --save-dev安装antd,babel-plugin-import;
npm install antd -S npm install babel-plugin-import -D
3.修改webpack.config.js文件中的配置:追加方框处代码 追加less配置
找到getStyleLoaders方法,追加代码:
最后一步,如何修改配置antd主题颜色,修改方框处代码为:
好了,大功告成
前言 异地灾备可以防止一个机房出现灾难而导致整个系统无法提供服务的问题。
异地双活在异地灾备的基础上减少了数据的冗余,并且提高了对数据双向同步及同步实时性的要求。
Kafka作为在双活中扮演了很重要的角色,一方面是两个区域的正常业务的消息数据分发、另一方面则是elasticsearch等中间件集群的双活方案有时需要依赖kafka的双活。那么在保证实时性的前提下做好kafka的双活呢?下面博主抛砖引玉给出自己实现的基于Kafka自带组件Mirror-Maker的两种方案,读者可以根据自己需要进行改进。
一、Kafka-Mirror-Maker MirrorMaker是Kafka官方提供的用来做跨机房同步的组件。在kafka的安装目录的bin目录下有一个kafka-mirror-maker.sh文件就是MirrorMaker的入口。
image.png 工作原理: 1、MirrorMaker本质上既是一个生产者又是一个消费者
2、MirrorMaker从一个机房的某个主题消费消息,再把消费到的消息生产到另一个机房的相同的主题下。
如何使用: bin/kafka-mirror-maker.sh --consumer.config consumer.properties --producer.config producer.properties --num.streams 3 --whitelist=".*" 参数解释:
--producer.config:mirrormaker中的生产者,与我们常规的生产者配置是一样的,我们可以参照生产者配置文档进行参数配置
--consumer.config:mirrormaker中的消费者,与我们常规的消费者配置相同,可以参照消费者配置文档进行参数配置
--num.streams:mirrormaker中消费者线程的个数
--whitelist:mirrormaker中消费者指定消费的主题,.*表示所有主题,常规可以使用 | 分割开多个主题。
当然还有很多其他参数,我们可以执行bin/kafka-mirror-maker.sh --help来查看
疑问解答: 1、mirrormaker应该从哪个机房消费,向哪个机房生产。
答:应该从异地机房消费向本地机房生产。如果反过来,当网络异常的时候就会产生消费的消息没有及时得到转发。
2、mirrormaker怎么配置生产者和消费者?
答:参照这个链接里的配置 就可以了 https://www.orchome.com/511
方案一、各机房自主题 实现原理 1、假设有北方机房和南方机房需要实现双活
2、南方机房的kafka包含江苏、广东、上海三个topic。北方机房包含黑龙江、甘肃、四川三个topic。每个机房的消费者只向自己机房的topic生产消息和消费消息。
3、启动两个Mirror-Maker分别负责从北向南同步数据和从南向北同步数据,保证两遍的机房都有六个省份的全量数据。
4、考虑异常情况,如果北方机房挂了或者南方机房挂了,那么另一个机房都会有全量数据可以提供服务。当然不排除小部分数据丢失,但灾难情况下是无法避免的。
存在问题及解决办法
存在问题: 1、__consumer_offset主题无法双向同步,会造成消费死循环。这就导致切换机房的时候备用消费者只能从头消费来保证消息的不丢失,消息会大量重复。
2、即便是灾备集群也存在同样的问题,如果把consumer_offset同步到灾备集群,如果主集群的topic的partition和灾备集群的topic的partition的数目不一致,就会导致切换机房的时候备用消费者无法复用offset的情况发生,最终导致消息大量重复消费或者消息丢失。
对于问题1的解决办法
1、参照方案二,做数据的全量同步
对于问题2的解决办法:
解决办法1、根据消息时间戳来找到消费者组对应的offset,然后从offset开始消费,同时业务端需要做幂等处理。下面给出关键代码(对应的kafka版本的消息要有时间戳才行)。
// 获取所有分区 List<PartitionInfo> partitionInfos = consumer.partitionsFor(topic); // 把分区映射成TopicPartition List<TopicPartition> topicPartitionList = partitionInfos .stream() .map(info -> new TopicPartition(topic, info.partition())) .collect(Collectors.toList()); // 给consumer分配这些分区 consumer.
在做数据聚合整理的时候,存在需要将同一ID的多列,合并成一个json,通过collcet_Set手动拼接json,手动效率不高,而且内置的UDF有连接符,最后生成的json格式怎么调试都不对,本想自己写UDF生成json,google后找到存在的UDF函数,先做以下记录:
google原帖参考:
https://stackoverflow.com/questions/25188734/converting-data-from-multiple-hive-tables-to-complex-json
https://stackoverflow.com/questions/24826530/collect-to-a-map-in-hive
附上github地址:
https://github.com/klout/brickhouse
该项目已经三年没更新,自己手动编译为通过,可能是原项目JDK版本太老了,好在有现成jar包
复制jar包到服务器
--导入udf ADD jar /opt/UDF/brickhouse-0.7.1-SNAPSHOT.jar; --创建临时UDF包collect CREATE TEMPORARY FUNCTION collect AS 'brickhouse.udf.collect.CollectUDAF'; --创建临时UDF包to_json CREATE TEMPORARY FUNCTION to_json AS 'brickhouse.udf.json.ToJsonUDF'; 这里解释下:
to_json可以将to_json(collect_set(字段名1)),将单列字段名1生成JSON串,生成的结果不带KEY值,格式为[{“value1”,“value2”…}]
这里在解释下collect_set collect_list的区别,collect_set 去重,collect_list不去重
collect可以将多列字段名,通过json的key-value方式结合,并且可以通过嵌套sort_array进行排序,其中得通过内置named_struct的UDF,组合为KEY-VALUE的格式,
to_json(sort_array(collect_set(named_struct(“key1”,字段名1,“key2”,字段名2… ))))
最后生成的json串带排序,且为key-value的格式
附 named_struct函数的官方解释
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
Linux Java JDK多版本管理自定义工具 为什么有其他工具还要自定义?我的工具基本原理运行工具前的步骤上代码运行效果 为什么有其他工具还要自定义? 之前用过update-alternatives 这个命令管理 但是如果JDK版本更新了,文件夹一变,你就要重新改注册,你要各种拷贝目录…
我的工具基本原理 通过软连接的方式在环境变量中配置一个固定的路径,这样每次要切换JDK版本时,只要改变下这个软连接路径即可,其他不要动。
即使增加新版本,只要将JDK放到/usr/lib/jvm/目录下即可通过运行工具选择切换。
运行工具前的步骤 按照正常情况,JDK默认安装的位置是/usr/lib/jvm/,所以我也就按照这个默认的位置来,把JDK的文件夹(如:jdk1.8.0_231)不管是安装还是拷贝的方式都放到这个目录下。
然后,如果是第一次使用,还是要正常配置环境变量的,不过要按照如下规则配置,其中这个路径不能变(/usr/lib/jvm/java_home)
#set oracle jdk environment export JAVA_HOME=/usr/lib/jvm/java_home ## Don't change this directory!!! export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH 最后运行下命令source /etc/profile激活你设置的环境变量。
接着就可以运行工具了。
上代码 将下面代码保存为sh文件即可,然后直接运行。没有位置要求,如果经常用可以放到bin目录下使用。
#!/bin/bash echo echo "===================================================================" echo "Please follow 3 steps as below before you select the JDK version!" echo "Step 1:" echo echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "Please put jdk folder in '/usr/lib/jvm/', this program will scan JDK in this directory!
注:名称长度不超过8位
##切换用户启动数据库
su - db2inst1
db2start
##连接数据库
db2 connect to 本地数据库名称 user 用户名 using 密码;
db2 set schema 本地SCHEMA;
## 打开联邦数据库参数
db2 update dbm cfg using FEDERATED YES
db2 force application all
db2stop
db2start
## 编目远程数据库节点
db2 "catalog tcpip node 节点名称 remote IP server 端口"
db2 "terminate"
## 编目远程数据库
db2 "catalog db 远程数据库名称 as 远程数据库在本地别名 at node 节点名称 authentication SERVER"
db2 "terminate"
## 测试连接是否可用
db2 "list db directory"
db2 "
本文讨论的重点跟踪算法如何应用在车道线应用中,即从得到车道线检测结果开始,到连续稳定地车道线跟踪的过程。包含车道线模型、鲁棒的拟合方法和跟踪。本文原创。
车道线检测和跟踪是自动驾驶中必不可少的功能,LDW(车道偏离预警)、LKA(车道保持辅助)等功能模块都依赖于连续稳定的车道线检测和跟踪。(多)目标跟踪算法已经得到充分研究,而且相关算法解析和综述网上已经有很多了,也可以在计算机视觉life相关文章中找到,不再赘述。但是以上跟踪的分析,大多针对点目标,而此处我们关注跟踪算法如何应用在车道线应用中。一般来说跟踪和检测需要分开实施,如果有端到端一步实现检测+跟踪的方法,烦请不吝赐教。
本文先简单介绍车道线检测结果和问题,然后建立车道线的多项式模型,以及获得模型参数需要的鲁棒的拟合算法。接着介绍常见的跟踪算法,以Kalman滤波为主。最后是车道线相关资源干货分享。
获得车道线检测结果 车道线跟踪前提是拿到车道线检测结果。车道线检测的传统图像处理方法有:梯度+颜色信息、参数空间投票、边缘检测+Hough变换及其变形、k-means聚类和利用图像特征检测等方法。传统的车道检测方法需要高度定制化,包括许多手工特征提取和后处理方法。当测试环境改变时,常常需要大量调参工作,甚至需要更换后处理方法。很多时候需要在鸟瞰图上利用车道线空间相互关系进行处理。
近两年(从2017年开始)开始出现了许多基于深度学习的方法,如SCNN,VPGNET,Lanenet,甚至是图像分割(可通行区域)等,实现了端到端的检测,在原图上很好的利用了环境信息,提高稳定性。
除了检测出存在曲线和位置,还要区分出不同车道的车道线,通常需要提供左左,左,右,右右共四条车道线,即能区分出三条车道。
这里检测结果应包括点坐标、颜色、线型、置信度等信息。当然也有研究把线型的确定称为车道线识别。
当状况良好的时候,仅靠车道线检测就能连续输出车道线,例如网上广为流传的Udacity提供的开源项目[8],仅靠梯度+颜色信息的检测方法,就能检测出几乎所有帧里的车道线,没有明显遗漏。因此后处理只需要对车道检测出来的点进行拟合并延伸到灭点即可,无需更多跟踪过程。如下图所示,当前车道线被红色线标记出来。
但是几乎所有实际路况,或多或少存在路面有修补、有积水、有阴影、车道线被遮挡、污损等情况以及车辆颠簸、上下坡等更极端的工况。下面的动图是LaneNet原始检测结果(from Karol Majek),车道线检测出的概率越高的地方颜色越亮。其中右侧路沿绿色的检测结果时断时续,在进入阴影时,检测失效,这是因为没有用跟踪进行结果稳定。因此,引入了车道线跟踪很重要,根据历史状态和道路几何关系,补充检测丢失、错误的车道线,并使车道线在空间位置上更稳定。
建立车道线模型 跟踪第一步,是要根据场景要求,合理地用较少参数准确描述出车道线,即把检测结果抽象成模型参数。但直接用图片像素上的曲线建立模型并不理想,而是需要转换到车体坐标系下建立模型,这是因为车体坐标系下模型参数的物理意义才更清晰。而且通常冗余设计包含多个相机,多个相机也必须统一到车体坐标系。通常使用逆透视变换把图片坐标转化为车体坐标。下图左红色坐标系定义了车体坐标系,坐标系原点为车辆中心(根据不同标准车辆中心位置定义不同,不具体讨论)。
假设路面水平,车道线模型可以用多项式 来表示,但是其中的多项式系数 的物理含义并不直观。我们可以改写成如下形式
其中 是车道线的位置即截距( ), 是车道线角度( ), 是车道线曲率( ), 是车道线曲率的变化率( )。车道线曲率半径为 ( ),如上图右上的Radius of Curvature的数值。以上所有参数都是在 处分析的,通过对 求多次导得到。需要说明的是,公式进行了必要的近似,只有车辆沿道路正常往前开或转向不明显——即 较小——时,角度 才近似于一阶项系数 ,曲率也才能近似于 的二阶导数(可参考曲率的定义)。
另外,也有文献用车道宽度、车中心偏离车道中心位置、车道线角度以及曲率四个参数来表征车道线,如文献[1] 。还有文献采用二次B条样函数表示车道线模型。
作为一般讨论,这里用水平路面四个参数 表征一条车道线,较简洁,而且和真实物理量之间也有清晰的对应关系。
鲁棒的曲线拟合 选定车道线模型后,需要利用车道线检测结果(通常为散点,需要事先变换到车体坐标下)拟合该模型的参数。这里主要介绍两种比较常用的方法,最小二乘法和RANSAC(随机抽样一致性),此处假设大家都大概了解这两个算法的原理。
最小二乘法是最小化残差平方和的一种最优化方法,广泛应用的原因之一是其平方和的形式,便于整理成矩阵相乘的形式,例如线性最小二乘容易得到闭合解 ,其中 是包含 、 、 、 的矩阵。而且平方形式便于求导和泰勒展开,才能有后面的Gauss-Newton和LM最优化迭代算法。
不过,最小二乘法的过拟合问题会显著影响车道线拟合效果,造成泛化误差增加。因为车道线参数在一定范围内不会有特别大的突变,如很少曲率特别大的弯道等,所以车道线以低阶多项式表达为主,根据经验,二阶形式能表示大部分情况。这种情况下如果有车道线检测有误差,会使得拟合曲线曲率异常,此时车道线模型中的三阶项就会产生明显的问题(此时三阶项系数 可能会异常的大),如下图所示。而且同一条线前后帧可能也会跳动剧烈,因为帧与帧之间的噪声不同,拟合误差大。解决办法之一是直接降低拟合阶数,不过最好能够自适应地调节并切换模型阶数,否则失去了该模型的意义。还可以采用带正则项的最小二乘,闭合解为 ,其中 是正则系数。因为正则化抑制了系数的异常变大,降低了噪声的影响。下图是直接最小二乘和带正则项的最小二乘的拟合效果比较,可以看到后者在高阶拟合时对噪声不那么敏感(此处拟合阶数大于3阶,只是为了展示问题)。
即便如此,最小二乘可能仍然不够鲁棒,因为最小二乘要用所有输入的点来计算,异常点不可避免地影响到拟合效果。例如有较大误差的噪声信号的情况(下图左),或者有多条车道线结果被错误包含在一条车道线的结果中的情况(下图右)。
RANSAC算法提供了另一种鲁棒性拟合的思路。RANSAC通过迭代算法找到包含最多内点(实际有用的数据点)数量的拟合曲线。由于只用内点进行拟合,而噪声或另一车道线的数据就会被当成外点,外点对拟合没有任何贡献。该算法用随机数据抽样的数据来拟合,因此一定概率能找到最优拟合曲线。但是,当这个概率——拟合置信度 ——很大时,如 ,就可以认为找到的曲线近似等于实际的曲线。经实验验证,对于包含 %误差的数据集,RANSAC的效果远优于直接最小二乘法。
RANSAC算法收敛的关键在于参数的选取,参数有:某个点是外点的概率(噪声或者错误车道线) ,每次抽样的点数 ,抽样次数 和算法收敛设定的 阈值,这几个参数的关系如下图所示。下图的表格为不同条件下 的选取。另外,还有一个参数是内点选取范围距离 ,该值与 和样本点方差 有关,如 时, 。
docker容器中使用jstack、jmap (基于livingobjects/jre8的镜像)
#进入容器里
docker exec -it xxx /bin/bash 容器里面运行:
1、修改源:
cd /etc/apk vi repositories 2、替换成阿里源
http://mirrors.aliyun.com/alpine/v3.8/main/ http://mirrors.aliyun.com/alpine/v3.8/community/ apk update 3、安装jdk
apk add openjdk8 cd /usr/lib/jvm/java-1.8-openjdk/bin 4、运行jstack、jmap等工具
./jstack ./jmap ./jmap -dump:live,format=b,file=dump20191122.hprof (pid)
一、问题 request.Request(url,headers=headerDict))的时候出现异常信息:'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
二、解决方案 http头中headerDict参数: "Accept-Encoding": "gzip, deflate",
代表本地可以接收压缩格式的数据,而服务器在处理时就将大文件压缩再发回客户端,IE在接收完成后在本地对这个文件又进行了解压操作。
出错的原因是因为你的程序没有解压这个文件,所以删掉这行就不会出现问题。
https://blog.csdn.net/zhang_cl_cn/article/details/94575568
Python模块Requests的中文乱码问题 from:http://blog.csdn.net/chaowanghn/article/details/54889835
解决Requests中文乱码 都在推荐用Requests库,而不是Urllib,但是读取网页的时候中文会出现乱码。
分析: r = requests.get(“http://www.baidu.com“) **r.text返回的是Unicode型的数据。 使用r.content返回的是bytes型的数据。 也就是说,如果你想取文本,可以通过r.text。 如果想取图片,文件,则可以通过r.content。**
获取一个网页的内容 方法1:使用r.content,得到的是bytes型,再转为str
url='http://music.baidu.com' r = requests.get(url) html=r.content html_doc=str(html,'utf-8') #html_doc=html.decode("utf-8","ignore") print(html_doc) 方法2:使用r.text Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 r.text 之时,Requests 会使用其推测的文本编码。你可以找出 Requests 使用了什么编码,并且能够使用 r.encoding 属性来改变它. 但是Requests库的自身编码为: r.encoding = ‘ISO-8859-1’ 可以 r.encoding 修改编码
url='http://music.baidu.com' r=requests.get(url) r.encoding='utf-8' print(r.text) 获取一个网页的内容后存储到本地 方法1:r.
一:
Druid在springboot框架下有更加好用的Druid Spring Boot Starter,可以省去原本写Druid的一些配置文件或者@Configuration来配置,直接将配置写在application.yml,使用法更加简单
引用druid架包
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> 引用mybatis架包:
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> 二在application.yml 文件中配置:
spring: profiles: active: ${DEPLOY_ENV} # 环境配置 application: name: service-web #项目名 datasource: # 数据源 url: ${bi.ds.jdbcUrl} username: ${ops.mysql.user} password: ${ops.mysql.password} driver-class-name: ${ops.mysql.jdbc.driverClass} type: com.alibaba.druid.pool.DruidDataSource druid: # 连接池的配置信息 # 初始化大小,最小,最大 initial-size: 5 min-idle: 5 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false # 打开PSCache,并且指定每个连接上PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat,wall,log4j # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.
问题描述:
UEFI对NTFS支持不是很好,所以一般使用FAT32格式FAT32不支持单文件4G+以cn_windows_10_business_editions_version_1903_updated_sept_2019_x64_dvd_2f5281e1.iso为例,其中\sources\install.wim文件就超过了4G,所以就算用fat32做好了启动盘,安装时也会出现install.wim出错,其实是因为文件不完整造成的。 解决方案:
参考官方文档,但是直接运行会出错,需要简单修改
原料:
ultraisowin10镜像假设已经掌握ultraiso制作u盘启动盘的流程 操作:
挂载镜像
右键该镜像 > 打开方式 > windows资源管理器拆分镜像 win+X > windows powershell**(管理员)**输入命令:Dism /Split-Image /ImageFile:J:\sources\install.wim /SWMFile:F:\install.swm /FileSize:4000 /ImageFile:后的J:\sources\install.wim 是用资源管理器打开ISO文件后你找到install.wim所在的路径/SWMFile:后的F:\install.swm 是拆分后生成的swm文件的储存路径,由于这个iso文件是只读的,所以换个不同于wim文件所在路径的路径保存/FileSize:后的4000是子文件最大MB数 然后弹出iso 写入U盘 打开ultraiso文件>打开>打开你的iso,启动>写入>写入硬盘映像选择你的U盘,写入方式用USBHDD+,格式化为FAT32,默认设置就行,然后写入。关闭ultraiso 替换映像文件 打开你的U盘,删掉install.wim,把你生成的install.swm和install2.swm放进去,完事
聚类方法有很多种,其中DBSCAN算法是比较适用毫米波雷达点迹聚类的算法。话不多说,先上图。
原始数据集:
聚类结果:
Dell Power Edge R740 安装部署Vmware vSphere hypervisor(ESXI) 6.7 U3 大家好!这是第一次写博客记录自己的学习及研究过程,感觉以前都没有认证记录过自己学习的一些知识,导致有些自己搞过的东西,过了一段时间就忘记了。
言归正传,此次记录在Dell R740上安装ESXI 6.7 U3
硬件环境准备 1.Dell R740物理机
Intel® Xeon® Silver 4216 CPU *2个
192 GB内存
4T硬盘
2.同一网络的操作机一台(服务器在机房,很吵,Dell R740支持iDRAC远程操作功能)
3,操作机可连接互联网
软件下载 官网地址:
https://www.dell.com/support/home/cn/zh/cnbsd1/product-support/product/poweredge-r740/drivers
下载最新版本的ESXI 镜像
不建议去VMware官网去下载其他版本,原因有二:1、Vmware官网下载要注册账号登录啥的比较烦。2、这个是Dell定制的镜像,对硬件的兼容性更好。
软件操作的前期准备 1.配置Dell R740的iDRAC并远程连接
2.将磁盘阵列创建为虚拟磁盘
以上两步操作可参考文章(https://www.cnblogs.com/iamjianghao/p/11441753.html)中的第二步和第三步
通过iDRAC远程操作安装ESXI 1.使用 Virtual Media映射下载好的ESXI 6.7 iso文件 点击“Connect Virtual Media”按钮
选择本地的ISO镜像文件,并点击“Map Device”按钮
Map Device 后点击Close关闭弹框
2.设置启动项为“Virtual CD/DVD/ISO” 点击“Boot”按钮后选择“Virtual CD/DVD/ISO”,并确认选择。
3.重启服务器 点击“Power”按钮后选择“Power Cycle System (cold boot)”重启电脑
4.重启后自动进入安装页面 重启后进入安装页面
等待资源加载
第一个操作页面为兼容提醒页面,按回车键继续
用户版权协议,按“F11”同意并继续
Python PyPDF2、pdfplumber 提取 PDF 文本、图片内容 安装库安装 pdfplumber安装 PyPDF2 内容提取代码图片提取文本提取完整代码 说明
本方法提取的图片并不算完整,我测试用的是阿里2017年双十一的一份PDF,AliDouble11.pdf,提取过程中有一处报错,部分图片提取不完整
由于PyPDF2 直接提取文本内容对中文支持不友好,因此结合两个库提取
安装库 安装 pdfplumber pdfplumber 可以使用 pip 安装
pip install pdfplumber 安装 PyPDF2 PyPDF2 需要去 GitHub 下载 https://github.com/mstamy2/PyPDF2
下载完成后解压,进入解压的目录 E:\tools\PyPDF2-master
执行 setup.py 进行安装
python setup.py install 不用pip安装的原因是 pip 下载的只更新到 1.26.0 更新日期是 2016年5月19日,只用这个版本无法提取 jpg 格式图片,会报错
Traceback (most recent call last): File "D:/projects/util/pdf_util.py", line 106, in extract_image data = xObject[obj].getData() File "D:\projects\util\venv\lib\site-packages\PyPDF2\generic.py", line 844, in getData decoded._data = filters.decodeStreamData(self) File "
javawab里启动tomcat时报了Failed to initialize component [Connector[HTTP/1.1-80]] 本人是学软件的大二学生一枚,过够了普本的咸鱼大学生活。决定在沉迷打游戏无法自拔的时候悬崖勒马。
看过许多人在博客园上坚持自己,分享自己所学,,,很是敬佩!!!
在别人的博客上真的学到了许多,,,
我想唯有传扬他们的分享精神,才是对他们最大的感谢!!
tomcat解压版里的startup.bat 今天我们老师开始讲javawab了,但我在配置tomcat这个软件上遇到了一个问题!!
在conf/server.xml配置Connector port=80就报Failed to initialize component [Connector[HTTP/1.1-80]],其他端口就不会报错!
作为极度强迫症患者,怎么能忍着用其他端口呢!我就要用80端口!!!
于是我抛弃老师,放弃课堂,要搞好它!
首先 既然是端口占用,那就查占用端口呗!在window打开cmd,输入netstat -nao | find “80”(不会netstat,没关系,netstat -h一下就会咯)
发现本地有一个进程ID为4的程序在占用,那这个ID为4的程序是谁呢!在输入一个tasklist | findstr "4"查找一下
发现一个System,en… 我惊了!!那我想用80不就凉凉了。。系统端口能不能停呢?
但是我找到了一个netsh http show servicestate
详见->我在这看到的
在命令行里输入netsh http show servicestate就有了
但没有对应的ID号啊!请求队列尚未命名!!!仔细一找!在下面的对应的请求队列的地方!
我的上面对应的80端口是第2,3个这里也找第2,3个。他们是同一个ID。
找到这个ID不就好办了吗!打开任务管理器停掉它,不就行了吗!ctrl+alt+.打开任务管理器。找到18584,关掉它就行啦!
最后在试一试tomcat,startup.bat果然没问题了!但要记得如果上次没有shutdown.bat要先shutdown.bat一下哦!!
最后 本渣才疏学浅,如果有路过的大佬看到我有错误的地方希望得到指正。感谢!!
目标 处理存在淘宝滑块验证码,并封装成为工具类。。。。
主要学习以下知识点 方法名称方法说明page.evaluateOnNewDocument添加一个方法,在以下某个场景被调用:1.页面导航完成后,2.页面的iframe加载或导航完成。这种场景,指定的函数被调用的上下文是新加载的iframe。page._client.send向Chrome发送一个协议Page.getResourceContent返回base64编码后的字符串 详细api 可参考
https://blog.csdn.net/mengxiangxingdong/article/details/99237204
开始 本文章代码均在 上传在
https://gitee.com/hugo110/puppeteer-demo
效果图
1.代码 /* 获取浏览器中的缓存资源 目前例子是爬取博客的一个头像 */ const puppeteer = require('puppeteer'); //引入puppeteer库 const pUtil = require('./util/PuppeteerUtil.js'); (async () => { const browser = await puppeteer.launch({ //启动浏览器 headless: false, //代码运行时打开浏览器方便观察 // devtools:true //打开f12界面 }); const page = await browser.newPage(); //打开浏览器的一个tab 页 await page.goto('https://www.baidu.com/'); //访问网址 https://www.baidu.com/ let img_url = "https://www.baidu.com/img/baidu_jgylogo3.gif"; //测试获取图片 let img_str = await pUtil.getResourceContent(page, img_url); //验证获取的图片是否正确 let base64_prefix = 'data:image/png;base64,'; img_url = await base64_prefix + img_str; await page.
阿里云api:https://market.aliyun.com/products/57124001/cmapi024968.html
直接上代码
package com.kevy.aliyun; import static org.apache.commons.codec.binary.Base64.decodeBase64; import static org.apache.commons.codec.binary.Base64.encodeBase64; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.http.HttpResponse; import org.apache.http.util.EntityUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.kevy.util.HttpUtils; public class TestAliyunTable2 { private static final String appCode = "你的appCode";//替换该处 public static void main(String[] args) { //待识别图像-实际存在地址 String imgFile = "C:\\Users\\Administrator\\Desktop\\test\\test.jpg"; //保存的excel路径 String saveFile = "C:\\Users\\Administrator\\Desktop\\test\\test.xlsx"; transferExcel(imgFile, saveFile); } public static void transferExcel(String imgFile, String saveFile) { String host = "
1. BottomSheetBehavior 简介 An interaction behavior plugin for a child view of CoordinatorLayout
to make it work as a bottom sheet.
链接:https://developer.android.google.cn/reference/android/support/design/widget/BottomSheetBehavior?hl=en
划重点:一定要是CoordinatorLayout的子view,不要混淆成 ConstraintLayout。否则就会出现:BottomSheetBehavior is not a child of CoordinatorLayout 的错误
BottomSheetBehavior 可以和 CoordinatorLayout 的子View 一起,实现底部弹窗效果,手指拖动该面板,可以实现随手指上下滑动,如图:
2. 实现方法 2.1 gradle 中添加依赖: implementation 'com.android.support:design:25.3.0' 2.2 布局文件引入 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/cl" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.widget.NestedScrollView android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="wrap_content" app:behavior_hideable="true" app:behavior_peekHeight="50dp" app:layout_behavior="@string/bottom_sheet_behavior" > <!-- NestedScrollView里设置你的底部表长什么样的,也可以根据实际情况使用别的布局--> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout> PS: app:layout_behavior="@string/bottom_sheet_behavior" 这句一定不能省略,用于和BottomSheetBehavior 建立联系。 且该字符串已在库中定义,直接这样引用即可。否则,会出现如此错误:
先实例化,后调用。不能直接import进来
java.lang.ClassNotFoundException: org.apache.http.Header
在项目里使用http发送post请求,今天在做一个老项目的时候发现代码编译打包都没问题,但是部署服务器后会出现 java.lang.ClassNotFoundException: org.apache.http.Header这个问题,从问题的描述看应该是缺少Header这个类,逐一排查后发现是缺少了httpcore-4.4.6.jar这个包,导入重启解决!老的项目使用的是springMVC+spring+Mybatis的架构,重新启动,有可能会出现jar包缺少,版本太老的问题,为避免再次犯错,记录一下~
在python中,用pandas处理数据非常方便。
但是有时候从其他地方读取数据时,会有异常值需要处理。比如,我们要从excel读取数据然后调用接口写入数据库时,读取到的空值是NaN,但是,接口接收的对应单元格数据应该是None,这时候怎么处理呢?当然,用pandas做这个事也是非常容易的。示例如下:
原始数据:
示例代码:
import pandas as pd df = pd.read_excel('data/test_data.xlsx') # 将非空数据保留,空数据用None替换 df = df.where(df.notnull(), None) print(df) 输出结果:
id value 0 1 100 1 2 None 2 3 None 3 4 50
Spring Framework 开发工具:IDEA Professional,JDK1.8及以上,Maven工具
容器核心组件:
Beans:表示对所以Bean对象的管理,主要是包含了对象间的关系配置,以及一些对象实例化操作;
Core:包含了最底层的开发支持,例如:依赖的注入关系、资源文件的访问,数据类型的转换;
Context:提供的是一个完整的容器上下文,在这个上下文之中可以处理对象的生命周期或者是事务;
表达式语言模块: 利用SpELl实现表达式语言的操作,以增强String的功能。
切面编程:
AOP:是整个Spring的灵魂所在,利用切面编程来解决所有的辅助型操作;
Aspect:切面编程的语法支持;
Instrumentation:主要用于检测JVM在运行中代码的动态处理过程;
数据访问模块:
JDBC:在Java之中,对于数据库的操作只有JDBC一种操作形式,在Spring中提供有ORMapping框架,这个框架就利用JDBC半原生完成;
ORM:ORMapping框架的处理操作可以方便的整合:JDO、Hibernate、iBatis和MyBatis等常见组件;
OXM:提供了一个对象对XML文件之间的互相转换;
JMS:提供有消息服务的支持;
Transactions:在数据访问模块支持事务的操作处理;
Web支持模块:
MVC:Spring提供有自己的MVC实现(是目前实现最好的一种);
Struts:Spring方便的支持Struts2.x的管理;
Servlet:自己复制处理MVC的Servlet程序类;
整个Spring完成承办了一个项目能够独立开发并且可以容纳其他框架的综合性框架。
Spring中避免了关键字new造成耦合的问题,Spring不需要进行明确的引用关系传递,直接通过配置完成,Spring编程 = Factory设计模式+Proxy设计模式。
控制反转IOC(Inversion Of Control): 是一种包装的技术类型,使得所有对象实例化的处理操作都不再需要关键字new,控制反转指的就是将对象的创建权反转给了Spring,其作用是实现了程序的解耦合;
底层实现原理:工厂设计模式+反射+XML配置文件。 对于DAO持久层(data access object,数据访问对象),先创建一个接口,然后再创建接口对应的实现类。
创建项目:
首先用IDEA创建项目,如下图:
后面选择Spring支持包就行了,然后有Maven的仓库路径,选择自己已安装的路径就行了。
如下图创建resources文件夹,右击选择MakeAs-> Resources Root,然后创建applicationContext.xml。
输入以下代码:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans> 之后创建Service文件夹,创建IService接口,提供 一个 dosomething();方法,然后写一个该接口的实现类IServiceImp:
@Override public void dosomething() { System.out.println("This is My first Spring project"); } 之后创建一个测试类test,使用ApplicationContext创建ctx对象调用 applicationContext.xml文件,获取Iservice的实现类,
post发起请求参数可以有很多形式,json、map,最直接的就是直接传,可一个传一个,也可以传多个。
前台请求(两个参数)
var url2 = "<e:url value='sendCode.e' />" $.post(url2, {id:findPwdNumber,validNum:validNum},function (data) { var message_code = '<%=request.getAttribute("PwdMsg_code")%>'; alert(message_code); }); 后台接收
public String sendCode(String id,String validNum,HttpServletResponse response,HttpServletRequest request) throws SQLException { System.out.println("=================验证码接口接口开始"); System.out.println("validNum:"+validNum); String rCodePwd = String.valueOf(request.getSession().getAttribute("rCode")); if(validNum==null||(validNum!=null&&validNum.length()==0)){ request.setAttribute("PwdMsg_code","请输入验证码!"); return "pages/frame/findPwd.jsp"; }if(!validNum.equals(rCodePwd)){ request.setAttribute("PwdMsg_code","验证码不正确!"); return "pages/frame/findPwd.jsp"; } //验证成功后销毁session中验证码 request.getSession().removeAttribute("rCode"); }
pandas的DataFrame的apply函数可以实现对指定的轴进行遍历操作,这是个很方便也很常用的函数,但是问题在于,当我们的数据量较大,比如有50万行,这时要对50万行进行逐行遍历的话,如果对每行的操作用到了Series索引,那么这将是一个非常耗时的过程,因为对于pandas来说,索引操作是低效的,这种低效再经过50万行放大,那么性能就会显得很差。对此,我们可以通过numpy的apply_along_axis函数替代,可以实现一样的功能,但是由于numpy的ndarray的索引相对更加高效,所以性能上会有很大的提升。
import pandas as pd import numpy as np df=pd.DataFrame(np.arange(800000).reshape(200000,4),columns=list('abcd')) t1=time.time() s1=df.apply(lambda x:x['a']+x['d'],axis=1) t2=time.time() print(t2-t1) arr=df.values t3=time.time() s=np.apply_along_axis(lambda x:x[0]+x[3],axis=1,arr=arr) t4=time.time() print(t4-t3) # output: # 9.685098886489868 # 1.3745567798614502 可以看到,性能提升了7倍多,如果数据量更大,性能提升会更加的明显。
对于apply_along_axis函数的使用,相比于DataFrame的apply函数,有以下几点需要特别注意:
1、apply_along_axis本质上还是一个for loop,只是其数据结构上性能会更佳,所以整体的速度会更快;
2、如果ndarray的数据类型是object,那么在使用apply_along_axis时,其会进一步的将object转为numpy的其他数据类型,因此这时就需要特别注意,特别注意第一个inner loop遇到的元素,之后将以此元素在numpy中的数据类型为准进行转换,这可能会引起数据类型不兼容的问题,会抛出异常或者产生数据误差,具体可看笔者的这篇文章。
3、axis参数只能接受一个int值,因为默认func参数中关于arr的输入只能是一个一维的array。
4、ndarray在形式上区别于DataFrame的重要的一点是,前者只有数字索引,而后者有标签索引,很多时候,标签索引给了相应的列或者行以明确的含义,这是很重要的,在脚本逻辑上有时也是必要的;那么如何在ndarray中也实现标签索引呢?我们只需要额外的构建一个字典,即关于标签和整数之间的映射,这样我们可以通过这个字典作为标签到数字的中转站,从而实现在ndarray中也有标签索引。
5、如果需要对多条轴进行同一个函数的操作,可以利用numpy.apply_over_axis,其axis参数可以指定多轴,其运算过程为:现在第一个传入的轴上做运算,得到结果后再在第二个轴上对第一步得到的结果做相同的函数操作,以此类推,返回结果。
SpringCloud eureka client无法正常启动,配置application.yml不生效。下面是相关配置:
application.yml
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ spring: application: name: eurekaclient cloud: loadbalancer: ribbon: enabled: false server: port: 8080 pom.xml相关依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.imooc</groupId> <artifactId>eurekaclient</artifactId> <version>0.0.1-SNAPSHOT</version> <name>eurekaclient</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Hoxton.RC2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.
推荐一款功能强大而且轻巧的解密工具,方便开发过程中需要去解密不同加密类型的密文。
找不到下载的可以私信我~~
目录
Python基础(六)--类与对象
1 类与对象的基本概念
1.1 什么是对象
1.2 什么是类
1.3 类与对象的关系
2 定义与初始化
2.1 类的定义
2.2 对象的初始化
2.3 动态增加属性方法
3 类成员
3.1 类属性与实例属性
3.2 类方法与实例方法
3.3 静态方法
3.4 类与实例
4 魔法方法
5 动态属性
6 面向对象与面向过程
7 面向对象的三大特征
7.1 封装
7.2 继承
7.3 多态
Python基础(六)--类与对象 1 类与对象的基本概念 1.1 什么是对象 对象具有属性和行为,属性多体现为名词,而行为多体现为动词。
1.2 什么是类 类,其实就是指一个类别,具有相同属性与行为的所有对象构成的一个整体。
1.3 类与对象的关系 (1)类是对象的抽象,而对象是类的具体表现形式
(2)类是设计的模板,而对象是该模板设计出的具体产物
2 定义与初始化 2.1 类的定义 使用class关键字定义类,如下:
class 类名:
类体
想让对象具备那些功能(属性和行为),就需要在类中指出。就需要在现实与Python程序中进行一种映射,对象的属性,通过令对象绑定一个变量来实现,而对象的行为,通过在类内定义方法来实现。所谓方法,其形式与函数非常相似,只不过是定义类的内部,关联了某个对象而已。
self:在两个方法中,都具有一个参数:self。该参数用来表示当前的对象(调用该方法的时候,所使用的对象。简单说,就是谁调用了这个方法,当前对象就是谁)。
如果仅仅定义了类,而没有为类具体化(创建对象),是不能够使用类中定义的功能的,通过对象调用方法时,该对象就会隐式的传递给方法的第一个参数(无需我们显式传递)。
# 定义一个学生类 class Student: def study(self): print("
排序算法是《数据结构与算法》中最基本的算法之一。
排序算法可以分为内部排序和外部排序。
内部排序是数据记录在内存中进行排序。
而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。
用一张图概括:
时间复杂度与空间复杂度
关于时间复杂度:
平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。
线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序;
O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序
线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。
关于稳定性:
稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。
不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。
1. 冒泡排序 1.1 算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
1.2 动画演示
冒泡排序动画演示
1.3 参考代码
1// Java 代码实现 2public class BubbleSort implements IArraySort { 3 4 @Override 5 public int[] sort(int[] sourceArray) throws Exception { 6 // 对 arr 进行拷贝,不改变参数内容 7 int[] arr = Arrays.
一、mysql调优
1.1 报错:
Mysql: error 1040: Too many connections
1.2 原因:
1
1、访问量过高,MySQL服务器抗不住,这个时候就要考虑增加从服务器分散读压力。<br>2、MySQL配置文件中max_connections值过小,默认151。
1.3 最优计算方法:
服务器响应的最大连接数值占服务器上限连接数值的比例值在10%以上,如果在10%以下,说明mysql服务器最大连接上限值设置过高。
Max_used_connections / max_connections * 100% = 2/151 *100% ≈ 1%
#默认最大连接数
mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.00 sec)
#调整最大连接数
mysql> set global max_connections = 1000;
Query OK, 0 rows affected (0.00 sec)
#查看最大连接数
mysql> show variables like '%max_connections%';
最近在使用微服务遇到一个feign 405的问题,一直很困惑,提出来希望大神们指导一二。
我们用的是springCloud的openFeign:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> feign:
@PostMapping(value = "/automatic_sign_for", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) void automaticSignFor() throws Exception; Controller:
@ApiOperation(value = "Automatic sign for orders that have no sign in status information in a period of time after delivery", tags = {"Automatic sign for APIs"}, nickname = "Automatic sign for") @ApiResponses(value = { @ApiResponse(code = 200, message = "Succ"), @ApiResponse(code = 401, message = "You are not authorized to access to this API"
启动安装 从网上下载SQL Server 安装包,解压,双击目录中的setup启动安装向导,出现【SQL Server安装中心】窗口,如下图所示.
我这下载的是SQL Server 2014的,
在左侧选择“安装”类,然后点击“全新SQL Server独立安装或向现有安装添加功能”链接 操作如图所示。
密钥许可 在“产品密钥”页,输入产品密钥,单击【下一步】按钮;在“许可条款”页,勾选“我接受许可条款”复选框,单击【下一步】按钮.
操作如图所示。
选择要安装的功能 在“设置角色”页,选中“SQL Server功能安装”选项,单击【下一步】按钮;在接下来的“功能选择”页,于“功能”区域中勾选要安装的功能组件,我这是全选,大家可根据需求选择相应的,操作如图所示。
出现问题:需要Microsoft.NET Framework 3.5 Service Pack1 解决办法:
控制面板-程序-(启用或 关闭Windows 功能)
下载有点慢
设置数据库用户密码 当安装向导进入到“数据库引擎配置”页后,选择身份验证模式为“混合模式”,我这设置的系统管理员帐户sa的密码为123456,必须记住自己所设的密码,后面在开发程序连接数据库时要用!输完密码并确认后,单击【添加当前用户】按钮,单击【下一步】按钮,操作如图所示。
其他配置 在“Analysis Services配置”和“Distributed Replay 控制器”页,都是单击【添加当前用户】按钮后再点【下一步】按钮,如图所示。
在“Distributed Replay 客户端”页,输入控制器名称,单击【下一步】按钮,如图所示。
开始安装 全部配置完成后,向导进入“准备安装”页,显示已准备好安装的内容项,如图所示,用户在确认无误后就可单击【安装】按钮进入安装过程,进度条显示安装的进度。
(7)安装完成
稍候片刻,向导进入“完成”窗口,如图所示,单击【关闭】按钮,系统会弹出消息框提示用户重启,点【确定】重新启动计算机。
使用PHP实时读取日志,文件大概500M左右,大小不固定。如采用正常读取,会直接内存溢出。可采用fopen的逐行读取、分块读取、以及Php的SPL类库
第一种:使用fopen逐行读取(测试在日志文件较大耗时时间会比较长,如果只是读取一次,可直接使用读取。 如果对日志实时计算处理,可采用SPL类库结合fopen来实现)fseek分块读取此处就不提供示例代码,可自行查找。 /** * 读取文件数据 * @return array */ public function getLog() { //当前LOG路径 $filename = '文件路径'; $data = []; //读取数据 防止内存溢出PHP报错,采用文件指针逐行读取 $fh = fopen($filename, 'r'); //声明初始变量 $result = []; while (! feof($fh)) { $line = fgets($fh); var_dump($line); } fclose($fh); } 第二种:针对需要使用PHP实时读取LOG并进行业务处理的需求(采用SplFileObject + fopen)
思路为:增加行数冗余,每次只处理新产生的数据,不对全部数据进行处理
每天第一次执行,获取当前文件全部数据,并记录当前执行的行数作为冗余,第二次之后根据第一次冗余的行数,使用SplFileObject的seek转到最后执行位置,只处理新产生LOG记录。 /** * 返回当前文件行数 * @return string */ public function countLine($file){ $fp=fopen($file, "r"); $lineNum=0; while(!feof($fp)) { //每次读取2M , 此处可根据实际需求进行调整每次读取文件大小 if($data=fread($fp,1024*1024*2)){ //计算读取到的行数 $num=substr_count($data,"\n"); $lineNum+=$num; } } fclose($fp); return $lineNum; } /** * 获取Log文件从M 到 N 行数据 * @return array */ public function getFileLines($filename, $startLine = 1, $endLine = 50, $method = 'rb'){ $content = []; $count = $endLine - $startLine; $fp = new \SplFileObject($filename, $method); // 转到第N行, seek方法参数从0开始计数 $fp->seek($startLine - 1); for ($i = 0; $i <= $count; ++$i) { //获取当前行内容 $content[] = $fp->current(); $fp->next(); // 下一行 } //过滤之后返回 return array_filter($content); }
Apache james安装配置笔记(一) Apache james安装配置笔记下载安装基本配置配置keystore配置webAdmin 启动james验证webAdmin Apache james安装配置笔记 公司要求使用开源的邮件服务系统,架构组的同事推荐了james这个项目,记录一下安装配置的过程
james项目地址
下载安装 james提供spring和guice两种注入方式,目前仅guice方式支持restful接口,为了方便开发管理工具下载的james包为guice+jpa,包下载路径为
https://archive.apache.org/dist/james/server/3.3.0/,下载
james-server-jpa-guice-3.3.0.zip 基本配置 配置keystore 解压压缩包,进入james的目录,生成keystore
cd ${james-path} keytool -genkey -alias james -keyalg RSA -keystore conf/keystore 需要记住输入的密码,然后进入conf目录,修改
smtpserver.xm
l文件,将secret里改为自己创建keystore时输入的密码
<smtpserver enabled="true"> <jmxName>smtpserver-TLS</jmxName> <bind>0.0.0.0:465</bind> <connectionBacklog>200</connectionBacklog> <tls socketTLS="true" startTLS="false"> <keystore>file://conf/keystore</keystore> <secret>yourkey</secret> <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider> <algorithm>SunX509</algorithm> </tls> <connectiontimeout>360</connectiontimeout> <connectionLimit>0</connectionLimit> <connectionLimitPerIP>0</connectionLimitPerIP> <!-- Authorize only local users --> <authRequired>true</authRequired> <authorizedAddresses>127.0.0.0/8</authorizedAddresses> <!-- Trust authenticated users --> <verifyIdentity>false</verifyIdentity> <maxmessagesize>0</maxmessagesize> <addressBracketsEnforcement>true</addressBracketsEnforcement> <smtpGreeting>JAMES Linagora's SMTP awesome Server</smtpGreeting> <handlerchain> <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/> <handler class="
rtt 计算方法
作者:LanPZzzz
文章目录 1. 请查看 [\[webrtc\] rtcp模块中rtt时间计算](https://blog.csdn.net/dittychen/article/details/70214675)2. 因为我们查看的是A->B,B->A 的数据互通,所以在rtt 的计算的,不管是A端计算还是B端计算,都应该是一样的3. 我们在测试的时候4. BR,RR 包5. rtt 计算OK,rtt 计算完成 1. 请查看 [webrtc] rtcp模块中rtt时间计算 2. 因为我们查看的是A->B,B->A 的数据互通,所以在rtt 的计算的,不管是A端计算还是B端计算,都应该是一样的 3. 我们在测试的时候 使用delay,把导到的包延迟发放,rtt没有变,但是按照计算应该是要变的啊 4. BR,RR 包 A (发送BR 包) -> B,BuildSR
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) { 。。。 rtcp::SenderReport* report = new rtcp::SenderReport(); report->SetSenderSsrc(ssrc_); 在report 放入 A 端的当前时间 report->SetNtp(ctx.now_); report->SetRtpTimestamp(rtp_timestamp); report->SetPacketCount(ctx.feedback_state_.packets_sent); report->SetOctetCount(ctx.feedback_state_.media_bytes_sent); report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_)); 。。。 } B (接收到BR 包)
void RTCPReceiver::HandleSenderReport(const CommonHeader& rtcp_block, PacketInformation* packet_information) { rtcp::SenderReport sender_report; if (!
video nack 模块
作者:LanPZzzz
文章目录 1. video nack 模块 在 modules\video_coding\nack_module.cc 中2. NackModule::OnReceivedPacket 获取 video rtp 包3. NackModule::AddPacketsToNack4. NackModule::GetNackBatch,分2种,根据 seq 和 timestamp 进行选择重发,在OnReceivedPacket 是 seq, 任务线程中是 ts5. NackModule::Process, 间隔时间 NackModule::TimeUntilNextProcess6. nack 中的rtt 是由线程驱动传递的7. nack 中的rtt 是怎么计算的,请看第三十章节 1. video nack 模块 在 modules\video_coding\nack_module.cc 中 2. NackModule::OnReceivedPacket 获取 video rtp 包 int NackModule::OnReceivedPacket(uint16_t seq_num, bool is_keyframe) { rtc::CritScope lock(&crit_); // TODO(philipel): When the packet includes information whether it is // retransmitted or not, use that value instead.
audio neteq
作者:LanPZzzz
文章目录 1. modules\audio_coding\neteq 中2. InsertPacket 的流程,在学习十三中,我们已经简单的看到,这里就不介绍了。我们看下NetEqImpl::InsertPacketInternal 都作了哪些动作3. NetEqImpl::GetAudioInternal 获取数据jitter 控制其播放,应该是用10ms 的速度控制的,复杂的一笔。。。 待续4. 参照,感谢 1. modules\audio_coding\neteq 中 neteq 的发起点有2个,neteq_impl.cc
NetEqImpl::InsertPacket // 接收数据 NetEqImpl::GetAudio // 发送数据 2. InsertPacket 的流程,在学习十三中,我们已经简单的看到,这里就不介绍了。我们看下NetEqImpl::InsertPacketInternal 都作了哪些动作 int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header, rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp) { if (payload.empty()) { RTC_LOG_F(LS_ERROR) << "payload is empty"; return kInvalidPointer; } 生成Packet 放入PacketList 中 PacketList packet_list; // Insert packet in a packet list. packet_list.push_back([&rtp_header, &payload] { // Convert to Packet.
有疑问的题已加粗,请读者谨慎考虑,若是知道确切答案,请在评论区指出,感激不尽
(文章判断选择来自于pta做题学习的总结,只对不容易记忆【或者我顺手复制】的内容进行总结和整理,如果涉及侵权或者其他不宜事宜,请通知我立刻删除)
2019年11月11日 第一次更新 1-1 java语言中不用区分字母的大写小写。 (F)
1-2 java.lang包是Java的核心类库,它包含了运行Java程序必不可少的系统类。(T)
1-3 package语句必须放到java程序的最开始。(T)
1-4 Java中所有的I/O都是通过流来实现的。(T)
1-5 Object是Java中所有类的共同父类。(T)
1-6 系统自动引入java.lang包中的所有类,因此不需要显示地使用import语句引入该包的所有类。(T)
1-7 java.lang包是Java 的核心类库,它包含了运行Java程序必不可少的系统类。(T)
1-8 在Java程序中,可以使用protected来修饰一个类. (F)
类的修饰符分为:可访问控制符和非访问控制符两种。
可访问控制符是:公共类修饰符 public
非访问控制符有:抽象类修饰符 abstract ;最终类修饰符 final
----也就是protected是不能用来修饰一个类的
java修饰符号
1-9 在Java程序中,可以使用private来修饰一个类
private 为私有的,只能在本类中访问,用于修饰属性和方法
1-10 如果一个类的声明中没有使用extends关键字,这个类被系统默认为是继承Object类。(T)
1-11 如果一个成员变量被修饰为final的,就是常量,常量必须赋给初值,而且不能再发生变化(T)
1-12 不允许使用final来修饰abstract方法。 (T)
抽象类中的抽象方法不能是final,但是非抽象方法前加final可以编译通过因为abstract和final相互排斥,前者专用于继承,后者禁止继承
抽象类中的抽象方法不能为static
非抽象方法可以为static
包裹类Integer、 String 、Float、 Double等都是final类,不能被继承!
原文链接:原文链接
1-13 对于abstract类,不能创建该类的对象。(T)
有些判断题是说“对于abstract类,不能new该类的对象。”都是错误的
相关资料
抽象类abstract
基本概念:通过在类定义前面放置关键字 abstract,可以将类声明为抽象类
抽象类是无法通过new创建的,要通过产生子类,由子类创建对象
1-14 子类如果想使用父类的构造方法,必须在子类的构造方法中使用,并且必须使用关键字super来表示,而且super必须是子类构造方法中的头一条语句。
稍微查了一下,有些题目没有最后一句《super必须是子类构造方法中的头一条语句》,不加语句是对的,加语句也是对的
1-15 如果在子类的构造方法中,没有使用关键字super调用父类的某个构造方法,那么默认有super();语句,即调用父类的不带参数的构造方法。
1.子类继承父类的方法属性,并重写父类的方法,子类修饰符不能比父类方法的修饰符的范围狭窄。
2.子类必须在构造函数中使用super()来调用父类的构造函数
说明:1.父类没有写构造函数(系统默认有一个无参构造函数),子类可以不写构造函数(可以理解为:子类的系统默认构造函数,默认调用了super();)
2.如果父类有无参构造函数,子类可以不写构造函数(同上理解)
3.如果父类有有参构造函数,则子类必须在自己的构造函数中显示的调用父类的构造函数即super(参数名)
在周期中使用switch-case
switch(num){ case "1":return 'a'; case "2":return 'b'; case "3":return 'c'; default:return 'd'; } render中使用switch-case
render: inputMethod => ( <div> {( ()=>{ switch(inputMethod){ case "1": return '日期框'; case "2": return '初始、结束日期框'; case "3": return '文本框'; default:return '数据为空'; } } )()} </div> )
一、什么是可变参数函数 C语言允许定义参数数量可变的函数,这称为可变参数函数(variadic function)。这种函数需要固定数量的强制参数,后面是数量可变的可选参数。
其中,强制参数必须至少一个,可选参数数量可变,类型可变,可选参数的数量由强制参数的值决定,或由用来定义可选参数列表的特殊值决定。
其实我们早就接触过可变参数函数了,C 语言中最常用的可变参数函数例子是 printf()和 scanf()。这两个函数都有一个强制参数,即格式化字符串。格式化字符串中的转换修饰符决定了可选参数的数量和类型。(是吧,printf中可以有自定义个%d,没毛病)
可变参数函数的参数列表的格式是,强制性参数在前,后面跟着一个逗号和省略号(…),这个省略号代表可选参数。比如:int fun(int, …) (我随便举的例子啊)
.
.
二、可变参数函数的实现 1、问题引入 我们先来思考这样一个问题,作为本节的引入:
如果我们要预先写一个可变参数的累加求和函数,其强制参数类型为int,用它来表示我们一共要传入多少个可变参数。于是我们大概可以有这么一个框架:
double getSum(int NumofPara, ...) { int i = 0; double sum = 0.0; for( i = 0; i < NumofPara; i++ ) { sum += ?? } } 发现什么问题没有?
由于已经知道要传入多少个可变参数,所以求和思路就是,for循环遍历NumofPara次,每次都把sum加上一个可变参数。
思路很清晰,没毛病。但是,问题来了。由于是可变参数,我们无法提前得知可变参量的名字,也就没法访问这些可变参数。(你参数列表里都是一串省略号了,你怎么可能提前知道变量名,所以自然而然也无法表示、无法访问这些变量了)
2、实现思路 为了解决上述问题,C语言规定:
当编写可变参数函数时,必须用 va_list 类型定义参数指针,以获取可选参数。可变参数函数要获取可选参数时,必须通过一个类型为 va_list 的对象来进行访问,它包含了参数信息。
这种类型的对象也称为参数指针(argument pointer),它包含了栈中至少一个参数的位置。可以使用这个参数指针从一个可选参数移动到下一个可选参数,由此,函数就可以获取所有的可选参数。va_list 类型被定义在头文件 stdarg.h 中。
这么说可能太过官方,太抽象了。我们来举个例子。
假设我们有一个可变参数函数getSum(int NumofPara, …),然后现在我们代入具体值,比如getSum(3, 7, 8, 9),通过上面的介绍我们知道,第一个3是强制参数,表明后面跟了3个可变参量,而后面的7、8、9则为具体的可变参量。
根据C语言的要求,我们需要在getSum(int NumofPara, …)函数中定义一个va_list类型的指针。