GP服务简介 Geoprocessor是用py写的脚本,它简单语法,并可以调用大部分ArcGISToolBox里的现有工具,十分强大。 Geoprocessing被称之为地理处理,实际上就是ToolBox里的各种tools用py连接起立,连续处理而不用反复操作单个工具,流程化了。 ArcGIS还提供了一个可视化的构建Geoprocessor工具,叫ModelBuilder。 在WebGIS开发当中,虽然ArcGIS API提供给我们很多的接口,但是现实需求总是千变万化的,很多可能部分需求在我们的API中没有实现,而GP服务就弥补了这一个缺点,我们可以将ArcGIS中的GP工具发布为服务,提供给我们前端调用。
GP服务从返回类型上可以分为:
返回矢量数据返回栅格数据 GP服务的参数 在ArcGIS中,GP工具的参数和GP服务的参数是有一个对应参数的,在现实开发中,GP服务总是容易调用失败,这很有可能便是GP服务的参数不对应导致,因此:当我们发布GP服务时,参数便是我们高度重视的地方。以下是GP服务和GP工具参数对应表: GP服务的调用方式 我们可以在官方API Reference中esri/tasks/Geoprocessor查看调用GP接口的详细信息。 官方中开始描述中: Represents a GP Task resource exposed by the ArcGIS Server REST API. A GP Task resource represents a single task in a GP service published using the ArcGIS Server and it supports one of the following operations:
“execute” - performed on a GP Task resource when the execution type is synchronous.“submitJob” - performed on an asynchronous GP Task resource.
ORACLE导入遇到ORACLE错误959解决方法 ORACLE
在导入数据库文件时,有一张表未导入成功,报了如下错误:
IMP-00003: 遇到 ORACLE 错误 959
ORA-00959: 表空间 'XXXXXXXXXXX' 不存在。
查询的确没有对应的表空间:
select * from dba_data_files where tablespace_name = 'XXXX' 添加上对应的表空间,再重新导入:
例子:
create tablespace ts_something logging datafile '/dbf1/ts_sth.dbf' size 32m autoextend on next 32m maxsize 2048m extent management local; create tablespace emaoyi logging datafile 'D:\app\Administrator\product\11.2.0\dbhome_1\database\emaoyi.dbf' size 10m autoextend on next 10m maxsize 20480m extent management local; 导入成功。 注:表空间自增长,其大小也不会超过最大大小,因此在设置大小时可以将MAXSIZE 设置为unlimited;
License
可以拷贝、转发,但是必须提供原作者信息,同时也不能将本项目用于商业用途。
论文题目:Neural Collaborative Filtering 参考资料:https://www.cnblogs.com/HolyShine/p/6728999.html
尽管最近的一些工作已经把深度学习运用到了推荐的任务当中,但只是用深度学习给一些辅助的信息建模,例如项目的文字描述或音乐的声学特征等等。在表示用户与项目之间的交互是仍然使用矩阵分解等用内积来建模。这篇文章的工作主要是用多层神经网络给用户和数据之间的交互建模,我们数据主要基于隐式反馈,例如浏览记录、购买记录等等。在本文中,我们探讨了如何利用DNN来模拟噪声隐式反馈信号的中心问题。
显示反馈(explicit feedback):用户直接反映其对产品的喜好信息,如评分等等。 隐式反馈(implicit feedback):间接反映出用户对于产品的喜好,如:购买历史、浏览记录、搜索记录等
论文贡献 1、我们提出了一种神经网络结构来模拟用户和项目的潜在特征,并设计了基于神经网络的协同过滤的通用框架NCF。 2、我们表明MF可以被解释为NCF的特例,并利用多层感知器来赋予NCF高水平的非线性建模能力。 3、我们对两个真实数据集进行广泛的实验,以证明我们的NCF方法的有效性和对使用深度学习进行协作过滤的承诺。
准备工作 符号说明 M M 和 NN 分别为项目和用户的数目。 Y∈RM×N Y ∈ R M × N 表示从用户的隐性反馈得到的用户-项目交互矩阵,定义如下:
这里, yui y u i 值为 1 1 仅表示用户 uu 与项目 i i 之间有交互信息,并不意味 uu 喜欢 i i ;同样的yuiyui 值为 0 0 也并不表示uu 讨厌 i i 。这其中缺少负反馈信息。这也是隐性反馈的一个挑战,因为它给用户偏好信息带来了干扰。
隐式反馈的推荐任务可以表示为预测矩阵 YY 中未观察到交互的entry的分数 y^ui=f(u,i|Θ) y ^ u i = f ( u , i | Θ ) ,这个分数最终用来给项目排名。
假设已经设置好xshell代理端口1080
# 设置代理 git config --global http.proxy 'socks5://127.0.0.1:1088' git config --global https.proxy 'socks5://127.0.0.1:1088' # 清除代理 git config --global --unset http.proxy git config --global --unset https.proxy 能直接访问后,把代理配置去掉就可以了
1、xrandr(查看当前分辨率和所有分辨率选项)2、xrandr -s 【表示分辨率的 宽X高】(设置分辨率)
一行数据包括:Hor Sync(行同步)、 Hor Back Porch(行消隐)、 Hor Active Video(行视频有效)和 Hor Front Porch(行前肩);一场数据包括:Ver Sync(场同步)、 Ver Back Porch(场消隐)、 Ver Active Video(场视频有效)和Ver Front Porch(场前肩)。
1280*800@60Hz:
4k:
HFP前沿(行前肩),HBP后沿(行消隐),HSW行同步,HACTIVE行有效;
VFP前沿(场前肩),VBP后沿(场消隐),VSW场同步,VACTIVE场有效;
由于最近一直做的是传统项目,而且电脑不让联网,所以很少用到maven,最近想把一个maven项目部署到tomcat中,发现自己不会弄了,依稀记得在上家公司(当时自己还是刚毕业的菜鸟),项目是配置的jetty+tomcat;只需要run一下,然后就可以加载tomcat启动,自动调用浏览器打开项目首页。当时这个技术自己还是很是高深(现在也是高深,自己还不会搭建,有会的朋友可以给我留言)。下面进入正题,
我的工具 是 eclipse +tomcat7 首先在eclipse中建立一个maven项目,
然后在tomcat的的conf文件夹中,修改tomcat-user.xml,文件,增加启动权限;如图
下一步是在maven的conf文件夹中,修改settting.xml文件,配置一个server,如图
最后是在项目的pom.xml文件中,添加一个插件,如图
然后在启动tomcat的情况下(自己去tomcat的bin文件夹中双击starup.bat(前提是window环境)),接着在右击项目,run as--->maven build ,看控制台打印出成功的信息
本文转载自:点击打开链接
请求网络未出错,但解析数据时发现返回的数据为:okhttp3.internal.http.RealResponseBody@ed23219,如下所示:
上面是经过处理的url网址。下面查看返回的数据,并不是预期数据。看了这篇文章之后,尝试了一下,将下面的语句:
String result = response.body().toString(); //原句 更改为:
String result = response.body().string(); //修改后 运行程序成功显示数据:
实属鬼才也,这也可以。怎么想到的呢。
问题导读: 1、CM是什么?
2、CDH是什么?
3、CM+CDH是什么?
4、什么是企业大数据平台?
5、如何用CM+CDH构建企业大数据平台?
..........
带着种种疑问让我们开启真正的企业级大数据平台搭建之旅。
随着互联网,尤其是移动互联网和智能移动设备的高速发展和大面积普及,数据产生的速度以及数据累积的规模已经超过了以往任何时候,所以我们正在或者已经步入了大数据时代。对于企业来说,企业所拥有的大规模数据正逐渐成为一种重要的生产要素,但是如何盘活企业海量数据资产,充分挖掘大数据背后的价值成为新的挑战。同时也带来了很大的机遇,通过对企业海量数据的科学分析,为精益化管理企业提供决策依据,为市场和客户的精准化营销提供数据支持,为公司创收提供新的动力,快速扩展市场业务,重塑企业核心竞争力,不断地把企业打造成拥有数据驱动核心竞争力的创新型企业。
一、如何实现上述目标呢? 首先,企业大数据平台的建设和运营无疑是重中之重,这也正成为企业信息化建设的核心任务和目标。通过构建企业大数据平台,对企业大规模数据进行科学高效的管理、分析、挖掘、监控、可视化,为公司内部产品的策划、运营、营销、财务、决策等提供科学精确的数据支撑,提高企业运营效率、最大化释放数据价值。
二、如何构建企业大数据平台呢? 当然这是一个比较大的话题,也是一个比较复杂的事情,但是核心内容是不变的,无非就是对企业大规模数据的管理、分析和结果可视化呗。现在企业有了这么多的数据,怎么办?就像生孩子一样,你不能只管生不管养呀。你还想靠他给你养老送终呢?所以说数据也一样,有了这么多数据,你又想从数据里获取对企业有用的价值,怎么办?总得先存储起来吧,先养着。OK,那么现在就带来了一个问题,怎么存?也就是如何解决大规模数据的存储问题?
(一)如何解决大规模数据的存储问题? 这是很大的一块内容,我们先长话短说,化繁为简。我们最终要解决的是大规模数据的存储,数据规模小的话很好解决,假设数据规模特别大,大到超过单台机器的存储空间,如果还要存储那么该怎么办?
常见两种方法:
(1)增加本机的磁盘空间。
但是不可能一直增加,本机存储空间总会有一个极限。加到一定程度就会超过限制。
(2)增加机器数量,用共享目录的方式提供远程网络化的存储。
这种方式就可以理解为分布式文件系统的雏形,就是把同一文件切分之后放入不同的机器中,空间不足了还可继续增加机器,突破本机存储空间的限制。Hadoop目前最多可以支持到上万台机器规模组成的集群,总之,足够你用了。这个不用担心。但是这种方式还是有很多问题的。比如:数据怎么切分,数据切分之后如何存储,又怎么高效的管理存储在多台机器上的数据等等复杂问题,肯定不能靠人工去维护吧,那就有点傻了。那么怎么办呢?就要通过系统来解决,即通过分布式文件系统来管理存储在多台机器上的大规模数据。也就是后面会提到的HDFS(Hadoop分布式文件系统)。
我们不是为了存储数据而存储数据,我们最终的目的是想通过对大规模数据的多维分析挖掘出数据背后对企业运营决策有价值的信息。
(二)如何对大规模数据进行分析?也就是如何解决大规模数据的计算的问题? 大规模数据存储通过分布式存储解决存储容量局限的问题
大规模数据计算重点考虑的是计算速度的问题。就是怎么能够加快大规模数据的处理速度。
一台机器资源有限,计算大规模数据可能时间很长,那么怎么加快处理速度呢?整多台,一台不够多台来凑,每个任务处理一部分数据,多台机器的多个任务分别处理一部分数据,这样速度肯定会比之前快。
总之,不管是大数据的存储还是计算,都是通过分布式系统来解决的,不再通过比较昂贵的小型机,因为小型机成本太高。那么分布式系统在哪运行呢,就需要构建分布式集群。所以说我们接下来的重点就是如何构建分布式集群。
三、什么叫构建Hadoop分布式集群? 构建Hadoop分布式集群实际上就是在一组通过网络连接的物理计算机组成的集群上安装部署Hadoop相关的软件。
所以接下来我们的任务就是:
(1)首先准备物理集群
(2)实现物理集群的网络互联,就是通过网络把集群内所有机器连接起来
(3)在实现网络互联的集群上安装部署大数据相关的软件
四、那么准备多少台机器的物理集群呢?首先要明白机器的数量和哪些因素有关? (1)数据量(要考虑用多少台机器组成的集群能够存储这么大的数据)
1)规划时间内的数据而不是现有数据
注意:这个数据量是公司一定规划时间内(比如两年)的数据量,不是现有的数据量,因为你不可能随着数据量的增加每月或每周都往集群里增加节点,这样每天绝大部分时间就都花在集群维护上了,虽然说我们的确可以随着数据量的动态变化通过动态的增减节点的个数来调整集群的存储和计算能力,但是最好还是要有一个1-2年左右的中长期规划。
2)多副本
因为Hadoop致力于构建在廉价的商用服务器上的,廉价的就更容易出现故障,出现故障就容易导致数据丢失,数据丢失是绝对不允许的。所以说怎么保证数据安全性呢?一份不够,存多份就得了呗,难道你们还能同时丢到,虽然说有可能,但是可能性是不是就小很多了。当然你也不可能买特别垃圾的服务器。我们需要在采购成本和维护成本之间做好权衡。
3)中间数据、临时数据和日志数据需要占用20-30%左右的空间。
这个应该很好理解,因为数据不只是需要分析处理的业务数据。 (2)每台机器的性能配置
假设有100T的数据,每台机器2T硬盘,至少需要50台,每台机器4T硬盘,至少需要25台,所以说机器性能配置的不同也会影响集群规模的大小。后边我们会单独讲机器选型及配置选择。
(3)平台的功能性和非功能性需求
平台实现基本的功能之外还需要实现非功能性需求:
1)性能需求:
比如对100G—1T左右的数据进行简单的查询分析,能够在2分-10分钟之内完成,复杂作业(比如多表连接)能够在20-1小时内完成,业务数据的增量导入和数据清洗在1小时之内完成。
2)可靠性需求:
比如系统每月宕机次数不能超过1次。
3)可用性需求:
系统每次宕机的时间不能超过两小时,还有就是系统内任何一台计算机每月不可用的时间不能超过总时间的2%。
4)容错性需求:
机器宕机、服务停止硬件损坏的情况下数据不会出现丢失,不同情况下的恢复时间也有要求,比如宕机或服务器停止,恢复时间10分钟之内,如果NameNode硬件损坏,2小时之内恢复。
所以接下来我们的任务就是:
(1)先确定选择什么样的机器,也就是机器选型,当然包括机器的资源配置了。
(2)再确定集群的规模,也就是集群包含多少台机器
注意:在机器选型时并不是每台机器的配置必须都是一样的,因为不管是Hadoop中的HDFS还是YARN都是分布式系统,采用的是主从的架构,建议主节点的配置要高于从节点,从节点的配置建议一样,不同组件的安装部署配置可以不同。具体根据不同的业务场景进行不同的配置选择。
完整视频+图文资料获取及技术答疑请加:大讲台大数据研习社⑦ :695520445
在R数据分析的时候,我们常常会用到Excel格式数据的读取,但是在读取数据的时候,需要加载xlsx包。值得注意的是xlsx包需要依赖Java环境,如果Java环境没有配置正确或则是环境有问题的话,也是无法正常读取的,因此这点非常重要,如果出现无法读取请认真看看是否是环境出现了错误,如果不是的话,就具体问题具体分析即可。
#R读取Excel数据是,首先要安装xlsx包,安装完
install.packages("xlsx")
#进行加载包
library("xlsx")
#制作input测试数据
# Read the first worksheet in the file input.xlsx.
data <- read.xlsx("input.xlsx", sheetIndex = 1)
#实现数据的输出
print(data)
#特别注意的是就是在加载xlsx包时,需要依赖到Java环境,如果Java环境没有安装或者是安装错误的话
#会一直报错,显示无法读取
参考文章:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
注:父元素设为flex后,子元素的float、clear和vertical-align属性将失效
一、容器属性 1、flex-direction:属性决定主轴的方向(即项目的排列方向)
row(默认值)— — 主轴为水平方向,起点在左端。row-reverse — — 主轴为水平方向,起点在右端。column —— 主轴为垂直方向,起点在上沿。column-reverse —— 主轴为垂直方向,起点在下沿。 2、flex-wrap:
nowrap(默认值)— — 不换行。wrap —— 换行,第一行在上方。wrap-reverse —— 换行,第一行在下方。 3、flex-flow:属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap
4、justify-content:属性定义了项目在主轴上的对齐方式。
flex-start(默认值) —— 左对齐flex-end —— 右对齐center —— 居中(水平居中)space-between —— 两端对齐,项目之间的间隔都相等。space-around —— 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。 5、align-items:属性定义项目在交叉轴上如何对齐。
flex-start —— 交叉轴的起点对齐。flex-end —— 交叉轴的终点对齐。center —— 交叉轴的中点对齐(垂直居中)。baseline —— 项目的第一行文字的基线对齐。stretch(默认值) —— 如果项目未设置高度或设为auto,将占满整个容器的高度。 6、align-content:属性定义项目在交叉轴上如何对齐
flex-start —— 与交叉轴的起点对齐。flex-end —— 与交叉轴的终点对齐。center —— 与交叉轴的中点对齐。space-between —— 与交叉轴两端对齐,轴线之间的间隔平均分布。space-around —— 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch(默认值) —— 轴线占满整个交叉轴。 二、项目(子元素)属性 1、order:属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
stretch(默认值) —— 轴线占满整个交叉轴。 2、flex-grow:属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。 3、flex-shrink:属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
错误 What are " VM protect failed to allocate %8024 bytes from system, VM Protect 2012 MB 参考 https://discuss.pivotal.io/hc/en-us/articles/204997207 1 添加SWAP
Validate the value of gp_vmem_protect_limit. gp_vmem_protect_limit maximum limit must be calculated based on the calculation as provided in Greenplum Documentation. Example: (SWAP + (RAM * vm.overcommit_ratio)) .9 / primary number_segments_per_server 发现原来aws的默认没有SWAP,添加SWAP后正常,报的错误理解 What are " VM protect failed to allocate %802400000000 bytes from system, VM Protect 100 MB 2 设置参数 gp_vmem_protect_limit 每个segment需要单独去设置,重启 3 添加一张临时表,将数据时时导入临时表,频繁查询使用临时表,数据量小,不会造成IO,CPU过高
正常开发的时候,我们都手动去写要引入到包,有过java开发的同事,用过快捷键ctrl + alt + o 会自动引入所有的依赖包,pycharm也有这样的设置,看看怎么设置吧。
设置快捷键,默认ctrl + 空格,win的用户会和切换中文快捷键冲突,这里我设置的shift +1 用的时候,shift + 1 ,按两下1看看效果。
1.从下往上进入 <transition name="pull-up"> ..... ..... </transition> 2.从上往下进入 <transition name="drop-down"> ..... ..... </transition> %common1 { opacity: 1; -ms-transform: scaleY(1); transform: scaleY(1); transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1) 0.1s, opacity 0.3s cubic-bezier(0.23, 1, 0.32, 1) 0.1s; -ms-transform-origin: center top; transform-origin: center top; } .pull-up-enter-active, .pull-up-leave-active { @extend %common1; transform-origin: center bottom; } .pull-up-enter, .pull-up-leave-active, .drop-down-enter, .drop-down-leave-active { opacity: 0; -ms-transform: scaleY(0); transform: scaleY(0); } .drop-down-enter-active, .drop-down-leave-active { @extend %common1; transform-origin: center top; } 2.
<form></form>标签
1. Invalid location of tag (form)
form 应该写到table外面去,并且form标签里面也不能套form标签。
1、原始node命令 直接命令行中使用node命令
node xxx.js 或者安装nodemon,使用nodemon启动方便在开发阶段热部署代码改动
npm i nodemon -G nodemon xxx.js 2、webstorm方式 webstorm中,需要执行的文件的上,右键->run,右上角出现js文件,点击下拉箭头->Edit Configurations。 选择Node iterpreter,apply。 文件上右键->run。 即可使用webstorm中的内置控制台运行nodejs文件。
3、pm2 全局安装pm2
cnpm i pm2 -g 用pm2运行nodejs
pm2 start xxx.js pm2以进程方式后台运行node文件。
pm2使用介绍: http://blog.csdn.net/chengxuyuanyonghu/article/details/74910875 https://www.jianshu.com/p/d2a640b8661c
数数并说序列是一个整数序列,第二项起每一项的值为对前一项的计数,其前五项如下:
111211211111221 1 被读作 “一个一” 即 11。 11 被读作 “两个一” 即 21。 21 被读作 “一个二 和 一个一” 即 1211。 给一个正整数 n ,输出数数并说序列的第 n 项。 注意:该整数序列的每项都输出为字符串。 例 1:
输入: 1 输出: "1" 例 2:
输入: 4 输出: "1211" 思路:对于前一个数,找出相同元素的个数,把个数和该元素存到新的string里。
/** * @param {number} n * @return {string} */ var countAndSay = function(n) { if (n <= 0) return ""; let res = "1"; while (--n) { let cur = ""; for (let i = 0; i < res.
1.语法格式: 基础语法格式
[exp for iter_var in iterable] 工作过程:
迭代iterable中的每个元素;每次迭代都先把结果赋值给iter_var,然后通过exp得到一个新的计算值;最后把所有通过exp得到的计算值以一个新列表的形式返回。 相当于这样的过程:
L = [] for iter_var in iterable: L.append(exp) 带过滤功能语法格式
[exp for iter_var in iterable if_exp] 工作过程:
迭代iterable中的每个元素,每次迭代都先判断if_exp表达式结果为真,如果为真则进行下一步,如果为假则进行下一次迭代;把迭代结果赋值给iter_var,然后通过exp得到一个新的计算值;最后把所有通过exp得到的计算值以一个新列表的形式返回。 相当于这样的过程:
L = [] for iter_var in iterable: if_exp: L.append(exp) 循环嵌套语法格式
[exp for iter_var_A in iterable_A for iter_var_B in iterable_B] 工作过程: 每迭代iterable_A中的一个元素,就把ierable_B中的所有元素都迭代一遍。
相当于这样的过程:
L = [] for iter_var_A in iterable_A: for iter_var_B in iterable_B: L.append(exp) 应用场景 其实列表生成式也是Python中的一种“语法糖”,也就是说列表生成式应该是Python提供的一种生成列表的简洁形式,应用列表生成式可以快速生成一个新的list。它最主要的应用场景是:根据已存在的可迭代对象推导出一个新的list。
使用实例 我们可以对几个生成列表的要求分别通过“不使用列表生成式”和“使用列表生成式”来实现,然后做个对比总结。
实例1:生成一个从3到10的数字列表
不使用列表生成式实现 list1 = list(range(3, 11)) 使用列表生成式实现 list2 = [x for x in range(3, 11)] 实例2:生成一个2n+1的数字列表,n为从3到11的数字
单例模式
特点: 一个类只能有一个实例,并且这个类能自己创建出自己的实例供别人使用。
类图:很简单,只有一个类。
单例模式的几种实现方式:
饿汉式,懒汉式,DCL双重检查锁式,静态内部类式,枚举式,登记式
单例模式实现看起来简单,却可以扩展很多知识点,比如线程同步,synchronized,volatile,类加载顺序等。
单例模式使用场景举例:
比如一些资源管理器,数据库连接池,线程池等,方便资源控制和资源共享。
1. 细致地观察真实世界的特点,通常还要有精确的测量;
2. 根据观察结果提出假设模型;
3. 根据模型预测未来的事件;
4. 继续观察并核实预测的准确性;
5. 如此反复知道确认预测和观察一致。
科学方法的一条关键原则是我们所涉及的实验必须是可重现的,这样他人也可以自己验证假设的真实性。所有的假设也必须是可证伪的,这样我们才能确认某个假设是错误的(并需要修正)。
正如爱因斯坦的一句名言所说:“再多的实验也不一定能够证明我是对的,但只需要一个实验就能证明我是错的。”
C语言计算一个结构体内成员地址的偏移量的两种方法(代码实例) 一、有时候需要需要看一下一个结构体内成员地址的偏移量,下面介绍两种实现方法。
二、实现方法。
1、方法一,包含头文件#include <stddef.h>,调用函数offsetof(struct s, i)来实现。
2、方法二,使用&(((s1*)0)->i)的形式。
三、实例测试。
1、c代码
#include <stddef.h> #include <stdio.h> #include <stdlib.h> int main(void) { struct s { int i; char c; double d; char e; char a[]; }; typedef struct { int i; char c; double d; char e; char a[]; }s1; //Output is compiler dependent printf("\nmethod one:\n"); printf("offsets: i=%ld; c=%ld; d=%ld e=%ld a=%ld\n", (long) offsetof(struct s, i), (long) offsetof(struct s, c), (long) offsetof(struct s, d), (long) offsetof(struct s, e), (long) offsetof(struct s, a)); printf("
使用apt-get出现问题,错误信息大概如下 The package <package-name> needs to be reinstalled, but I can't find an archive for it. 用 apt-get install -f 无法修复. 考虑一下报错信息,应该是apt对之前失败的某次安装A念念不忘,并且在安装其他东西之前会重新安装这个程序A.(这个和正常的失败是不一样的) apt-get本质上是包装了dpkg,可以想到在某个地方一定记录了apt-get的历史安装信息 于是找到了文件/var/lib/dpkg/status,vim查看一下,每条信息的格式大概如下: Package: 程序(包)名称 Status: 状态(正常为install ok installed) Priority: optional ... //不仔细写了,大概包括依赖包,版本,架构,配置文件等信息 于是直接搜索到了之前报错的包名称,发现状态是 install ok half-configured 果然和我想的一样,和一般的失败不同.把文件做了个备份,直接删掉了整条信息. 再次安装文件,发现ok 如果还是提示错误,apt-get install -f,之后可以正常安装,不过安装成功以后会弹出以前失败的内容,可以通过清空/var/lib/dpkg/info 来清除以前的错误.
在创建maven项目时,在下图的 ” Output folder : None ” , 说明没有指定编译后 .class 文件存放的路径,所以在run java application报”错误: 找不到或无法加载主类”。
解决这个问题操作步骤如下: 在项目上右键 build path –> configure build path 上述5步完成后就ok了
文章出处:http://blog.csdn.net/u013812779/article/details/46880559
Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
翻译:将有n个元素的数组向右旋转k步。
如:n=7,k=3时,数组 [1,2,3,4,5,6,7]旋转为[5,6,7,1,2,3,4]。
注意:
用尽量多的方法来解决该问题,至少有三种不同方法。
大神danny6514解法:
public void rotate(int[] nums, int k) { k %= nums.length; reverse(nums, 0, nums.
友元 采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的成员函数,但又需要频繁地访问类的私有数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
友元函数 友元函数可以直接访问类的私有成员,在类外定义,不属于任何类。
如上图所示,将输出流重载,使其可以输出我们自定义类型的对象。有两种做法,
第一:将输出运算符重载为类的成员函数,这种写法如下:
ostream& operator<<(ostream& os) { os << "_c = " << _c << endl; os << "_i = " << _i; return os; } 由于是类的成员函数,故只需要一个参数,它的调用方式为:a.operator<<(cout);,虽然实现了功能,但与我们平常的用法习惯不一样。 第二种:在类外部定义该函数,并将其声明为类的友元函数,这种方式,其使用法和我们平常的用法习惯相同。
友元类 如果一整个类的函数需要访问另一个类的私有成员,则可以将该类声明为另一个类的友元类。
class A{ public: friend class B;//声明B为A的友元类 A(char c, int i) :_c(c) , _i(i) {} private: char _c; int _i; }; class B{ public: B(char c, int i, float f) :_a(c,i) , _f(f) {} void Print() { cout << "
实现枪开枪后, 向上偏移一段距离,再缓慢下移复位(模仿cs)
调小后座力
using UnityEngine; using System.Collections; public class Camera2Follower : MonoBehaviour { // 枪cd计时器 float timer; // 后座力 之前枪摄像头的角度 Vector3 s_pre_euler; public float gun_end_force = 0.53f; // 枪后座力大小 (可以先调大些方便调试) void Update () { .... timer += Time.deltaTime; if (Input.GetButton("Fire1") && timer >= 0.15) { // 计时器清零 timer = 0f; s_pre_euler = transform.eulerAngles; // 后座力 rotationY += Input.GetAxis("Mouse Y") * sensitivityY + gun_end_force; Quaternion yQuaternion2 = Quaternion.AngleAxis(rotationY, Vector3.left); transform.localRotation = originalRotation * yQuaternion2; } // 检测鼠标有没有移动 if (Input.
地址: github地址:点击打开链接https://github.com/MeloFocus/focus
前端水平有限见谅
目标: (1)用springboot整合shiro
(2)完成简单的登录功能
(3)对url进行权限控制,当前登录用户拥有此url的权限码时,才可以访问此url
1.pom文件 可以先从此网站拉项目及所需要的依赖 http://start.spring.io/
目前需要的依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> </dependencies> 2.设计表,逆向生成 user:用户表 role:角色表 user_role_r:用户和角色关系表,多对多
role_business:业务角色表 resource:资源表
role_resource_r:角色资源关系表,多对多
authority:操作码表
resource_authority:资源和操作码关系表,多对多
最后逆向生成实体类,本博客另有一篇记录逆向生成
3.使用java配置,配置shiro ShiroFilterFactoryBean:是个拦截器,在请求进入控制层前将其拦截,需要将安全管理器SecurityManager注入其中
SecurityManager:安全管理器,需要将自定义realm注入其中,以后还可以将缓存、remeberme等注入其中
自定义reaml:认证授权会执行它,需要自己写
@Configuration public class ShiroConfig { /** * ShiroFilterFactoryBean 处理拦截资源文件问题。 * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager * Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过 * 3、部分过滤器可指定参数,如perms,roles */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.
大小端的寓言故事 有关大小端的争论,最早来自于《格列夫游记》里一个有趣的故事:
Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。
什么是大小端 目前普遍采用的是单字节编址方式,即对于每一个字节(8个位)编一个地址编号,这种方式对于单字节数据存储没有问题,但多字节的数据存储会带来问题,比如:要将整形 0x 87 65 43 21 (占四个字节)存储在其起始地址为 100处,是将高位 87 存储在高地址 103 处,还是将 21 存储在 103 处,这是一个问题。
将数据的高位存储在低地址处的方式称为大端模式;相反的,将数据的低位存储在低地址处的方式称为小端模式。 这样对于 0x 87 65 43 21 就有两种存储方式: 大小端的测定 下面给出两种测试方法(C语言):
用一个 char 的指针取得 int 的第一个字节, 通过查看 char 对应的是 int 的高位数据还是低位数据,从而得出结果。代码如下: #include <stdio.h> int main() { int i = 0x87654321; char *cp = (char*)&i; printf("%d\n", *cp); return 0; } 结果如下: 通过联合体的特点:所有成员共享同一内存,来达到测试目的。代码如下: #include<stdio.h> int check() { union{ int i; char c; }ic; ic.
memset可以方便的清空一个结构体类型的变量或者数组
如:
struct sample_struct { char csname[16]; int iseq; int itype; }; 对于变量 struct sample_struct sttest; 一般情况下,清空sttest的方法: sttest.csname[0]='\0'; sttest.iseq=0; sttest.itype=0; 用memset就非常方便: memset(&sttest,0,sizeof(struct sample_struct)); 如果是数组: struct sample_struct test[10]; 则 memset(test,0,sizeof(struct sample_struct)*10);
某天发现一个神奇的网站https://visualgo.net/en,对于学习各个算法非常有用,它将算法的步骤可视化,能很好地帮助我们理解。
顺序为从小到大。
1,冒泡排序
从头到尾两两比较,如果前者比后者大就交换,重复这个过程,直到不需要交换。
visualgo伪代码:
do swapped = false for i = 1 to indexOfLastUnsortedElement-1 if leftElement > rightElement swap(leftElement, rightElement) swapped = true while swapped UE4中C++实现:
void Atest::BubbleSort(TArray<int>& _array) { bool swapped = false; do { swapped = false; for (int i = 0; i < _array.Num() - 1; i++) { if (_array[i] > _array[i + 1]) { int temp = _array[i]; _array[i] = _array[i + 1]; _array[i + 1] = temp; swapped = true; } } } while (swapped); } 2,选择排序
解决办法 将你工程下的所有build.gradle文件中的buildToolsVersion 更改为"26.0.2"; 重新点Try again,同步一下OK。
我工程下的所有build.gradle文件中的compileSdkVersion 25;
对应安卓-sdk android-25;
一、标准Android系统(基于Android M,其他基本也是这样)音量调节基本流程:
见大神三部曲
1、[RK3288][Android6.0] Audio的音量设置流程小结 :http://blog.csdn.net/kris_fei/article/details/72929999
简明梳理了音量设置代码流程
2、[RK3288][Android6.0] Audio的音量计算过程小结 :http://blog.csdn.net/kris_fei/article/details/72957142
对音量的增益转换进行了说明
3、[RK3288][Android6.0] 调试笔记 --- Audio的Voice Call无法静音问题:http://blog.csdn.net/kris_fei/article/details/72961528
对于如通话音量的特殊处理做了说明,基于第二篇的音量增益转换,说明了通话音量无法静音的原因与修改方法
二、MTK平台音量调节特殊处理——STREAM_VOICE_CALL无法静音
1、参照大神第三篇说明修改后,仍然无法静音。
2、在进一步了解音量调节的流程后,修改了STREAM_VOICE_CALL的最小音量等级为0(一般系统默认的通话最小音量等级为非0,防止误设置通话音量导致通话没有声音),如下所示(下述修改同时调整最大音量等级为15),仍然无法静音
diff --git a/frameworks/base/services/core/java/com/android/server/audio/AudioService.java b/frameworks/base/services/core/java/com/android/server/audio/AudioService.java old mode 100644 new mode 100755 index 46dd821..5023bc9 --- a/frameworks/base/services/core/java/com/android/server/audio/AudioService.java +++ b/frameworks/base/services/core/java/com/android/server/audio/AudioService.java @@ -275,7 +275,7 @@ public class AudioService extends IAudioService.Stub { /** Maximum volume index values for audio streams */ /// M: Modify the max stream volume @{ private static int[] MAX_STREAM_VOLUME = new int[] { - 7, // STREAM_VOICE_CALL + 15, // STREAM_VOICE_CALL 15, // STREAM_SYSTEM 15, // STREAM_RING 15, // STREAM_MUSIC @@ -289,17 +289,17 @@ public class AudioService extends IAudioService.
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。
报错如题: .SpelEvaluationException: EL1008E: Property or field 'cache_department_list_Tree' cannot be found on object of type 'org.springframework.cache.interceptor.CacheExpressionRootObject' - maybe not public?
这是在一个springboot 工程中开启缓存的使用,缓存注解加在一个public方法A上,但方法A调用了一个private方法B。
解决:把方法B也改为public 。
(cache_department_list_Tree 是缓存的key)
1. 服务器:
平台内windows虚拟机
FTP软件:ServerU Version 9.2.0.1
平台公网IP映射服务器端口8080,20端口
2. 公网环境客户端:FileZilla FTP客户端 Version3.24
3.运行:
filezilla 连接公网IP地址8080端口,服务器返回的信息
”服务器发回了不可路由的地址。使用服务器地址代替“ 解释 :服务器返回的IP地址和端口号为服务器本机IP地址,例如,192.168.*.*,地址不可访问,用公网IP地址代替访问。
filezilla连接服务器成功,但是列出FTP目录失败,解决方案:
参考FTP 被动模式和主动模式区别,做如下修改
1. filezilla =》编辑=》ftp设置=》连接=》ftp=》 改成被动模式(如果未修改过,默认就是被动模式)。
2. ServerU管理界面首页=》服务器设置和限制,Upap(大致为路由器的意思)中启用passive模式,分配端口区间20-20
3. 客户端再次连接,成功。
附参考连接:
http://blog.csdn.net/pear86743/article/details/70954837
原文地址:http://blog.51cto.com/devbean/313477
最近一直在学习 Qt。Qt 有两个许可证:LGPL 和商业协议。这两个协议在现在的 Qt 版本中的代码是完全一致的(潜在含义是,Qt 的早期版本,商业版的 Qt 通常包含有一些开源版本所没有的库,比如 QtSingleApplication 这个库)。所以现在对于普通开发人员和部分商业公司来说,使用 LGPL 版本的 Qt 可以节省很大的开销。这两个版本最大的区别在于,前者是免费的,后者是收费的。既然代码都是一致的,所以费用就要是用来购买 Qt 的售后服务和培训等等相关服务。
现在我们是来说一下版权的问题。LGPL 是一个开源协议,因此,有人会担心 LGPL 能否用于开发闭源程序,能够拿来卖钱。尽管现在国内有些公司不是很重视这方面的问题,不过,如果你违反了协议,某一天被别人发来一纸律师函的时候,真的是欲哭无泪了哦。所以,我们还是先来研究一下这个协议,LGPL 究竟能不能用于开发闭源程序。
以下内容是我查找了 N 多网站总结出来的,因为豆子不是律师,所以 LGPL 协议基本看不懂。究竟怎样去理解这个协议,还是希望能够有专业人士说出来。这里就算做是一种抛砖引玉吧!尽管没有十分的确定,但是这里所说的理解基本也是八九不离十的了。
至于什么是 LGPL 协议,这里就不再多说了,我们关心的是,如果使用 LGPL 协议开发商业程序。请注意,这里所说的闭源程序,是指不以某种形式开放源代码,也就是说,用户(包括其他开发者)不能获取其源代码的程序。首先说明一点,LGPL协议是一个商业友好的协议。这里的含义是,你可以用 LGPL协议开发商业程序,当然也可以是非商业的闭源程序。但是,它是有一些限制的。这就是我们要讨论的重点。
既然我们已经对其定性,那么我们直接进入主题:使用 LGPL 协议开发闭源程序,如果你使用动态链接的形式,那么,你可以以任何形式发布你的应用程序,商业的、非商业的、开源的、非开源的,随你。
如果你因某种原因必须静态链接一个基于 LGPL 协议发布的库(一下我们简称为 LGPL 库),那么,你有义务进行下面的工作: 1. 你必须在你的文档中说明,你的程序中使用了 LGPL 库,并且说明这个库是基于 LGPL 发布的; 2. 你必须在你的应用程序发布中包含一份 LGPL协议,通常就是那个文本文件; 3. 你必须开放使用了 LGPL 库代码的所有代码,例如某些封装器。但是,其他使用这些封装器的代码就不需要开放了; 4. 你必须包含你的应用程序的余下部分的目标文件(通常就是我们所说的 .o 等等),或者是其他等价的文件。源代码并不是必须的。 是不是很难理解呢?我们详细的说一下。 第一条很容易理解; 第二条也很容易理解,你可以在这里找到 LGPL 协议的内容,复制下来随你的程序一起发布就可以了。 第三条就不那么好理解了。简单来说,LGPL协议要求,如果你的类使用了LGPL库的代码,那么必须把这个类开源。例如,如果你的程序 app.exe 每个源文件都使用了 LGPL 库的代码,那么你的所有源代码都要开源。为了避免这种情况,我们通常编写一个封装器,把 LGPL库的代码封装起来,这样就只需要开放这个封装器的代码,而其他使用了这个封装器的代码就不需要开放。 第四条是对第三条的一种补充:那些使用了封装器的程序不需要开源,但是你必须把你编译的那些中间文件开放出来,Windows 下就是那些 .
C语言的main函数通常含有参数argc和argv,写法通常如下:
int main(int argc,char *argv[]) int main(int argc,char **argv) 下面详细解释一下这两个参数:
argc : 命令行传入参数的总个数 argv : *argv[]是一个指针数组,里面存放的指针指向所有的命令行参数,argv[0]指向程序的全局路径,argv[1]指向在DOS命令行中执行程序名后的第一个字符串,argv[2]指向第二个。
现在知道了参数的含义,下面讲解一下怎么从命令行传参: 现在有一段程序:
#include<stdio.h> int main(int argc,char *argv[]) { int i; for(i=0;i<argc;i++) printf("第 %d 个参数是 %s\n",i+1,argv[i]); return 0; } 这段程序用Code::Blocks编译后会产生两个文件,如下图: 然后在当前文件件下打开DOS命令窗口(shift+鼠标右键),然后执行exe文件,此时你的路径默认为第一个参数,在后面你可以传入其他参数,中间用空格隔开: 。 下面再举一个例子,对于C语言的文件操作,可以用到命令行传参的方式来控制用什么方式打开什么文件:
#include<stdio.h> int main(int argc,char *argv[]) { int ch; FILE *fp; if(argc!=3) { printf("Error"); return -1; } if((fp=fopen(argv[1],argv[2])) == NULL) { printf("Error"); return -1; } ch = fgetc(fp); while(ch!=EOF) { putchar(ch); ch = fgetc(fp); } fclose(fp); return 0; } 这段代码需要用户传入需要读取的文件名和打开文件的方式,这里我以read的方式打开名字为test.
原文地址:http://blog.csdn.net/qiek/article/details/50900890
ARM平台NEON指令的编译和优化 本文介绍了ARM平台基于ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7,Cortex-A8, Cortex-A9, Cortex-A15)上的NEON多媒体处理硬件加速器针对C/C++语言、汇编语言和NEON intrinsics如何编译和优化,包含如何向量化、向量化的ARMCC和GCC编译器选项、NEON的汇编和EABI程序调用规范、如何在bare-metal和Linux操作系统上检测NEON硬件、如何指导编译器进行向量化NEON指令的优化等内容。
NEON向量化 基于ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15)都可以选用NEON多媒体处理器加速程序运行,NEON是一种SIMD(Single Instruction Multiple Data)架构的协处理器,ARM的NEON处理器还可选配置成向量浮点VFPv3(Vector Floating-Point)指令集处理器。
常用的编译器选项配置 自动向量化选项 armcc编译器使用–vectorize选项来使能向量化编译,一般选择更高的优化等级如-O2或者-O3就能使能–vectorize选项。
gcc编译器的向量化选项-ftree-vectorize来使能向量化选项,使用-O3会自动使能-ftree-vectorize选项。
选择处理器类型 armcc编译器使–cpu 7-A或者–cpu Cortex-A8来指定指令集架构和CPU类型。
gcc编译器的处理器选项-mfpu=neon和-mcpu来指定cpu类型。如-mcpu=cortex-a5
选择NEON和VFP类型 gcc选择用-mfpu=vfpv3-fp16来指定为vfp协处理,而-mfpu=neon-vfpv4等就能指定为NEON+VFP结构。
选择浮点处理器和ABI接口类型 -mfloat-abi=soft使用软件浮点库,不是用VFP或者NEON指令;-mfloat-abi=softfp使用软件浮点的调用规则,而可以使用VFP和NEON指令,编译的目标代码和软件浮点库链接使用;
-mfloat-abi=hard使用VFP和NEON指令,并且改变ABI调用规则来产生更有效率的代码,如用vfp寄存器来进行浮点数据的参数传递,从而减少NEON寄存器和ARM寄存器的拷贝。
常用的CPU类型编译器选项 CPU类型CPU类型选项FP选项FP + SIMD选项备注Cortex-A5-mcpu=cortex-a5-mfpu=vfpv3-fp16
-mfpu=vfpv3-d16-fp16-mfpu=neon-fp16-d16表明只有前16个浮点寄存器可用Cortex-A7-mcpu=cortex-a7-mfpu=vfpv4
-mfpu=vfpv4-d16-mfpu=neon-vfpv4-fp16表明支持16bit半精度浮点操作Cortex-A8-mcpu=cortex-a8-mfpu=vfpv3-mfpu=neonCortex-A9-mcpu=cortex-a9-mfpu=vfpv3-fp16
-mfpu=vfpv3-d16-fp16-mfpu=neon-fp16Cortex-A15-mcpu=cortex-a15-mfpu=vfpv4-mfpu=neon-vfpv4 常用的gcc组合编译器选项 Cortex-A15 with a NEON unit arm-gcc -O3 -mcpu=cortex-a15 -mfpu=neon-vfpv4 -mfloat-abi=hard -ffast-math -omyprog.exe myprog.c Cortex-A9 with a NEON unit arm-gcc -O3 -mcpu=cortex-a9 -mfpu=neon-vfpv3-fp16 -mfloat-abi=hard -ffast-math -omyprog.exe myprog.c Cortex-A7 without a NEON unit arm-gcc -O3 -mcpu=cortex-a7 -mfpu=vfpv4-d16 -mfloat-abi=softfp -ffast-math -omyprog2.
在 iOS 程序访问 HTTP 资源时需要对 URL 进行 Encode,比如像拼出来的 http://unmi.cc?p1=%+&sd f&p2=中文,其中的中文、特殊符号&%和空格都必须进行转译才能正确访问。现在以"?!@#$^&%*+,:;='\"`<>()[]{}/\\| "字符串为例子,用stringByAddingPercentEncodingWithAllowedCharacters取代CFURLCreateStringByAddingPercentEscapes
过期代码:
-(NSString *)urlEncode:(id)value { return (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)[value description], NULL, (CFStringRef)@"#[]@!$'()*+,;\"<>%{}|^~`", kCFStringEncodingUTF8)); } -(NSString *)URLDecodedString:(NSString *)str { NSString *decodedString=(__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)str, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); return decodedString; } 修改后:
static inline NSString * WebURLEncode(NSString * str) { NSString *charactersToEscape = @"#[]@!$'()*+,;\"<>%{}|^~`"; NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:charactersToEscape] invertedSet]; NSString *encodedUrl = [[str description] stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; return encodedUrl; } static inline NSString * WebURLDecodedString(NSString * str) { return [str stringByRemovingPercentEncoding]; }
现在越来越多的App都要求关注公众号,实现跳转到微信公众号界面,或者已经关注的人,直接进来微信公众号中聊天!
在之前可以通过以下方式实现跳转:
// Intent i = new Intent(Intent.ACTION_VIEW); // String guanzhu_URL = "http://weixin.qq.com/r/STn7497EyYO2rZqA92xb"; // i.setData(Uri.parse(guanzhu_URL)); // i.setPackage("com.tencent.mm"); // i.putExtra(Intent.EXTRA_SUBJECT,"Share"); // i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // startActivity(i); url 是你的公众号的扫描后得到的字符串.(如果你知道公众号,但是不知道怎么得到他的url的话,你可以用的应用,扫一下这个二维码,然后在回调里面通过日志打印出来!,然后把这个url放在这里) ,但是,目前这个方式是在微信公共接口没有关闭前,才可以使用,这个接口开发的时间不长,可能是担心,任何app没有经过微信官方审核后,就直接跳,可能存在安全隐患吧)
后来微信这个对这个接口进行了,管理,必须是他的认证的开发者,并且必须通过认证后,才能调用该接口, 审核时间大概是7个工作日
为了方便遇到相同问题的朋友查询方便,提供以下链接:
https://open.weixin.qq.com/cgi-bin/frame?t=news/note-communicate-port_tmpl&;
按照这个链接的说明,一步一步操作即可完成你目前遇到的困惑或者难题!,如果以上答案可以帮助到你,记得给我点个赞,或者关注一下哦,谢谢!
一、GET方式 /** * @描述:HttpURLConnection 接口调用 GET方式 * @param strUrl 请求地址 * @param param 请求参数拼接 * @return 请求结果集 */ public static String httpURLConectionGET(String strUrl, String param) { StringBuffer sb = new StringBuffer(""); BufferedReader br =null; HttpURLConnection connection =null; try { strUrl = strUrl + "?" + param.trim(); URL url = new URL(strUrl); // 把字符串转换为URL请求地址 // 实例化本地代理对象 Proxy proxy= new Proxy(Proxy.Type.HTTP,new InetSocketAddress(proxyIp,proxyPort)); Authenticator.setDefault(new SimpleAuthenticator(proxyUserName,proxyPassword)); connection = (HttpURLConnection) url.openConnection(proxy);// 打开连接 connection.setConnectTimeout(60000); connection.setDoOutput(true); connection.
遇到企业微信的接口开发,找到了一个很好的教程。
转载自: http://www.cnblogs.com/shirui/p/7325447.html
原文:
一、源码
此系列教程的源码我都放在了github上,欢迎fork以及关注。
传送门:https://github.com/shirayner/WeiXin_QiYe_Demo/tree/master
二、学习资源
1. Java-微信企业号开发教程(http://blog.csdn.net/column/details/weixindeveloper.html)
2. youz1976-微信公众号开发(http://blog.csdn.net/u014520797/article/category/5876155)
3. 微信开发 (http://blog.csdn.net/column/details/omswechat.html)
4.jssdk:
https://my.oschina.net/superkangning/blog/367484
https://leo108.com/pid-2069/
http://blog.csdn.net/txqd1989/article/details/51757492
http://www.itnose.net/detail/6687130.html
在使用Vue框架的时候,有时候需要在Vue在页面数据渲染完成之后调用方法,不然获取不到准确的数据,特别是在获取列表的高度的时候,由于数据没有加载完,获取不到准确的高度。之前在使用jquery的时候,有ready可以帮助我们实现,但是Vue不存在此类方法,我们需要结合watch和this.$nextTick()来实现。
nextTick:在下次 DOM 更新循环结束之后执行延迟回调。
watch:用于观察Vue实例上的数据变动。对应一个对象,键是观察表达式,值是对应回调。
之前我是这样子使用nextTick的:
mounted:{
this.$nextTick(function(){
/方法
})
}
经测试发现实现不了所需要的效果,只有结构,没有数据,即获取不到想要的高度
后发现需要结合watch监听某个属性:
watch:{
asyncArray:function()
this.$nextTick(function(){ //方法 }); } } 经测试可用!
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="js/jquery.min.js"></script> <script src="js/jquery.cookie.js"></script> <script> $(document).ready(function() { //所创建的cookie有效期默认到用户关闭浏览器为止 $.cookie('the_cookie', '五颜六色千变万化'); //创建一个cookie并设置 cookie的有效路径: $.cookie('the_cookie_expires_07', '世界是座魔方大厦', { expires: 7 }); //读取cookie var value = $.cookie('the_cookie'); var value_07 = $.cookie('the_cookie_expires_07'); $('p').html('读取cookie的值:' + value + '<br />' + '读取cookie存在7天的值:' + value_07); }); //清除所有cookie函数 function clearAllCookie() { var keys = document.cookie.match(/[^ =;]+(?=\=)/g); if(keys) { for(var i = keys.length; i--;) document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString() } } /**清楚指定cookie**/ $("
作者:EZLippi 链接:https://www.zhihu.com/question/19823234/answer/31632919 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 有一些比较好的开源框架可以学习,比如: Webbench Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用C语言编写, 代码实在太简洁,源码加起来不到600行。下载链接: LippiOuYang/WebBench · GitHub Tinyhttpd Tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。下载链接链接: LippiOuYang/Tinyhttpd · GitHub cJSON cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。
cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。
项目主页:cJSON | SourceForge.net
Libev libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理。基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。
下载链接:http://software.schmorp.de/pkg/libev.html
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态数据库驱动网站的速度。Memcached 基于一个存储键/值对的 hashmap。Memcached-1.4.7的代码量还是可以接受的,只有10K行左右。
下载地址:memcached - a distributed memory object caching system
SQLite SQLite是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。足够小,大致3万行C代码,250K。
下载地址:SQLite Home Page 。
redis redis是高性能键值对存储系统 antirez/redis · GitHub 查看C++框架整理:值得推荐的C/C++框架和库
转载于:https://www.cnblogs.com/alexhg/p/8431512.html
欢迎访问我的个人博客 http://xiaolongwu.cn/ 先简单介绍一下各个属性 ::-webkit-scrollbar :滚动条整体部分,其中的属性有width,height,background,border等。
::-webkit-scrollbar-button :滚动条两端的按钮。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果。
::-webkit-scrollbar-track :外层轨道。可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果。
::-webkit-scrollbar-track-piece :内层轨道,具体区别看下面gif图,需要注意的就是它会覆盖第三个属性的样式。
::-webkit-scrollbar-thumb :滚动条里面可以拖动的那部分
::-webkit-scrollbar-corner :边角,两个滚动条交汇处
::-webkit-resizer :两个滚动条交汇处用于拖动调整元素大小的小控件(基本用不上)
下面看几组比较 效果一 上图滚动条效果的css代码如下,默认此部分为原始代码,之后的效果图修改都是在此基础上修改
/*css主要部分的样式*/ /*定义滚动条宽高及背景,宽高分别对应横竖滚动条的尺寸*/ ::-webkit-scrollbar { width: 10px; /*对垂直流动条有效*/ height: 10px; /*对水平流动条有效*/ } /*定义滚动条的轨道颜色、内阴影及圆角*/ ::-webkit-scrollbar-track{ -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); background-color: rosybrown; border-radius: 3px; } /*定义滑块颜色、内阴影及圆角*/ ::-webkit-scrollbar-thumb{ border-radius: 7px; -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); background-color: #E8E8E8; } /*定义两端按钮的样式*/ ::-webkit-scrollbar-button { background-color:cyan; } /*定义右下角汇合处的样式*/ ::-webkit-scrollbar-corner { background:khaki; } 效果二 在上面原始代码上加如下代码
RESTful简介: (详情参考:) http://baike.baidu.com/link?url=1FMTyxYwnN5OED7oXwbLBI1z35JCuE1bfIamqJMrbBUeNDPmQ6U3t-gx9tGHC170A0akfPhhzfBNWF0BwHj-xq http://developer.51cto.com/art/200908/141825.htm https://www.zhihu.com/question/28557115 http://blog.csdn.net/aooppo/article/details/8686595 … 个人理解: 在同一个路径下,不同的协议请求(Get、Post、Put、Delete、Patch、Head、Option s、Trace)实现不同的功能。
一、环境配置 ①、开发前的基础配置:配置好相应的Spring MVC、JSON和Restful需要的依赖程序包。 ②、Tomcat9.0服务器配置 ③、在项目配置web.xml
<servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 路径是 '/' 斜杠 --> <url-pattern>/</url-pattern> </servlet-mapping> ④、建立一个测试类TextRestful .java,测试环境是否可用
@Controller public class TextRestful { @RequestMapping(value="/restful",produces="text/plain;charset=UTF-8") public @ResponseBody String info() { return "Hello World!"; } } 浏览器输入路径:http://localhost/XXXX(项目名称) / restful(方法路径) 页面显示:Hello World!则代表环境搭建完成。 ⑤准备要测试的Vo类
public class Emp implements Serializable { private Integer empno; private String ename; private double sal; private Date hiredate; //此处省略setter()、getter()和toString()方法 }
KIWI 是新西兰的国鸟,中文名叫”几维”,KIWI跟其他鸟最大的区别,就是他们穷其一生都没有飞翔能力。 这是一部美国动画短片,名字就叫《KIWI!》,是06年奥斯卡获奖动画片,片长03:09,影片作者Dony Permedi是美国School of Visual Art学院的学生,KIWI是他的毕业作品。 三分钟,三分钟0九秒而已,感动,无以言表。没有翅膀的鸟,通向天堂的飞翔,KIWI,无翼鸟,告诉人们什么是梦想!
如果不是那一滴眼泪,我不会有过多的情绪产生,如果不是有那一排排的它栽下的树,我不会在熬了一夜意倦神疲还坐下来写评。 我想我应该为这只没有翅膀的小鸟写些什么,为那些愿意为了自己的理想而不计代价和后果孤注一掷的人写些什么,以此来纪念和庆祝自己这么多年来,从不曾对这个社会,对这个世界有过丝毫绝望。 因为有像kiwi一般的人在。因为这样的人,生活才得以精彩,精神才得以超越,生命才得以辉煌,世界才得以进步。 在这个星球上,总有一些人是大幅度区别于众生的,他们或者超前或者滞后,或者沉静或者疯狂,没有什么能把他们拉回正常的轨道,也没有什么能让他们放弃心中的梦想。他们听从自己的内心,以各种不可思议的方式去实践着自己的向往。他们一边给主流群体展示着生命的独特体验,一边接受着自然的残酷淘汰。他们也许会赢得短暂的鲜花和掌声,但注定要时刻承受压力和误解。 可是他们是可爱的一群,他们让大多数人感受到了生命原来还可以这样,可以让大多数人来参考自己是否正常,他们无声无息的拉拽着庞大的群体,步履艰难的进行着多方向的前进尝试。他们让人感受到生命的多情和张力,他们用自己的梦把世界装点的多姿多彩,把生活书写的妙趣横生。 在看到一些好东西的时候,常常会燃起爱恨交织的感情,这样浪漫的诗句为什么不是我写下的,这样美好的故事为什么不是我创造的,这样翻腾的一生为什么不是我活出来的。为什么我就不能把信念狠狠的砸进行动,不敢用大把的时光来换取生命的质量。为什么我喜欢这些人却不肯承认自己本身也是这些呢? 当我在驯龙记中看到骑龙遨游的时候,我为自己曾经嘲笑那些为了实现飞翔的梦想而近乎愚蠢的付出生命的人而羞愧,因为我明白了那片刻的美好已经远胜现实的一生。我想起一位驻守高原朋友曾和我说,当你面对皑皑雪山的时候,你就会知道为了房子大了职务小了而烦恼是很无聊的事。我说可是那就是生活。后来我明白了,那不是生活,那是误解生活之后的实用衡量。当你再也感受不到血液的沸腾,再也迸发不出生命的热力,再也爆发不出追求的呐喊和勇气,当你对什么都了如指掌对什么都嗤之以鼻对什么都用规矩框用尺子量的时候,生命就已经结束了,剩下的日子,只是依赖旧日的惯性在轨道上滑行而已。 问问自己有多少想做的没能去做,问问自己有多少事之所以改变是因为别人的眼光,问问自己如果没有任何人的认同是不是依旧可以承认,面对和肯定自己。问问自己的生活方式究竟是谁给你提供的选择。问问自己来到这个世上到底想做些什么。 在kiwi兴高采烈的从悬崖跳下去的时候,干净的音乐响起。我不知道这只有一双脚的小鸟用了多少时间和心血去种那些用来营造飞翔感觉的树,不知道它从哪里找来了飞行眼镜。可我看到它落泪了,它眼里有让我难以正视的神采和光芒。而那种眼神,我也许一辈子也不会具有。 它没有飞,它只是以重力加速度坠向死亡。 它一生只能做这一次飞行,梦想的世界里没有力学。 这一刻对理想主义的它感同身受。 是的,也许我们终究也不会成为这样的人,可是至少知道了什么不是我们需要的人生。当有人再度以自诩老练成熟睿智的姿态来肆意评论你应该如此不懂这般的时候,至少可以笑着拍拍他的肩膀说,这些都和我无关,带上你成功的优越滚去帮助和你一样的聪明人吧。 因为我宁可被自己的梦想毁灭,也不愿毁灭自己的梦想。 因为我可以一辈子打不开翅膀,但是绝不会变的和你一样。
主机A:虚拟机linux
主机B:虚拟机linux
主机C:真实机win8
情景一:桥接模式 主机C通过真实网卡来与外网通信,如果主机AB选择了桥接模式,那么,三者共用一个真实网卡与外网通信。言简意赅老哥没毛病。
前提是主机C就是能够访问外网,主机ABC都配置一样的DNS。当然8.8.8.8也ok。
虚拟机设置:
IP配置:
主机A:192.168.2.11(和主机C同一网段即可)
主机B:192.168.2.22(和主机C同一网段即可)
主机C:192.168.2.66
测试一:三者是否互通? 必须互通。
就不上图了,你想想同一个网卡同一个网段,不互通怎么可能。
测试二:三者都能访问外网吗? 必须可以。
情景二:NAT模式 如果主机AB设置了此模式,那么他们的网络包都是通过VMware8这块网卡转发,经过nat转化后便通过主机C真实网卡与外网进行通信。
虚拟机设置:
IP设置:
此时主机C与AB通信是通过VMware8这个网卡192.168.158.1地址
主机A和B通过DHCP获取地址,定义了下发地址192.168.158.128-192.168.158.254
主机A:DHCP获取IP:192.168.158.129
主机B:DHCP获取IP:192.168.158.131
主机C:VMware8:192.168.158.1
测试一:三者是否互通? 必须互通。
就不上图了,你想想同一个网卡同一个网段,不互通怎么可能。
测试二:三者都能访问外网吗? 必须可以。
情景三:仅主机模式 如果主机AB设置了此模式,那么他们的网络包都是通过VMware1这块网卡转发,没有nat转化,与主机C通信只能靠VMware1网卡,并不能访问外网。
虚拟机设置:
IP设置:
此时主机C与AB通信是通过VMware1这个网卡192.168.241.1地址
主机A和B通过DHCP获取地址,定义了下发地址192.168.241.128-192.168.241.254
主机A:DHCP获取IP:192.168.241.129(手工配当然也行)
主机B:DHCP获取IP:192.168.241.131(手工配当然也行)
主机C:VMware1:192.168.241.1 测试一:三者是否互通? 必须互通。
就不上图了,你想想同一个网卡同一个网段,不互通怎么可能。
测试二:三者都能访问外网吗? 必须不可以。
这下没人不了解了吧,走心了我这次。
由于segmentfault编辑器上传图片错误,小编试过多种方式试图拯救,还是未能成功,所以如要看完整文章请至http://t.cn/R8njjaT miaomiao 高级测试工程师 7年测试工作经验,参与产品的功能/自动化/性能测试;目前负责 Red.Q、Warden 产品的质量保障工作。 背景 Red.Q 是岂安为客户提供业务风险情报服务的产品。API 是该产品的一个模块,客户可以通过输入不同的参数获取不同的风险数据。
在测试该 API 的过程,就是对这个接口的测试,不同的 Token 对应不同的订单,对应不同的标签,对应不同的返回。本文主要介绍在测试该接口时总结的一些场景用法。
工具介绍 目前接口测试的工具,例如 Postman/SoupUI,等大多都提供了接口的发送、响应结果的获取、以及针对响应结果的断言,都可以用来做接口的自动化测试,我们目前选用的工具是 JMeter,各种工具大同小异。如对 JMeter 工具不了解的同学请戳 Bioneck 分享的 Jmeter+Jenkins 文章。
实现本次自动化测试用到的组件介绍 :
Threads--> 线程组配置元件--> HTTP 请求默认值配置元件--> JDBC Connection Configuration配置元件--> HTTP 信息头管理器定时器--> 高斯定时器Sampler--> HTTP 请求Sampler--> JDBC Request后置处理器--> 正则表达式提取器断言--> BeanShell 断言断言--> 响应断言监听器--> 查看结果树 测试场景与测试实现 1使用Token调用API 一个最简单的 HTTP 请求,由 host+ 端口 + 路径 + 参数构成,调用 API 的设置如下:
1) HTTP 请求默认值,设置好服务器 IP 和端口,所有作用范围内的 HTTP 请求可以不再指定。
2) HTTP 请求,设置路径和参数
opencv读取 #导入cv模块 import cv2 as cv import numpy as np #读取图像,支持 bmp、jpg、png、tiff 等常用格式 #第二个参数是通道数和位深的参数,有四种选择,参考https://www.cnblogs.com/goushibao/p/6671079.html img = cv.imread("filename.tif",2) print img #在这里一开始我写成了img.shape(),报错因为img是一个数组不是一个函数,只有函数才可以加()表示请求执行, #参考http://blog.csdn.net/a19990412/article/details/78283742 print img.shape print img.dtype print img.min() print img.max() #创建窗口并显示图像 cv.namedWindow("Image") cv.imshow("Image",img) cv.waitKey(0) #释放窗口 cv.destroyAllWindows() 但是出现了问题,我的TIFF是signed 16-bit的,用这种方法读出的值域范围0~65535,正常是-32768~32767.可能是opencv只支持unsigned 16-bit.
TIFFFILE包 from libtiff import TIFF tif = TIFF.open('filename.tif', mode='r')
img = tif.read_image() TIFFReadDirectory: Warning, Unknown field with tag 33550 (0x830e) encountered. TIFFReadDirectory: Warning, Unknown field with tag 33922 (0x8482) encountered. TIFFReadDirectory: Warning, Unknown field with tag 34735 (0x87af) encountered.
①:首先我们需要有一个自己的备案域名,以baidu.com为例。
②:有一个阿里云的OSS(不懂的可以百度)的bucket ,名称为test。
③:在阿里云的test的bucket 中找到外网访问域名为:test.oss-cn-beijing.aliyuncs.com(仅为例子,以自己实际的为准)
④:在bucket 的域名管理中绑定域名,如图:
上图的 用户域名为自己设置的二级域名,以oss.baidu.com为例,绑定的OSS域名为test的bucket的外网访问域名,即③中的域名。
⑤:进入域名解析界面,对域名进行解析,如图:
上图中 域名是baidu.com,添加解析的时候,记录类型为:CNAME,主机记录为自定义的:oss,记录值为阿里云OSS中test的bucket的外网访问域名 :test.oss-cn-beijing.aliyuncs.com。
设置完毕,等待生效,然后访问:oss.baidu.com/文件名 即可访问
如有问题,请联系QQ群:563752274,答案:Tony。
选择操作: Shift+Left 选择当前位置左边一个字符 Shift+Right 选择当前位置右边一个字符 Shift+Down 从当前行开始向下选择 Shift+Up 从当前行开始向上选择 Ctrl+- 选择一块,就是{}之间的 Shift+F6 选择一行 Shift+PgDn 选择上页 Shift+PgUp 选择下页 Shift+F7,Ctrl+. 选择句子,直到遇到一个.为止 Ctrl+Shift+Home 从当前位置选择到文件开始 Ctrl+Shift+End 从当前位置选择到文件结束 Shift+Home 从当前位置选择到行的开始 Shift+End 从当前位置选择到行的结束 Shift+F5 选择一个单词 Ctrl+Shift+Left 选择左边的单词 Ctrl+Shift+Right 选择右边的单词 光标移动: Ctrl+Shift+N 光标定到查找文件窗口处 Alt+L 光标定到查找符号窗口处 Home 光标到行首 End 光标到行尾 Ctrl+Home 到窗口顶部 Ctrl+End 到窗口底部 Ctrl+Left 到单词左边,即单词的开始处 Ctrl+Right 到单词右边,即单词的结束处 Ctrl+Alt+[ 光标到选择部分的开始 Ctrl+Alt+] 光标到选择部分的结尾 Ctrl+Shift+] 到块的下面,就是到{ 位置 Ctrl+Shift+[ 到块的上面,就是到} 位置 Alt+Left 左滚 Alt+Right 右滚 Alt+Down 向上滚动一行 Alt+Up 向下滚动一行 Ctrl+K 复制一行 ctrl+Shift+K 复制该位置右边的该行的字符 Ctrl+Del 复制到剪贴板 Ctrl+U 剪切一行 Ctrl+; 剪切该位置右边的该行的字符 Ctrl+P 粘贴一行,不同的是它会占一行 Ctrl+I 插入一行 Ctrl+J 删除换行符,把两行变成一行 搜索: Ctrl+F 在本文件中搜索 Ctrl+Shift+F 在多个文件中搜索 F3 向后搜索 F4 向前搜索 F12 转到下一个匹配 Ctrl+H 替换 Ctrl+Shift+H 替换文件 Ctrl+=,Ctrl+点击 跳到定义处 + 到下一个函数定义处,小键盘的+ - 到上一个函数定义处,小键盘的- Alt+, 后退 Atl+.
重置方法:
运行此sql 找到你的管理员帐户: select u.id, u.user_name, u.active from cwd_user u join cwd_membership m on u.id=m.child_user_id join cwd_group g on m.parent_id=g.id join cwd_directory d on d.id=g.directory_id where g.group_name = 'confluence-administrators' and d.directory_name='Confluence Internal Directory'; 并记住管理员帐户的id
运行此sql, 恢复管理员密码为 admin update cwd_user set credential = 'x61Ey612Kl2gpFL56FT9weDnpSo4AV8j8+qx2AuTHdRyY036xxzTTrw10Wq3+4qQyB+XURPWx1ONxp3Y3pB37A==' where id=xxxxxx; 注意此处xxxxxx 为上一步的 id
如果你使用的是zsh ,那么在你使用 find 进行通配符 * 匹配的时候,会出现 zsh: no matches found 的问题
Look!下面是博主在查看 python 所有版本的时候,就遇到了:
这是由于 zsh 导致的,在缺省的情况下,zsh 始终自动解释 * ,传不到给 find 解释
解决方案
1.在 ~/.zshrc 中加入:setopt no_nomatch 2.执行 source ~/.zshrc
现在可以看出 find 可以正确识别了
作为一个在硬件方面知识为空白的coder,偏偏进了一个硬件公司,感觉好吃力,今天一个大神简单讲了一下dsp、mcu、sensor,顺便在网上搜了一下FPGA等知识,怕忘了所以马上记录下来。
IC:Integrated Circuit 集成电路,半导体元件产品的统称,通常指电子元器件,例如:加密IC、电阻、电容、pcb板等。
MCU :Micro Controller Unit 又称单片机,微型计算机,将计算机的CPU、RAM、ROM及各种I/O口集成在一个电路上形成芯片级的计算机。MCU是一种IC(集成电路)单芯片,MCU也是一种IC。中文名称为“微控制单元”,又称单片微型计算机(SingleChipMicrocomputer),简称“单片机”,是指随着大规模集成电路的出现及其发展,将计算机的CPU、RAM、ROM、定时数器和多种I/O接口集成在一片芯片上,形成芯片级的计算机,为不同的应用场合做不同组合控制。
ROM:用于存储数据,类似电脑硬盘
MPU: Micro Processor UnitMCU集成了片上外围器件;MPU不带外围器件(例如存储器阵列),是高度集成的通用结构的处理器,是去除了集成外设的MCU。MCU集成了片上外围器件;MPU不带外围器件(例如存储器阵列),是高度集成的通用结构的处理器,是去除了集成外设的MCU;DSP运算能力强,擅长很多的重复数据运算,而MCU则适合不同信息源的多种数据的处理诊断和运算,侧重于控制,速度并不如DSP。
DSP 数字信号处理芯片,这个用途可做信号处理,例如图像处理,数据采集处理,它比单片要快很多,比单片机功能要强大,比MCU功能更强大。MCU区别于DSP的最大特点在于它的通用性,反应在指令集和寻址模式中。DSP与MCU的结合是DSC,它终将取代这两种芯片。 FPGA、CPLD可变逻辑控制,这个做逻辑处理控制,小型的CPLD是没有中央处理器的,大型可以嵌入系统,功能在单片机之上,适合做大型的数据处理,逻辑控制。其价格不便宜。但是他和单片机有本质的区别。例如单片机有内嵌外设 AD,DA转换等,CPLD则需要通过控制其他外设IC。
以下为转载:
CPU(Central Processing Unit),是一台计算机的运算核心和控制核心。CPU由运算器、控制器和寄存器及实现它们之间联系的数据、控制及状态的总线构成。差不多所有的CPU的运作原理可分为四个阶段:提取(Fetch)、解码(Decode)、执行(Execute)和写回(Writeback)。 CPU从存储器或高 速 缓冲存储器中取出指令,放入指令寄存器,并对指令译码,并执行指令。所谓的计算机的可编程性主要是指对CPU的编程。发展出来三个分枝,一个是DSP(Digital Signal Processing/Processor,数字信号处理),另外两个是MCU(Micro Control Unit,微控制器单元)和MPU(Micro Processor Unit,微处理器单元)。
MPU (Micro Processor Unit),叫微处理器(不是微控制器),通常代表一个功能强大的CPU(暂且理解为增强版的CPU吧),但不是为任何已有的特定计算目的而设计的芯片。这种芯片往往是个人计算机和高端工作站的核心CPU。最常见的微处理器是Motorola的68K系列和Intel的X86系列。
MCU(Micro Control Unit),叫微控制器,是指随着大规模集成电路的出现及其发展,将计算机的CPU、RAM、ROM、定时计数器和多种I/O接口集成在一片芯片上,形成芯片级的芯片,比如51,avr这些芯片,内部除了CPU外还有RAM,ROM,可以直接加简单的外围器件(电阻,电容)就可以运行代码了,而MPU如x86,arm这些就不能直接放代码了,它只不过是增强版的CPU,所以得添加RAM,ROM。
SOC(System on Chip),指的是片上系统,MCU只是芯片级的芯片,而SOC是系统级的芯片,它既MCU(51,avr)那样有内置RAM,ROM同时又像MPU(arm)那样强大的不单单是放简单的代码,可以放系统级的代码,也就是说可以运行操作系统(将就认为是MCU集成化与MPU强处理力各优点二合一)。
SOPC(System On a Programmable Chip)可编程片上系统,上面4点的硬件配置是固化的,就是说51单片机就是51单片机,不能变为avr,而avr就是avr不是51单片机,他们的硬件是一次性掩膜成型的,能改的就是软件配置,说白点就是改代码,本来是跑流水灯的,改下代码,变成数码管,而SOPC则是硬件配置,软件配置都可以修改,软件配置跟上面一样,没什么好说的,至于硬件,是可以自己构建的也就是说这个芯片是自己构造出来的,这颗芯片我们叫“白片”,什么芯片都不是,把硬件配置信息下载进去了,他就是相应的芯片了,可以让他变成51,也可以是avr,甚至arm,同时SOPC是在SOC基础上来的,所以他也是系统级的芯片,所以记得当把他变成arm时还得加外围ROM,RAM之类的,不然就是MPU了。
顺便再讲一下这个SOPC吧,首先上面讲的“白片”一般指的是FPGA或CPLD这类芯片,由于它是可配置的,所以一旦断电,他的硬件配置就没了,当然,软件配置也没了,什么都没了,比如把他硬件配置成51单片机,软件配置为跑流水灯,结果一断电,这个芯片就什么都不是了,恢复原样“白片”。
一般有两种用法,一是用它来验证芯片,因为他是可以多次下载配置验证的,成功后再把这硬件配置下载到一次性的芯片上,如果采用基于hardcopy的SOC则成功率100%,不然每次下载硬件配置验证用SOC等到你调试出正确的硬件配置,那得烧多少芯片啊,毕竟这些是一次性的,不成功只能成仁--扔掉!跟调试软件配置一样,一般软件调试很多次才能成功的,所以他是验证技术,行了再将配置配在其他的芯片,第二种方法是,芯片就用这“白片”,然后把配置信息放到flash里,上电后先将这硬件配置信息烧入这“白片”,使其变成自己想要的芯片,然后再调入软件配置。其中硬件配置可以用quartus软件编写,软件配置可以用NIOS软件,这都是altera公司的产品,可以去查看。
1.所有头文件都应该使用 #define 防止头文件被多重包含, 命名格式当是: <PROJECT>_<PATH>_<FILE>_H_
#ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_ … #endif // FOO_BAR_BAZ_H_ 2.能用前置声明的地方尽量不使用 #include.
当一个头文件被包含的同时也引入了新的依赖, 一旦该头文件被修改, 代码就会被重新编译. 如果这个头文件又包含了其他头文件, 这些头文件的任何改变都将导致所有包含了该头文件的代码被重新编译. 因此, 我们倾向于减少包含头文件, 尤其是在头文件中包含头文件.
使用前置声明可以显著减少需要包含的头文件数量. 举例说明: 如果头文件中用到类 File, 但不需要访问 File 类的声明, 头文件中只需前置声明 class File; 而无须 #include "file/base/file.h".
3.只有当函数只有 10 行甚至更少时才将其定义为内联函数.
定义:
当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.
优点:
当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励 使用内联.
缺点:
滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少 代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行 更快。 4.使用标准的头文件包含顺序可增强可读性, 避免隐藏依赖: C 库, C++ 库, 其他库的 .h, 本项目内的 .
本次实验,主要与CC2530的串口相关。 串口电路图如下所示 首先,先介绍一下CC2530的外设I/O引脚映射,如下图所示,每个外设单元对应两组可以选择的I/O引脚。而外设I/O位置的选择使用由寄存器PERCFG来控制,其中bit1和bit0决定UART1和UART0的位置,0表示外设位置1,1表示外设位置2.
PERCFG |= 0x00;//设置UART0为外设位置1 P0SEL |= 0x0c;//设置P0_2和P0_3作为串口 由映射表可知,I/O映射可能存在冲突,可以通过设置优先级来解决冲突,与优先级设置相关的寄存器是P2SEL和P2DIR.
P2SEL |= 0x40; //端口1UART0优先 P2DIR &= ~0xc0;//端口0UART0为第1优先级 接下来介绍与UART0相关的寄存器
USART0控制与状态寄存器。 U0CSR |= 0x80;//将USART模式选择为UART模式 U0CSR |= 0x40;//使能UART接收器 USART0生成控制寄存器和USART0波特率控制寄存器两者共同决定串口的波特率。 //假设系统时钟为32MHz,设置串口波特率为115200 U0GCR |= 11; U0BAUD |= 216; 时钟控制命令寄存器。 CLKCONCMD &= ~0x40; //设置系统时钟源为32MHz晶振 CLKCONCMD &= ~0x47; //设置系统时钟为32MHz 时钟状态控制寄存器。 while(CLKCONCMD & 0x40);//等待晶振稳定为32MHz USART0接收/发送数据缓冲寄存器 中断标志寄存器5 bit2和bit1分别是USART1和USART0的中断标志位 /*CC2530通过串口发送数据到PC端,由PC端的串口助手打印显示出来*/ #include <ioCC2530.h> #include <string.h> typedef unsigned char uchar; typedef unsigned int uint; #define TX_SIZE 15 #define TX_STRING "ZIGBEE IOT "
Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks.Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.
However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle.
引言 我们经常在golang代码中看到这样一种惯用法:根据选项option或者配置config创建一个对象,而创建对象的工厂函数CreateXXX的输入参数不是一个大的选项结构体Options,而是Option的变长参数。举个例子:
func main() { p := CreatePersion(WithID(123), WithName("tom")) log.Println(p) } func WithID(id int) Option { return func(opts *Options) { opts.ID = id } } func WithName(name string) Option { return func(opts *Options) { opts.Name = name } } type Option func(*Options) type Options struct { ID int Name string } func CreatePersion(opts ...Option) *Person { var options Options for _, opt := range opts { opt(&options) } return &Person{ ID: options.
var j1 = [ { "menuDate": 1, "dinnerTime": "0", "num": 5 }, { "menuDate": 1, "dinnerTime": "0", "num": 1 }, { "menuDate": 1, "dinnerTime": "1", "num": 3 }, { "menuDate": 2, "dinnerTime": "0", "num": 3 }, { "menuDate": 2, "dinnerTime": "0", "num": 6 } ] var jmap = {}; var result = []; j1.forEach(function(al){ var key = al.menuDate + '_' + al.dinnerTime; if(typeof jmap[key] === 'undefined'){ jmap[key] = []; } jmap[key].
1.出现的问题 使用ifconfig命令时,只有lo,没有eth0
当前环境 1.虚拟机上配置静态ip访问外网(NAT模式) 因为作者换了网络,所以虚拟机目前上不了网,所以修改了vi /etc/sysconfig/networt-scripts/ifcfg-eth0目录下的DNS1(配置的静态ip,NAT模式,只需要修改DNS1即可),修改后我使用了service network restart命令进行生效,最后ifconfig查看时只有lo,没有出现eth0。 2.解决办法 1.进入/etc/sysconfig/network-scripts 目录,发现是否存在有ifcfg-eth0,如果存在即网卡(驱动)存在但未启用。 2.输入ifconfig -a命令,可显示eth0和lo。 3.输入ifconfig eth0 up,启用网卡。此时用ifconfig,只能看到inet6(ipv6?)的地址,没有inet的地址。 4.修改/etc/sysconfig/network-scripts/ifcfg-eth0 文件,如下:
DEVICE=eth0 HWADDR=00:0C:29:09:A3:62 TYPE=Ethernet UUID=a1b11b7d-02bf-4485-adf8-4df8f856adca ONBOOT=yes NM_CONTROLLED=no BOOTPROTO="static" IPADDR=192.168.137.200 NETMASK=255.255.255.0 GATEWAY=192.168.137.2 DNS1=192.168.0.1 5.重启
使用root用户进行重启 [hadoop@zhangyu dev]$ sudo service network restart Shutting down interface eth0: [ OK ] Shutting down loopback interface: [ OK ] Bringing up loopback interface: [ OK ] Bringing up interface eth0: Determining if ip address 192.168.137.200 is already in use for device eth0.
CC2530之定时器T3 在本次学习中,主要通过定时器T3周期性的控制LED的亮灭。
首先,先查看相关电路图。由图可知,当CC2530端口1的0号引脚输出低电平时,LED1将被点亮。 接下来,先查看与LED(P1_0)配置相关的寄存器。
端口1功能选择寄存器(P1SEL)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为普通的I/O口,若设置为1,则将相关引脚设为外设I/O,默认值都为0。 端口1方向选择寄存器(P1DIR)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为输入引脚,若设置为1,则将相关引脚设为输出引脚,默认值都为0。 端口1输入模式寄存器(P1INP)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为上拉/下拉模式,若设置为1,则将相关引脚设为三态模式,其中P1_0和P1_1没有上拉/下拉功能,可以不用配置,默认值都为0。 再来看看与定时器T3相关的寄存器
定时器3的控制寄存器(T3CTL) bit7~bit5:设置分频值 bit7:5描述000分频值为1001分频值为2010分频值为4011分频值为8100分频值为16101分频值为32110分频值为64111分频值为128 bit4:定时器T3的启动/停止位。写1表示启动,写0表示停止 bit3:溢出中断掩码。写1表示打开溢出中断,写0表示关闭溢出中断。 bit2:清计数器。写1表示将计数器设置为0并初始化所有相关引脚。 bit1~bit0:设置计数器的计数模式。
bit1:0描述00自由计数,从0x0000计数到0xFFFF,不断重复计数01向下计数一次,由T3CC0计数到0,10模计数,从0x0000计数到T1CC0,不断重复计数11向上/向下计数,从0x0000计数到T1CC0再从T1CC0计数到0x0000,不断重复 定时器3通道0捕获/比较控制寄存器。 bit6:通道0中断掩码。写1表示使能中断,写0表示禁用中断。 bit5~bit3:通道0比较输出模式选择。 bit5:3描述000在比较中设置输出001在比较中清除输出010在比较中切换输出011在比较正计数时设置输出,在0时清除100在比较正计数时清除输出,在0时设置101在比较时设置输出,在0xFF时清除110在比较时清除输出,在0时设置111初始化输出引脚。 CMP[2:0]不变 bit2:定时器3通道0的模式。0表示捕获模式,1表示比较模式。 bit1~bit0:捕获模式选择
bit1:0描述00无捕获01在上升沿捕获10在下降沿捕获11在所有边沿都捕获 定时器3通道0捕获/比较值寄存器 当T3CCTL0.MODE=1(比较模式)时写该寄存器会导致T3CC0.VAL[7:0]更新到写入值延迟到T3CNT.CNT[7:0]=0x00 定时器1/3/4中断掩码/标志寄存器 bit1:定时器3通道0中断标志。0:无中断未决;1:中断未决 bit0:定时器3溢出中断标志。0:无中断未决;1:中断未决 中断标志4寄存器 bit3:定时器3中断标志,当中断发生时置为1,当CPU向量指向中断服务例程时置为0 中断使能寄存器1 bit3:定时器3中断使能。1:中断使能;0:中断失能。 中断使能寄存器0 bit7:总中断使能。 /*利用定时器3,间隔约0.5s将LED电平翻转一次*/ #include <ioCC2530.h> typedef unsigned char uchar; typedef unsigned int uint; #define LED1 P1_0 void LEDInit(void) { P1SEL &= ~0x01; //普通IO P1DIR |= 0x01; //输出模式 } void TIM3Init(void) { T3CTL |= 0xE0; //128分频 T3CTL &= ~0x03; //自由计数 T3CTL |= 0x08; //使能定时器3溢出中断 T3IE = 1; //定时器3中断使能,相当于IEN1 |= 0x08 T3CTL |= 0x10; //启动定时器3 EA = 1; //开启总中断,相当于IEN0 |= 0x80 } uint count; #pragma vector = T3_VECTOR __interrupt void T3_ISR(void) { IRCON = 0x00;//清中断标志,也可由硬件自动完成 /*产生245次中断后,LED发生翻转,时间间隔大概为 128*255*245/16000000 = 0.
最近在弄资源更新,接触了IIS服务的使用及配置的一些方法,做做笔记方便以后查看
配置服务的密钥 服务器IP 版本文件的地址
CC2530之定时器T1 在本次学习中,主要通过定时器来控制LED的亮灭。 首先,先查看相关电路图。由图可知,当CC2530端口1的0号引脚输出低电平时,LED1将被点亮。 接下来,先查看与LED(P1_0)配置相关的寄存器。
端口1功能选择寄存器(P1SEL)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为普通的I/O口,若设置为1,则将相关引脚设为外设I/O,默认值都为0。 端口1方向选择寄存器(P1DIR)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为输入引脚,若设置为1,则将相关引脚设为输出引脚,默认值都为0。 端口1输入模式寄存器(P1INP)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为上拉/下拉模式,若设置为1,则将相关引脚设为三态模式,其中P1_0和P1_1没有上拉/下拉功能,可以不用配置,默认值都为0。 再来看看与定时器相关的寄存器 1. 定时器1的控制寄存器(T1CTL)_。 该寄存器的bit3和bit2位用来设置分频值 - 00:分频值为1 - 01:分频值为8 - 10:分频值为32 - 11:分频值为128 bit1和bit0位用来设置计数模式 - 00:暂停计数 - 01:自由计数,从0x0000计数到0xFFFF,不断重复计数。 - 10:模计数,从0x0000计数到T1CC0,不断重复计数。 - 11:向上/向下计数,从0x0000计数到T1CC0再从T1CC0计数到0x0000,不断重复。 定时器1状态标志寄存器(T1STAT)。
bit5:定时器1的溢出中断标志bit4:定时器1通道4的中断标志bit3: 定时器1通道3的中断标志bit2:定时器1通道2的中断标志bit1:定时器1通道1的中断标志bit0:定时器1通道0的中断标志 中断标志4寄存器(IRCON)。
bit1:定时器1中断标志,当中断发生时置为1,当CPU向量指向中断服务例程时置为0 /*设置定时器,当发生溢出中断时,LED进行一次翻转*/ #include <ioCC2530.h> typedef unsigned char uchar; typedef unsigned int uint; #define LED1 P1_0 void LEDInit(void) { P1SEL &= ~0x01; P1DIR |= 0x01; } void TIM1Init(void) { T1CTL |= 0x0d;//128分频,自由计数模式 } void main(void) { LEDInit(); TIM1Init(); while(1) { if(IRCON>0) //是否发生中断 { LED1 = !
在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。
但是局部变量也有问题,就是在函数调用的时候,传递起来很麻烦:
def process_student(name): std = Student(name) # std是局部变量,但是每个函数都要用它,因此必须传进去: do_task_1(std) do_task_2(std) def do_task_1(std): do_subtask_1(std) do_subtask_2(std) def do_task_2(std): do_subtask_2(std) do_subtask_2(std) 每个函数一层一层调用都这么传参数那还得了?用全局变量?也不行,因为每个线程处理不同的Student对象,不能共享。
如果用一个全局dict存放所有的Student对象,然后以thread自身作为key获得线程对应的Student对象如何?
global_dict = {} def std_thread(name): std = Student(name) # 把std放到全局变量global_dict中: global_dict[threading.current_thread()] = std do_task_1() do_task_2() def do_task_1(): # 不传入std,而是根据当前线程查找: std = global_dict[threading.current_thread()] ... def do_task_2(): # 任何函数都可以查找出当前线程的std变量: std = global_dict[threading.current_thread()] ... 这种方式理论上是可行的,它最大的优点是消除了std对象在每层函数中的传递问题,但是,每个函数获取std的代码有点丑。有没有更简单的方式?
ThreadLocal应运而生,不用查找dict,ThreadLocal帮你自动做这件事:
import threading # 创建全局ThreadLocal对象: local_school = threading.local() def process_student(): print 'Hello, %s (in %s)' % (local_school.
1.背景 公司一个后台模块要用到插入表格的功能,之前项目中使用的是 Umeditor,UEditor 的迷你版,然后悲催地发现 umeditor 中并没有插入表格的功能,好吧,只能换插件了。因为对百度富文本的风格较为熟悉,所以果断换完整版的 UEditor 了。于是开始了貌似短暂却充满艰辛的 ueditor 探(tong)索(ku)之路。
2.引入 Editor 插件(1)下载 链接一(ueditor 官方下载路径):http://ueditor.baidu.com/website/download.html 链接二(文档说明):http://fex.baidu.com/ueditor/ (2)引入到项目中,结构如下 ① demo.html 文件是依据链接二中的文档说明新增的,其他均为插件中。
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title>ueditor demo</title> </head> <body> <!-- 加载编辑器的容器 --> <script id="container" name="content" type="text/plain"> 这里写你的初始化内容 </script> <!-- 配置文件 --> <script type="text/javascript" src="ueditor.config.js"></script> <!-- 编辑器源码文件 --> <script type="text/javascript" src="ueditor.all.js"></script> <!-- 实例化编辑器 --> <script type="text/javascript"> var ue = UE.getEditor('container'); </script> </body> </html> 此时,不需要修改任何东西,直接访问demo.html 就可以看到编辑器: 3.实现图片上传 一般情况下,现在其实功能都可以用了,只要保证你的路径配置是正确的,图片上传也没毛病。但是,可能你也会像我一样衰到上传图片几乎百度能搜到的几个常见问题基本一个不落地碰到,哭死……好吧,在看这种异常情况之前,我们先来了解几个重要的文件:
① ueditor.
1、ugui中的层级是按先渲染者在下面,即在同一个画布中节点越靠上,越先渲染越在底层,画布间用sortOrder参数设置层级 2、ugui中image会挡住button的事件, 这种情况只需要为Image添加 CanvasGroup組件,或者将button放在画布的最下方 3、组件的对齐设置注意Pivot的设置,x+y=1; 4、ugui文本中设置字体的颜色,粗体、斜体、大小等: Tag Description Example Notes b 将呈现粗体文本 We are <b>not</b> amused. i 将呈现斜体文本 We are <i>usually</i> not amused. size 设置文本大小的参数值,根据给定的像素数 We are <size=50>largely</size> unaffected. 虽然此标记是可用于Debug.Log,如果大小设置太大,你会发现在控制台的窗口栏中的行间距看起来很奇怪。 color 设置文本的颜色的参数值。在传统的HTML格式,可以指定颜色。#rrggbbaa…那里字母对应成对的十六进制数字表示红、绿、蓝和 alpha(透明度)值的颜色。 <color=#00ffffff>… 另一种选择是使用颜色的名称。这是容易理解,但自然的颜色范围是有限的,他们总是设定为完全不透明。 <color=cyan>……在下表中给出可用的颜色名称。 http://bbs.9ria.com/thread-420408-1-1.html 5、鼠标悬停、按下等事件接口 接口 说明 方法 IPointerEnterHandler 当鼠标在按钮上时系统自动调用此方法 public void OnPointerEnter(PointerEventData eventData) IPointerDownHandler 当按钮被按下后系统自动调用此方法 public void OnPointerDown(PointerEventData eventData) IPointerUpHandler 当按钮抬起的时候自动调用此方法 public void OnPointerUp(PointerEventData eventData) IPointerExitHandler 当鼠标从按钮上离开的时候自动调用此方法 public void OnPointerExit(PointerEventData eventData)
在本次学习中,主要通过外部中断来控制LED的亮灭。 首先,先查看相关电路图。由图可知,当CC2530端口1的0号引脚输出低电平时,LED1将被点亮,当按键S1按下时,端口0的1号引脚将为低电平,抬起时为高电平。在接下来的实验过程中,将通过配置使按键按下时产生中断。 接下来,先查看与LED(P1_0)配置相关的寄存器。
端口1功能选择寄存器(P1SEL)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为普通的I/O口,若设置为1,则将相关引脚设为外设I/O,默认值都为0。 端口1方向选择寄存器(P1DIR)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为输入引脚,若设置为1,则将相关引脚设为输出引脚,默认值都为0。 端口1输入模式寄存器(P1INP)。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为上拉/下拉模式,若设置为1,则将相关引脚设为三态模式,其中P1_0和P1_1没有上拉/下拉功能,可以不用配置,默认值都为0。 再来看看与中断相关的寄存器
端口中断控制寄存器(PICTL)。该寄存器的最低位控制端口0输入模式下的中断配置,当该位为0时,表示输入的上升沿引起中断,该位为1时,表示输入的下降沿引起中断。 端口0中断屏蔽寄存器(P0IEN)。该寄存器控制端口0下8位引脚的中断使能,将相应位设置为0,表示禁用相应引脚的中断;将相应位设置为1,表示使能相应引脚的中断. 端口0中断状态标志寄存器(P0IFG)。当发生中断时,相应位将被置1. 中断使能寄存器1(IEN1)。该寄存器的bit5位为端口0的中断使能位,将该位设置为1,表示打开端口0中断,设置为0,表示禁用端口0中断。 中断使能寄存器0(IEN0)。该寄存器的最高位为中断总开关,将该位设置为1,表示打开总中断,设为0,表示禁用所有中断。 /* 按下按键S1,使LED发生翻转 */ #include <ioCC2530.h> typedef unsigned char uchar; typedef unsigned int uint; #define LED1 P1_0 #define KEY1 P0_1 void delay_ms(uint ms) { uint i,j; for(i=0;i<ms;i++) for(j=0;j<555;j++); } void initLed(void) { P1SEL &= ~0x01; //设置P1_0为普通IO P1DIR |= 0X01; //设置P1_0为输出模式 } void initKey(void) { P0IEN |= 0X02; //P0.1中断使能 PICTL |= 0X01; //P0口下降沿触发 IEN1 |= 0x20; //允许P0口中断 P0IFG = 0X00; //初始化中断标志位 EA = 1; //总中断使能 } /* 在IAR编译器里用__interrupt来定义一个中断函数。 用#pragma vector = P0INT_VECTOR来提供中断函数的入口地址 P0_ISR为函数名,可以修改。 */ #pragma vector = P0INT_VECTOR __interrupt void P0_ISR(void) { delay_ms(10); LED1 = !
这次会介绍三篇文章,因为原理比较相似,都是采用分层架构来解决多轮对话问题,三篇论文如下所示:
Building End-To-End Dialogue Systems Using Generative Hierarchical Neural Network Models(HRED)A Hierarchical Latent Variable Encoder-Decoder Model for Generating Dialogues(VHRED)Attention with Intention for a Neural Network Conversation Model(AWI) 前面两篇出自Serban,文章思路和方法大体一致,后者在第一篇文章的基础上加入了变分编码机的思路,改善了模型的效果。而第三篇论文将Attention机制融合到分层seq2seq模型中,同样是引入了高层变量的方法。下面分别介绍三篇文章的具体细节:
HRED 模型的系统架构图如下所示:
简单来说就是使用分层的seq2seq模型构造多轮对话,Encoder RNN主要用于对输入句子进行编码,这里跟普通的seq2seq没有什么区别,并且把最后一个时刻的隐层向量认为是输入句子的编码向量,当做下一层RNN的输入向量。中间一层context RNN用来编码整个对话的状态、意图等对话层面的信息,而第一层RNN用来编码一句话的句子层面信息,中间层每个时刻输入的第一层输出的句子表示向量,这样context RNN的隐藏层向量就可以记住之前的对话信息,所以成为上下文向量。最后,将该编码了之前对话信息的向量作为decoder RNN的输入向量,使得在解码过程中除了使用回答句子本身信息还会结合对话上下文信息。这就是整体的架构,还有几个小的点需要注意一下:
Encoder和Decoder RNN每个句子是一个RNN,而Context RN只有一个RNN;在编码和解码阶段,处理每个句子的RNN结构完全相同而且共享参数(“The same encoder RNN and decoder RNN parameters are used for every utterance in a dialogue”),目的是为了生成一般化的语言模型;在解码阶段,每个时刻都会把Context RNN的输出与该时刻的输入并联一块作为输入,目的是是的每个解码时刻都可以引入上下文信息。 但是论文中也有提到这种方法效果并不是很好,反而会受预训练模型的影响比较严重,比如与训练的词向量和适用别的任务对参数预训练,这些预训练的参数对模型的准确度提升有着显著效果。
VHRED 前面说了HRED模型效果一般,所以作者后面提出在Context RNN环节引入一个高斯随机变量来改善模型产生回答的多样性。其模型架构图如下所示:
作者认为在传统的seq2seq模型中唯一变化的因素就是输出序列概率分布的不同导致输出发生变化,这在多轮对话中显然是无法满足对话响应的多样性需求。因为一旦输出的第一个词确定之后,后面的单词基本上都是根据语言模型确定,而且每个编码时刻的隐层向量hm更倾向于记住短期依赖而不是全局信息。因此为了引入更多的变化因素,作者引入变分编码的思想,在Context RNN环节加入一个高斯随机变量zn,以增加响应的多样性。
Zn的均值和方差都是根据Context RNN的隐藏层向量计算的,现将其传入一个两层神经网络增加一定的变化性,然后将该神经网络的输出与一个矩阵相乘得到均值,再将该输出与另一个矩阵相乘经过一个softplus函数得到方差。有了均值和方差之后便可以经过采样得到高斯变量Zn,将其与Context RNN拼接就相当于加入了噪声,可以一定程度上增加模型的变化性。
Attention with Intention 跟上面两个模型的思路很想,本文也是使用分层的seq2seq模型来解决多轮对话问题,但是跟上面不一样的是融入了Attention机制,以改善模型的效果。模型主要包括Encoder RNN、Intention RNN、Decoder RNN三个模块,架构图如下所示:
现在大部分游戏使用的寻路算法都是A*,但是如果游戏中的NPC或都AI智能体太多的时候,使用A*会特别消耗性能,这时可以考虑使用流场寻路,流场寻路的介绍及基本使用方法在如下链接中:
https://howtorts.github.io/2014/01/04/basic-flow-fields.html
CC2530之按键与LED 在本次学习中,主要是通过板载按键来控制LED的亮灭。 首先,先来查看与LED及按键相关的电路图。 由图可知,当CC2530端口1的0号引脚输出低电平时,LED1将被点亮。当按键S1按下时,端口0的1号引脚将为低电平,抬起时为高电平。 接下来,先查看与LED(P1_0)配置相关的寄存器。 1. 端口1功能选择寄存器。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为普通的I/O口,若设置为1,则将相关引脚设为外设I/O,默认值都为0。 2. 端口1方向选择寄存器。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为输入引脚,若设置为1,则将相关引脚设为输出引脚,默认值都为0。 3. 端口1输入模式寄存器。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为上拉/下拉模式,若设置为1,则将相关引脚设为三态模式,其中P1_0和P1_1没有上拉/下拉功能,可以不用配置,默认值都为0。 再来看看与按键S1(P0_1)配置相关的寄存器。 1. 端口1功能选择寄存器。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为普通的I/O口,若设置为1,则将相关引脚设为外设I/O,默认值都为0。 2. 端口1方向选择寄存器。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为输入引脚,若设置为1,则将相关引脚设为输出引脚,默认值都为0。 3. 端口1输入模式寄存器。这是一个8位的寄存器,对应端口1的8个引脚,将相应位设为0,表示将相应引脚设置为上拉/下拉模式,若设置为1,则将相关引脚设为三态模式,其中P1_0和P1_1没有上拉/下拉功能,可以不用配置,默认值都为0。 /* 本实验效果,每按一次按键,LED效果翻转一次 */ #include <ioCC2530.h> typedef unsigned char uchar; typedef unsigned int uint; #define LED1 P1_0 #define KEY1 P0_1 void delay_ms(uint ms) { uint i,j; for(i=0;i<ms;i++) for(j=0;j<555;j++); } void LEDInit(void) { P1SEL &= ~0x01; //设置P1_0为普通IO P1DIR |= 0X01; //设置P1_0为输出模式 } void KEYInit(void) { P0SEL &= ~0x02; //设置P0_1为普通IO P0DIR &= ~0x02; //设置P0_1为输入模式 P0INP &= ~0x02; //设置P0_1为上拉模式 } /*扫描按键是否按下*/ uchar KEYScan(void) { if(KEY1 == 0) { delay_ms(10); if(KEY1 == 0) { while(!
import requests import json kd_dict = {1:'shentong',2:'ems',3:'shunfeng',4:'yuantong',5:'zhongtong',6:'yunda',7:'tiantian',8:'huitong',9:'quanfeng',10:'debang',11:'zhaijisong'} while 1: print('请选择您的快递公司:') print('1.申通快递:') print('2.EMS邮政快递:') print('3.顺丰递运:') print('4.圆通快递:') print('5.中通快递:') print('6.韵达快递:') print('7.天天快递:') print('8.汇通快递:') print('9.全峰快递:') print('10.德邦物流:') print('11.宅急送:') num = int(input('选择您的快递公司:')) while num not in range(1,12): num = int(input('选项有误,请重选:')) type = kd_dict[num] postid = input('请输入您的快递单号:') url = 'http://www.kuaidi100.com/query?type=%s&postid=%s'%(type,postid) rs = requests.get(url) kd_info = json.loads(rs.text) msg = kd_info['message'] if msg == 'ok': print('您的快递%s物流信息如下:'%postid) data = kd_info['data'] for data_dict in data: time = data_dict['time'] context = data_dict['context'] print('时间:%s %s'%(time,context)) else: if msg == '参数错误': print('您输入信息有误,请重输:') else: print(msg)
本文转载自:https://www.jianshu.com/p/84983a3bdbff,感谢原创作者!
什么叫冷启动和热启动?
拿起你的手机,把后台的任务都清理掉,然后再点击你想要打开的app图标,这个时候,就是所谓的app冷启动了。有人肯定会说,有冷启动那不是还有热启动?对的,当你退出app的时候,没把后台的任务清理,并且系统没有把这个app的进程服务给干掉,然后你点击这个app的图标再次进入的时候,这就是热启动了。
冷启动造成APP假死状态?
有时候,你在打开一个app的时候会发现,你点击了这个app的图标,打开了之后会出现一段时间的白屏或者图标卡顿了一会再进入app界面,这个时候你就会吐槽了,为什么会那么卡的?难道是我的手机永久了变卡的原因吗?并不是的,这是因为app的冷启动时间过长的原因造成app进入假死状态了。
后续假死优化方法请看https://www.jianshu.com/p/84983a3bdbff。
首先按照官方文档写出html结构样式,
如下:
<div class="goodContent" ref="goodContent"> <div> <!-- 顶部提示信息 --> <div class="top-tip"> <span class="refresh-hook">下拉刷新</span> </div> <ul> <li v-for="(num,key) in 30" :key="key" @click='_numClick(key)'>{{num}}</li> <li v-for="(person,key) in persons" :key="key">{{person.name}}</li> </ul> <!-- 底部提示信息 --> <div class="bottom-tip"> <span class="loading-hook">加载更多</span> </div> </div> </div> 其中的提示信息视情况使用,这里要注意的是一定要给最外层的div添加个定位;没有定位将导致页面无法滑动; 然后就是按照官方文档给的接口去写你需要用到的方法,示例如下: 这里需要注意的是bscroll初始化的时候
1.可以按一下上\下方向键,命令行就会显示相对于当前命令的上一条或下一条历史记录.
2.和方向键相同功能的就是组合键Ctrl+ p (前面执行过的命令),Ctrl +n(后面执行过的命令).
2.上面两个都是相对于当前命令查询上一条或者下一条命令的历史记录.如果搜索命令历史记录,
就用Ctrl+ r 组合键进入历史记录搜寻状态,然后,键盘每按一个字母,当前命令行就会搜索出命令历史记录.
1. history作用 linux的history命令的作用是,记录执行过的命令。 用法: history [n] n为数字,列出最近的n条命令 -c 将目前shell中的所有history命令消除 history [-raw] histfiles -a 将目前新增的命令写入histfiles, 默认写入~/.bash_history -r 将histfiles内容读入到目前shell的history记忆中 -w 将目前history记忆的内容写入到histfiles shell > history 34 14-10-28 16:19:24 ll 35 14-10-28 16:19:26 vim test 36 14-10-28 16:19:33 ll 37 14-10-28 16:19:34 ll shell > history 3 1032 14-11-02 16:10:41 history 1033 14-11-02 16:10:46 history |more 1034 14-11-02 16:11:15 history 3 使用! 执行历史命令。 ! number 执行第几条命令 !
程序的世界,从某种角度来说,存在两种角色, 功能提供者和功能使用者。一个良好的设计是提供者和使用者是松耦合的,提供者需要思考怎样设计才能做到对使用者影响最小。这就产生了一些设计原则和设计模式,指导提供者进行代码设计。
前人总结出来23种设计模式,今天看下代理模式。
代理模式分静态代理和动态代理。
静态代理, 代理类和被代理类实现相同接口,代理对象依赖被代理对象干活。代理类是服务提供者手动编写的,编译生成字节码由classloader加载。下面是静态代理的类图。
动态代理,与静态代理不同的是,代理类是程序运行过程中由一些框架帮助自动生成字节码文件由classloader加载。
根据框架不同,动态代理类或者实现被代理类的接口,或者直接继承被代理类。不管什么框架,动态代理类有一个共同点,动态代理类中的所有方法都是委托给一个handler实现。
我目前了解到的可以生成动态代理类的三种框架, JDK Proxy, CGLIB和Javassist。
JDK Proxy动态代理类图如下:
CGLIB动态代理类图如下:
Javassist动态代理类图如下:
代理模式的一些例子:
远程对象访问(RMI),客户端的stub就是服务端服务的代理,客户端用户,就像调用本地服务一样调用远程服务,其实并不知道或者也不关心, RMI框架实际提供的服务对象是一个stub, stub封装了与远程对象通信的复杂流程。
Spring AOP是代理模式的典型应用,在不改变被代理对象的情况下,通过在其方法执行前后或者捕获某些异常等情况下添加一些业务逻辑,不改变业务接口却可以实现功能扩展。
在上一篇文章Tensorflow Dataset API详解里面,我们说Datasets API和Estimators API是TensorFlow 1.3开始引入的两个高级API。其中,Estimators API 提供了训练模型、测试模型准确率和生成预测的方法。在这篇文章里面,我准备对Estimator API做一个基本讲解,其中主要内容还是来源于官方文档。
首先,还是先看看tensorflow中Estimators API的组成图:
从上图我们可以知道:Estimators分为Pre-made Estimators和custom Estimators两大类。其中,tf.estimator.Estimators是基类(base class),pre-made Estimators是基类的子类,而custom Estimators则是基类的实例(instance)。
Pre-made Estimators和custom Estimators差异主要在于tensorflow中是否有它们可以直接使用的模型函数(model function or model_fn)d的实现。对于前者,tensorflow中已经有写好的model function,因而直接调用即可;而后者的model function需要自己编写。因此,Pre-made Estimators使用方便,但使用范围小,灵活性差;custom Estimators则正好相反。
Your model function could implement a wide range of algorithms, defining all sorts ofhidden layers andmetrics. Like input functions, all model functions must accept a standard group of input parameters and return a standard group of output values. Just as input functions can leverage the Dataset API,model functions can leverage the Layers API and the Metrics API.
import React,{Component} from 'react'; import {View,Text} from 'react-native'; export default class Demo13Component extends Component{ render(){ return ( <View> <View style={{height:100,width:100,backgroundColor:'#eee',alignItems:'center'}}> <Text>水平居中</Text> </View> <View style={{height:100,width:100,backgroundColor:'green',justifyContent:'center'}}> <Text>垂直居中</Text> </View> <View style={{height:100,width:100,backgroundColor:'red',alignItems:'center',justifyContent:'center'}}> <Text>水平垂直居中</Text> </View> </View> ) } }
一:扩展运算符 1:含义
扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。扩展运算符内部调用的是数据结构的 Iterator 接口
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
(1)该运算符主要用于函数调用
function push(array, ...items) {
array.push(...items);
}
上面代码中,array.push(...items)是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。
(2)扩展运算符与正常的函数参数可以结合使用
function add(x, y) {
return x + y; }
const numbers = [4, 38];
add(...numbers) // 42
(3)扩展运算符后面还可以放置表达式
const arr = [
...(x > 0 ? ['a'] : []),
'b',
];
如果扩展运算符后面是一个空数组,则不产生任何效果。
[...[], 1]
// [1]
二:扩展运算符的应用 (1)复制数组 数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。
符号表文件.dSYM实际上是从Mach-O文件中抽取调试信息而得到的文件目录,实际用于保存调试信息的问价是DWARF,其出身可以从苹果员工的文章《Apple’s “Lazy” DWARF Scheme》了解一二。
1、Xcode自动生成 Xcode会在编译工程或者归档时自动为我们生成.dSYM文件,当然我们也可以通过更改Xcode的若干项Build Settings来阻止它那么干。
2、手动生成 另一种方式是通过命令行从Mach-O文件中手工提取,比如:
Xcode 生成项目app路径为
/Users/kangxg/Library/Developer/Xcode/DerivedData/ettNextGen-hcoabpnaanaokcelcdxxabpdvbng/Build/Products/Debug-iphoneos/ettNextGen.app/ettNextGen 提取命令
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/kangxg/Library/Developer/Xcode/DerivedData/ettNextGen-hcoabpnaanaokcelcdxxabpdvbng/Build/Products/Debug-iphoneos/ettNextGen.app/ettNextGen -o ettNextGen.dSY 为了方便 可以包app包 复制放到需要的位置 提取命令:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/kangxg/Desktop/未命名文件夹/ettNextGen.app/ettNextGen -o ettNextGen.dSYM 这时候在目录中就可以看到 生成的 dSYM
python + selenium + chrome 如何清理浏览器缓存 1. 背景 在使用selenium + chrome浏览器渲染模式爬取数据时,如果并发任务过多,或者爬虫的运行时间很长,那么很容易出现浏览器崩溃的现象,如下: 这一般是资源消耗过大造成的(据说chrome浏览器有内存泄漏的情况。或者是浏览器缓存过大,越堆越多)。selenium模拟浏览器会产生大量的临时文件,那如何解决这个问题呢? 之前提出一个解决方法,就是使用headless模式,减少渲染文件的产生,文章可以参考:http://blog.csdn.net/zwq912318834/article/details/79000040今天要提出另一种思路:那就是直接清除浏览器缓存。 2. 环境 python 3.6.1系统:win7IDE:pycharm安装过chrome浏览器配置好chromedriverselenium 3.7.0 3. 清除浏览器缓存 3.1. 只清cookie # 清除浏览器cookies cookies = browser.get_cookies() print(f"main: cookies = {cookies}") browser.delete_all_cookies() 3.2. 清除浏览器所有缓存垃圾 在selenium爬虫启动时,定时开一个窗口,在地址栏键入:chrome://settings/content 或 chrome://settings/privacy,然后由程序,像操作普通网页一样,对浏览器进行设置,“ 清除数据 ”,然后进行保存。如下所示: 关于selenium窗口切换可以参考这篇文章:http://blog.csdn.net/zwq912318834/article/details/79206953
U盘打不开的情况下,不仅不能往U盘里面存放文件,原本盘里的文件也无法使用了。很多人不知该如何解决这类问题,无奈之下选择放弃U盘重置一块新的。要想解决U盘无法打开的问题,我们先来看看U盘打不开的常见情况:
一、U盘打不开的常见情况:
1、U盘中毒;
2、U盘接入电脑却提示需要格式化;
3、U盘接入电脑,却提示“无法识别的设备”;
4、点击U盘盘符,电脑提示“无法访问”;
5、U盘接入电脑却没有任何反应。
二、解决方法
1、U盘中毒:
对U盘进行全盘的杀毒扫描,可利用数据恢复软件来恢复数据。不过最好另备一块新U盘来存放数据。需要说明的是,有些病毒以破坏文件为主要目的,杀毒软件和数据恢复软件都是不能修复破损数据的。
2、U盘接入电脑却提示需要格式化: 同样可用数据恢复软件来恢复数据。先将U盘中的数据恢复保存到安全磁盘中,再格式化U盘,看U盘能否恢复正常。
3、U盘接入电脑,却提示“无法识别的设备”:
如果U盘的工作频率和电脑不能同步,系统就会提示无法识别,那么可以考虑换晶振。如果晶振正常,那可能是主控坏了。或者考虑线下的人工恢复,更加精准地检测。
4、点击U盘盘符,电脑提示“无法访问”:
可以先换几台电脑设备接入看看,如果依旧无法访问U盘,那么就要考虑到是否U盘硬件问题了。一个简单方法判断U盘是否有硬件问题:鼠标右键点击“我的电脑”,选择“管理”,点击“磁盘管理器”,进入查看U盘能否正常显示盘符和内存。若不正常,则很有可能是硬件问题,需要人工恢复。
5、U盘接入电脑却没有任何反应:
请专业人员查看U盘的相关参数。
对于模型构建器的初学者来说,有些学员仅会打开模型构建器的对话框创建新的模型,然而在模型构建器创建完成之后,想要重新进行编辑却不知如何操作,因为双击创建好的模型会弹出工具对话框,而不会打开模型构建器的编辑页面。有些学员甚至会再重建一个新的模型构建器进行工作,这就导致了重复的工作量并浪费了我们的时间。其实该操作非常简单,只需在Catalog中右键创建完成的模型,单击【编辑】选项即可。
模型构建器创建完成之后,会以一个工具的形式存储在工具箱或者文件夹中,在Catalog中,双击打开,会以工具对话框的形式展示,但是用户有时发现打开之后对话框的形式如下:
对话框中无任何参数,想要换个数据或者设置一下参数运行,还必须打开模型构建器进行重新编辑,这为我们带来了很大的麻烦,对于一些不会使用模型构建器的人来说更是难上加难。那么如何设置这个参数呢:
在模型构建器的对话框中,右键想要在对话框中添加参数选项的的参数,然后选择【模型参数】选择,在该参数的右上角会出现一个P的字母,然后依次在想要显示的参数上进行该操作,最后运行并保存模型即可。
博主在项目期间遇到一个需求,就是搜索关键词时需要高亮显示,我相信很多小伙伴有同样的经历,因此,整理了一下。
没啥说的,直接上代码,很简单的。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>实现查找关键字高亮显示</title> <style type="text/css"> #box{ height:200px; width:500px; margin:50px auto; border:2px solid #eee; text-indent:20px; } #inpt{ text-align:center; } li{ list-style-type: none; margin: 10px 0; } </style> </head> <body> <div id="box"> <ul> <li>测试文本1:博主大帅哥一枚,</li> <li>测试文本2:转载收藏此博文的比博主还帅还漂亮。</li> <li>测试文本3:博主有点飘;早晚要挨刀!</li> </ul> </div> <div id="inpt"> <input type="text" id="testTxt" placeholder="请输入关键字"/> <input type="button" id="btn" value="确定"/> </div> <script type="text/javascript"> var oBox = document.getElementById("box"); var oContent = oBox.innerHTML; var testTxt = document.getElementById("testTxt"); var oBtn = document.
[ERROR] Unknown lifecycle phase "mvn". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1] org.apache.maven.lifecycle.LifecyclePhaseNotFoundException: Unknown lifecycle phase "mvn". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>.
adaboost+hog识别目标 前言:我们将要产生一个包含级联分类器的.xml文件(包含级联分类器的信息),也就是最为关键的一部分 将用到opencv_cratesample.exe和opencv_traincascade.exe(在opencv\build\x64\vc14\bin目录下,如果你是32位选择VC12)。
正负样本的准备 (补充)正负样本图片和工具下载 1.准备工作: 我们要建立一个文件夹,可以命名为my_det,opencv_haartraining.exe/opencv_traincascade.exe复制过来,并且在此路径下建立正负样本文件夹,这里我把正负样本文件夹命名为pos_image,neg_image。 ==注意==: ① 一般做的时候正负样本的比例大约为1:3,样本当然是越多越精确。我用了1001个正样本和3147个负样本来做测试!对于正样本,要对其进行==剪裁(也就是图片要在包含目标的前提下最小)。==看下面的例子:
剪裁前: 剪裁后: ② 把所有的素材剪裁好后,然后还需要把这些剪裁好的图片处理成比较小的灰度图(黑白图片),大小一般为24X24(或者48X48),大了不容易处理;==正负样本一定要命名规律!便于后面路径的添加,或者用批量修改名称代码~==
注意:图片的名字里面不要包括空格,减号“-”等,只用字母数字和下划线,要不然前面说的.exe读不出来。 一、正样本尺寸灰度处理 先在VS2015下搭建Opencv开发条件: 搭建链接 然后在pos_imagze中加入正样本,并用代码转化成24X24的灰度图片,按下图所示: 接下来在命令行里生成正样本描述文件(文本文件)。进入命令行输入一下命令(进入pos_image,输入dir /b >../pos_image.txt),==别忘了pos_image是我们正样本文件夹名字。== 然后打开后在每个文件上加上目录,正样本还有修改后缀,用文本的替换,这就是为什么图片命名要有规律原因! 编辑->替换 如图: 最终: 二、负样本处理 负样本要求很低,彩色图片也行,大小只要比正样本大就行。把他们放进neg_image文件夹里。并且生成负样本描述文件,修改好! ==注:==负样本不需要修改后缀!
一.使用Command和DataReader对象:
(1).首先连接数据库有两种模式:
1.混合连接模式 该模式需要输入登录名和密码
代码如下:
string Myconnection ="server=服务器名称(如果是本地也可以用.来代替);database=连接的数据库名称;";uid=登录名;pwd=密码";
SqlConnection conn=new SqlConnection(Myconnection);
2.Window连接模式 该模式必须将Trusted_connection=true
string Myconnection="server=服务器名称;database=连接的数据库名称;Trusted_connection=true";
SqlConnection conn=new SqlConnection(Myconnection);
(2).调用Connection对象的Open方法打开连接
(3).连接数据源(指的是连接到具体的数据库文件中)有两种方式
1.通过Command对象和DataReader对象
2.通过DataSet对象和DataAdapter对象(适用于经常更改数据库)
(4).从数据源读取数据 (5).调用Command对象的Close方法关闭连接 二.下面是两种连接数据源方法的代码:
(Command对象和DataReader对象)此方法需要引用using System.Data.SqlClient命名空间
string StrSql = "server=.;database=BookDB;trusted_connection=true";
SqlConnection conn = new SqlConnection(StrSql);
SqlCommand com = new SqlCommand();
//封装连接数据源的方法
ADOCRUDByCommend(conn, com);
//使用try catch finally catch可以将Try代码块的错误捕捉,而且使用该方法的好处是try中的代码无论是否出错都可以编译,如果代码出错catch将会显示出错,最后执行finally中的语句。
try
{
conn.Open();
//数据库中的CRUD(增删查改)操作语句
string Sqlstr = "select * from Table1";
//string Sqlstr = "insert into Table1 values('05','005','0005','0005')";
//string Sqlstr = "
Anaconda作为一个工具包集成管理工具,下载python工具包是很方便的,直接敲:
conda install package_name 但是有时候安装一个工具包(如skimage)的时候,在当前的channels中找不到这个包,会提示:
PackageNotFoundError: Packages missing in current channels: - skimage We have searched for the packages in the following channels: - https://repo.continuum.io/pkgs/main/linux-64 - https://repo.continuum.io/pkgs/main/noarch - https://repo.continuum.io/pkgs/free/linux-64 - https://repo.continuum.io/pkgs/free/noarch - https://repo.continuum.io/pkgs/r/linux-64 - https://repo.continuum.io/pkgs/r/noarch - https://repo.continuum.io/pkgs/pro/linux-64 - https://repo.continuum.io/pkgs/pro/noarch 这个时候,我们可以使用下面的指令来查找我们想要安装的包(以skimage为例)
$ anaconda search -t conda skimage 如上图所示,这里我们找到了一个可用的skimage包,名为DavidMertz/accelerate-skimage。
接着,我们使用show指令来查看该包的详细情况
$ anaconda show DavidMertz/accelerate-skimage 根据提示,我们使用下面的指令install这个包
$ conda install --channel https://conda.anaconda.org/DavidMertz accelerate-skimage 选择y(yes),然后等待下载安装 安装完成后,我们可以打开python试试是否已经成功导入了skimage包,如果在python输入import skimage而不报错,就是成功了
$ python Python 3.5.4 |Anaconda, Inc.| (default, Nov 20 2017, 18:44:38) [GCC 7.
如果首次把项目从git远程仓库pull到本地,然后想切换到已经存在的某个分支上,直接使用git checkout 分支名,这个时候是无效的,会出现如下提示: 假设要切换到的分支为dev,应该先使用下面的命令:
git checkout origin/dev 执行完成之后会出现如下提示:
Note: checking out 'origin/dev'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again.
为什么类别不平衡是不好的 从模型的训练过程来看 从训练模型的角度来说,如果某类的样本数量很少,那么这个类别所提供的“信息”就太少。 使用经验风险(模型在训练集上的平均损失)最小化作为模型的学习准则。设损失函数为0-1 loss(这是一种典型的均等代价的损失函数),那么优化目标就等价于错误率最小化(也就是accuracy最大化)。考虑极端情况:1000个训练样本中,正类样本999个,负类样本1个。训练过程中在某次迭代结束后,模型把所有的样本都分为正类,虽然分错了这个负类,但是所带来的损失实在微不足道,accuracy已经是99.9%,于是满足停机条件或者达到最大迭代次数之后自然没必要再优化下去,ok,到此为止,训练结束! 于是这个模型没有学习到如何去判别出少数类。
从模型的预测过程来看 考虑二项Logistic回归模型。输入一个样本 x ,模型输出的是其属于正类的概率 y’ 。当 y’>0.5时,模型判定该样本属于正类,否则就是属于反类。 为什么是0.5呢?可以认为模型是出于最大后验概率决策的角度考虑的,选择了0.5意味着当模型估计的样本属于正类的后验概率要大于样本属于负类的后验概率时就将样本判为正类。但实际上,这个后验概率的估计值是否准确呢? 从几率(odds)的角度考虑:几率表达的是样本属于正类的可能性与属于负类的可能性的比值。模型对于样本的预测几率为 y’/(1-y’) 。 模型在做出决策时,当然希望能够遵循真实样本总体的正负类样本分布:设 θ 等于正类样本数除以全部样本数,那么样本的真实几率为 θ/(1−θ) 。当观测几率大于真实几率时,也就是 y’>θ 时,那么就判定这个样本属于正类。 虽然我们无法获悉真实样本总体,但之于训练集,存在这样一个假设:训练集是真实样本总体的无偏采样。正是因为这个假设,所以认为训练集的观测几率 θ/(1−θ) 就代表了真实几率 θ/(1−θ) 。 所以,在这个假设下,当一个样本的预测几率大于观测几率时,就应该将样本判断为正类。
三种解决方案 目前主要有三种办法: 1. 调整 θ值(也叫再缩放、再平衡、阈值移动、是代价敏感学习的基础) 根据训练集的正负样本比例,调整 θ 值。 这样做的依据是上面所述的对训练集的假设。但在给定任务中,这个假设是否成立,还有待讨论。 2. 过采样 对训练集里面样本数量较少的类别(少数类)进行过采样,合成新的样本来缓解类不平衡。 下面将介绍一种经典的过采样算法:SMOTE。 3. 欠采样 对训练集里面样本数量较多的类别(多数类)进行欠采样,抛弃一些样本来缓解类不平衡。 SMOTE过采样算法 SMOTE全称是Synthetic Minority Oversampling Technique即合成少数类过采样技术,它是基于随机过采样算法的一种改进方案,由于随机过采样采取简单复制样本的策略来增加少数类样本,这样容易产生模型过拟合的问题,即使得模型学习到的信息过于特别(Specific)而不够泛化(General),SMOTE算法的基本思想是对少数类样本进行分析并根据少数类样本人工合成新样本添加到数据集中,算法流程如下。
1、对于少数类中每一个样本x,以欧氏距离为标准计算它到少数类样本集中所有样本的距离,得到其k近邻。
2、根据样本不平衡比例设置一个采样比例以确定采样倍率N,对于每一个少数类样本x,从其k近邻中随机选择若干个样本,假设选择的近邻为xn。
3、对于每一个随机选出的近邻xn,分别与原样本按照如下的公式构建新的样本 xnew=x+rand(0,1)∗|x−xn| smote算法的伪代码如下: 因此,smote算法的思想是合成新的少数类样本,合成的策略是对每个少数类样本a,从它的最近邻中随机选一个样本b,然后在a、b之间的连线上随机选一点作为新合成的少数类样本。 下面具体介绍如何合成新的样本。 设训练集的一个少数类的样本数为 T ,那么SMOTE算法将为这个少数类合成 NT 个新样本。这里要求 N 必须是正整数,如果给定的 N<1 那么算法将“认为”少数类的样本数 T=NT ,并将强制 N=1 。 考虑该少数类的一个样本 ii ,其特征向量为 xi,i∈{1,…,T}: 首先从该少数类的全部 T 个样本中找到样本 xi 的 k个近邻(例如用欧氏距离),记为 xi(near),near∈{1,…,k}; 然后从这 k 个近邻中随机选择一个样本 xi(nn) ,再生成一个0 到 1 之间的随机数 ζ1 ,从而合成一个新样本 xi1 : xi1=xi+ζ1⋅(xi(nn)−xi) 3.
vi的使用
一、初识vi
1、什么是vi
vi,即终端中一款编辑器。
2、vi的应用场景
当我们要通过远程连接到服务器时,此时没有图形界面,当我们要对服务器上的文件进行编辑时,便可以使用vi进行快速地处理。其核心设计思想便是让程序员的手指始终保持在键盘的核心区域便能够完成所有的编辑操作。
3、vi的特点
vi没有图形界面,只能编辑文本内容,不支持鼠标操作,没有菜单,只有命令。
4、vi与vim
在很多Linux发行版中,直接把vi做成vim的软链接。vim(vim = vi improved)是从vi发展来的一个文本编辑器,支持代码补全、编译、错误跳转等多项功能,被称之为"编辑器之神"。
二、使用vi
通过人如下命令可以使用vi打开文件:
vi 文件名 提示:若文件已经存在,则直接打开,否则会创建一个新文件。
使用如下命令可以打开文件并将光标定位到指定行:
vi 文件名 +行数 提示:若只有"+“而不指定行号,会直接定位到文件末尾。
注:若vi异常退出,在磁盘上会保存交换文件,下次使用vi编辑该文件时,会看到如下提示信息,这时需按下字母"d"删除交换文件才能继续进行编辑。
三、vi三种工作模式
1、命令模式
使用vi打开一个文件首先进入命令模式,是使用vi的入口,通过命令对文件进行常规的编辑操作,如:定位、复制、粘贴、翻页、删除等。
2、末行模式
用于执行保存、退出等操作。要退出vi,需要在末行模式下输入命令,末行模式是vi的出口。(在命令模式下按”:"便进入末行模式,可通过相应命令执行相应的结果,按"esc"便可退回到命令模式)
末行模式命令如下:
命令英文功能wwrite保存qquit退出,若没有保存不允许退出q!quit强行退出,不保存直接退出wqwrite&quit保存并退出x保存并退出 3、编辑模式
用于正常的文字编辑。(在命令模式下按"i"便可进入编辑模式,按"esc"便可退回到命令模式)
三种模式关系如下所示:
四、vi常用命令
注:使用vi时,一定要将输入法切换至英文状态,否则无法正常使用。
1、重复命令
在命令模式下,可以在要执行的命令前加一个数字,就可以使该命令执行的结果重复指定次数。
2、移动和选择命令
①在命令模式下,可以通过"h",“j”,“k”,"l"四个按键来控制光标的移动,其四个按键的移动方位如下图所示:
②vi在行内移动
命令英文功能wword向后移动一个单词bback向前移动一个单词0行首^行首,即不是空白字符的位置$行尾 ③行数移动
命令英文功能gggo文件顶部Ggo文件末尾数字gggo移动到指定数字的行数数字Ggo移动到指定数字的行数数字移动到指定数字的行数 ④屏幕移动
命令英文功能ctrl + bback向上翻页ctrl + fforward向下翻页HHead屏幕顶部MMiddle屏幕中部LLow屏幕底部 ⑤段落移动
在vi中会使用空行来区分一个段落,使用如下命令可以在段落间移动。
命令功能{上一段}下一段 ⑥括号匹配
在我们开发中,经常会出现"()","{}","[]"括号,并且均成对出现,使用如下命令便可以方便找到当前行中与之匹配的另一个括号的位置。
命令功能%括号匹配与切换 ⑦标记
在编辑时,也许需要先查看别的位置,之后再回到当前位置继续进行编辑,只是可以在当前位置添加标记,以便在需要编辑该位置时可以快速跳转回来。
在需要的行使用m增加标记,m后加上标记名称,若其他行添加了相同名称的标记,之前添加的标记会被替换掉。
使用('标记名)便可以定位到标记所在位置。
注:若标记所在行被删除,标记也会被同时删除。
命令英文功能mxmark添加标记x,x是a-z或A-Z之间的任意一个字母'x直接定位到标记x所在位置 3、编辑命令
①选中文本
在vi中要选中文本需要使用Visual命令切换到可视模式,vi中提供了三种可视模式以便选中文本,按"esc"可以放弃选中,返回到命令模式。
命令英文功能v可视模式从光标位置开始按照正常模式选择文本V可视行模式选中光标经过的完整行ctrl + v可视块模式垂直方向选中文本 注:在可视模式可以和移动命令连用,如ggVG会选中全部内容。
今天在研究Dapper项目时,下载代码点击生成之后报错,如下图:
从图中可以看到报错的项目为Dapper.Tests.Perfomance,该项目的依赖项也报错的
在网上搜索了一下解决方案,说是更改.csproj文件中的TargetFrameworks,然后打开Dapper.Tests.Performance.csproj文件,发现TargetFrameworks的值为net462,说明当前电脑环境中没有.net Framework4.6.2的版本,所以我们要将TargetFrameworks的值改为已有版本。
如何查看当前电脑中已有的.net framework版本呢?
很简单,打开Visual Studio,新建项目,点击选择framework版本下拉框即可看到所有的已安装framework版本啦,这里我选择4.6.1的版本(TargetFrameworks的值改为net461),重新生成项目,成功~
在开发中,如果去调用别人写的方法时,是否能知道别人写的方法是否会发生异常?这是很难判断的。针对这种情况,Java总允许在方法的后面使用throws关键字对外声明该方法有可能发生异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过。
如下面代码
package www.kangxg.jdbc; public class Example { public static void main(String[] args) { // TODO Auto-generated method stub int result = divide(4,2); System.out.println(result); } public static int divide(int x,int y) throws Exception { int result = x/y; return result; } } 这时候 编译器上会有错误提示 Unhandled exception type Exception 所以需要对调用divide()方法进行try...catch处理 package www.kangxg.jdbc; public class Example { public static void main(String[] args) { try { int result = divide(4,2); System.out.println(result); } catch (Exception e) { e.
在centos7下安装了pycharm,但是每次在shell窗口输入 import viewclass.models as models 来引入模块,结果报错:
django.core.exceptions.ImproperlyConfigured: Requested setting LOGGING_CONFIG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
但是程序用python manage.py runserver 启动却正常,google里面有好多解决办法,但是都不适用。
解决办法:
在shell窗口输入 python manage.py shell
然后在输入 import viewclass.models as models 来引入。
开发环境:Android Studio
在复制了一个项目之后,修改了程序包名,修改了应用程序ID,对程序做了进一步开发之后,发现无法安装到手机上,错误代码:installation failed with message failed to finalize session:INSTALL_FAILED_INVALID_APK,具体如下图所示:
非常之头疼,原来复制项目再运行的时候是不会出现错误的(在Android Studio中复制项目并做修改,可以参考:http://blog.csdn.net/Lone1yCode/article/details/79087495)
疯狂Baidu之后发现了一个非常有效的办法,如下图所示:
如上图所示,在Android Studio上,点击File\Settings\Build,Execution,Deployment\Debugger\Instant Run,取消对勾后再尝试安装,成功!!
Instant run的作用就是加速构建、重构,第一次运行程序的时候,与正常速度一样,但是在对程序作出很多修改后,再次运行程序,Android Studio会飞速的完成构建,相比于第一次运行程序快上不少。自行Baidu,可以了解更多。
另外,我只有复制了项目之后,运行程序会出现这个错误提示,如果编辑的项目而不是复制来的,建议还是开启Instant run吧。
进来开发需要,欲于app中加入百度地图导航功能,然时间紧迫,遂以嵌入网页为先。
然在使用webView加载网页过程中,遇到了如上问题,显示ERR_UNKNOWN_URL_SCHEME
不知何故之下,学网上删去webView.setWebViewClient(new WebViewClient(){...},并加上webView.setWebChromeClient(new WebChromeClient());的确可以正确显示了,但是尝试后,发现点击链接会自动跳转手机浏览器,而不继续在这儿显示了,这显然不是我所希望的。
但是想让网页只在我的webview内跳转,而不要跑到手机浏览器去了,那么就需要用到如下代码:
webView.setWebViewClient(new WebViewClient(){ public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } }); 是的,这正是前面删掉的嘛,而且只要加了这东西,即便加上webView.setWebChromeClient(new WebChromeClient()); 也是无用,一样的报错。
难道无解了吗?不不不,上述方法既不治标也不治本,而真正治本的方法如下:
首先我们观察一下错误显示: 发现了吗,位于baidumap://xxx 的网页无法加载,明明输入的是http://xxx 为何变成了这个开头? 这是因为其自定义了scheme,类似的还有alipays://,weixin:// 等等。而webView只能识别http://或https://开头的url,因此才会报此错。 想处理也很简单,对于这种自定义scheme的url单独处理即可。 以我的baidumap://为例,修改代码如下:
webView.setWebViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { try{ if(url.startsWith("baidumap://")){ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } }catch (Exception e){ return false; } webView.loadUrl(url); return true; } }); 另外那个webView.setWebChromeClient(new WebChromeClient()); 得删去啦。 上述是只针对以baidumap:// 开头的scheme,如果当前页面显示的网站是固定的,那么也如此操作即可,而如果需要做成一个类似浏览器的形式,只需判断开头是否是http://或https:// ,如若不是,则将上面的try.
在我们的日常工作生活中一定碰到过下面的情况:
场景 1: 安装完某个软件后,看到的安装程序变成类似这样的一组字符" µç×Ó˰Îñ¾ÖÖ¤ÊéÇý¶¯¼°·þÎñƽ̨"图 1 所示的样子;
图 1. 安装程序中的乱码 场景 2:打开一个文档发现里面的内容全面是问号??????如图 2 所示;
图 2. 带有问号的乱码 场景 3:打开某个网页,却显示成:如"бЇЯАзЪСЯ"、"�????????"?等等;
场景 4:打开某个文档后,出现§ § § §。
上面例子中看到的就是困扰着我们的乱码。这篇文章基于项目实践,分别从普通用户和编程角度总结了常见的乱码种类,产生原因以及如何解决这些乱码问题。在分析乱码原因和解决办法之前,首先阐述一下和乱码相关的术语。
编码解码概述 我们都知道计算机不能直接存储字母,数字,图片,符号等,计算机能处理和工作的唯一单位是"比特位(bytes)",一个比特位通常只有 0 和 1,是(yes)和否(no),真(true)或者假(false)等等我们喜欢的称呼。利用比特位序列来代表字母,数字,图片,符号等,我们就需要一个存储规则,不同的比特序列代表不同的字符,这就是所谓的"编码"。反之,将存储在计算机中的比特位序列(或者叫二进制序列)解析显示出来成对应的字母,数字,图片和符号,称为"解码",如同密码学中的加密和解密,下面将详细解释编码解码过程中涉及到的一些术语:
字符集合(Character set):是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等,简单理解就是一个字库,与计算机以及编码无关。
字符编码集(Coded character set):是一组字符对应的编码(即数字),为字符集合中的每一个字符给予一个数字,如 Unicode 为每一个字符分配一个唯一的码点与之一一对应。
字符编码(Character Encoding):简单理解就是一个映射关系,将字符集对应的码点映射为一个个二进制序列,从而使得计算机可以存储和处理。常见的编码方式有 ASCII 编码、ISO-8859-1(不支持中文)、GBK、GB2312(中国编码,支持中文)、UTF-8 等等,详情见表 1。
字符集(Charset):包括编码字符集和字符编码,如 ASCII 字符集、ISO-8859-X、GB2312 字符集(简中)、BIG5 字符集(繁中)、GB18030 字符集、Shift-JIS 等,即下文中提到的字符集。
表 1. 常见字符集和对应编码方式 字符集编码详解ASCII
ASCII 编码ASCII字符集:主要包括控制字符(回车键、退格、换行键等);可显示字符(英文大小写字符、阿拉伯数字和西文符号。
ASCII 编码:用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符;ASCII的最大缺点是只能解决了部份西欧语言的显示问题,但对更多其他语言依然无能为力。I 字 ISO-8859-X
(常用的 ISO-8859-1)ISO-8859-1 编码
ISO-8859-2 编码
原文地址:http://blog.csdn.net/losophy/article/details/17006573 本教程提供了一个Python程序员使用protocol buffers的基本的入门教程。通过创建一个简单的示例应用程序,它向您展示了如何 *在一个.proto文件中定义Message的格式。
*使用protocol buffer compiler。
*使用Python protocol buffer API去读写Message。
这不是一个在Python中使用protocol buffers的一个全面的指南。如果想了解更详细的参考信息,请阅读 Protocol Buffer Language Guide,Python API Reference,Python Generated Code Guide和Encoding Reference。
Why Use Protocol Buffers?
我们将使用的示例是一个非常简单的“地址簿”应用程序,可以从一个文件中读写人们的联系方式。地址簿中的每个人都有一个名字,一个ID、一个电子邮件地址,和联系电话号码。
你怎样用这样方式序列化和检索结构数据?这里有一些办法可以解决这个问题:
*使用Python处理。这是默认的方法,因为这种方法是直接用到语言,但它不利于模式演变,还有,它不利于你共享数据给c++或Java写的应用。
*你可以发明一种特别的方式将数据项编码为一个字符串,如将4个int编码为“12:3:23:67”。这是一个简单的和灵活的方法,尽管它一次性需要编写编码和解析的代码,并为解析加上一个小小的运行成本。这方法最适合为非常简单的数据编码。
*用XML序列化数据。这种方法非常有吸引力,因为XML具有易读性,还有了许多库,用来支持各种语言。这是一个好选择,如果你想和其它应用/工程共享数据。但是,XML也是出了名的耗空间,还有,编码/解码会令应用程序性能产生巨大的损失。加上,操纵一个XML DOM树通常会比操纵类中的字段复杂。
Protocol buffers会灵活、高效、自动化解答来准确地解决这个问题。有了protocol buffers,你就可以编写一个.proto文件用来描述你想存储的数据结构。因此,protocol buffer编译器会创建一个类,实现自动编码和解析protocol buffer数据,通过一个高效的二进制格式。这个生成的类提供了getter和setter的字段组成一条protocol buffer,而且把读出和写入的细节当成protocol buffer的一个单元。更重要的,protocol buffer支持在日后里扩展格式这种想法,这样,代码仍然可以读取用旧的格式编码的数据。
Where to Find the Example Code
在源代码目录中,文件夹“examples”下包含所有的例程。Download it here.
Defining Your Protocol Format
为了创建你的“地址簿”应用,你会用到一个.proto文件。这是一个很简单的.proto文件定义:你可以为你想序列化的数据结构添加一条Message,然后在Message中为每个字段指定一个名称和一个类型。以下是你想为你的Message定义的.proto文件,addressbook.proto。
[plain] view plain copy
package tutorial; message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; } message AddressBook { repeated Person person = 1; } 如你所见,在语法上很像C++和Java。那就让我们看看文件中的每个部分和看看它们究竟是干什么的。
错位的连线,如下图。
设置方法:在Cadence OrCAD Capture 工具栏,依次点击'Options'-->'Preferences'-->'Grid Display',勾选红色框,点击'确定',如下图:
设置好后如下图: