WebFlux和Spring Data Reactive的完整demo

文章目录 配置ReactiveRedisTemplate配置ReactiveMongoTemplate、ReactiveMongoRepositoryWebFlux处理流实例 本实例演示了:在处理一个REST请求的过程中,web服务器依次发起读redis、查mongodb、写redis这些网络IO请求,这些IO请求的执行过程全部遵从NIO模式,即发出IO请求的线程不进行阻塞而是直接释放,等到数据源返回结果后,新分配一个reactive线程来处理结果数据。 依赖的spring版本为:spring-webflux(5.1.2)、spring-data-redis(2.1.2)、spring-data-mongodb(2.1.2);使用的是非springboot项目也支持的配置方式。 配置ReactiveRedisTemplate 1、先定义连接池配置 package wzp.redis.factory; import java.time.Duration; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.FactoryBean; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; public class LettuceClientConfigurationFactory implements FactoryBean<LettuceClientConfiguration> { @Override public LettuceClientConfiguration getObject() throws Exception { GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxTotal(200); poolConfig.setMaxWaitMillis(2000); poolConfig.setTestOnBorrow(true); LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig).commandTimeout(Duration.ofMillis(3000)).shutdownTimeout(Duration.ZERO).build(); return lettuceClientConfiguration; } @Override public Class<?> getObjectType() { return LettuceClientConfiguration.class; } } 2、再配置ReactiveRedisTemplate <bean id="redisStandaloneConfiguration" class="org.springframework.data.redis.connection.RedisStandaloneConfiguration"> <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <property name="

Gradle加速编译

调整gradle配置 开启daemon 相比没有开启daemon,开启daemon有如下好处 不需要每次启动gradle进程(JVM实例),减少了初始化相关的工作 daemon可以缓存项目结构,文件,task等,尽可能复用之前的编译成果,缩短编译过程 开启daemon很简单,以Mac为例,在家目录下的.gradle/gradle.properties文件(如没有,可需要新建文件),加上如下的代码即可。 org.gradle.daemon=true 或者传递gradle参数 ./gradlew task --daemon 为了确保gradle配置生效,建议使用gradle —stop停止已有的daemon。 ./gradlew --stop 再次执行gradle任务就可以应用daemon了,留意的话,可以看到类似这样的日志输出。 Starting a Gradle Daemon (subsequent builds will be faster) 设置heap大小 为Gradle分配足够大的内存,则可以同样加速编译。如下修改文件gradle.properties org.gradle.jvmargs=-Xmx5120m -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 由于Flipboard依赖繁多,且文件也多,并结合自身设备8G内存,这里为Gradle分配最大5G。效果目前看起来不错,大家可以根据自己的情况不断调整得到一个最优的值。 开启offline 开启offline之后,可以强制Gradle使用本地缓存的依赖,避免了网络读写操作,即使是需要从网络进行检查这些依赖。 ./gradlew --offline taskName 如上使用时,加上—offline参数即可。 注意,如果是某个依赖在本地不存在,则会编译出错,解决方法,只需要暂时关闭offline,等依赖下载到本地后,在后续的执行中加入offline即可。 设置并行构建 现在的工程往往使用了很多模块,默认情况下Gradle处理多模块时,往往是挨个按顺序处理。可以想象,这种编译起来会有多慢。好在Gradle提供了并行构建的功能,可以让我们充分利用机器的性能,减少编译构建的时间。 修改gradle.properties文件 org.gradle.parallel=true 或向gradle传递参数 ./gradlew task --parallel 当我们配置完成,再次执行gradle task,会得到类似这样的信息,信息标明了开启Parallel以及每个task使用的线程信息。 ./gradlew clean --info Parallel execution is an incubating feature. ....... :libs:x:clean (Thread[Task worker Thread 3,5,main]) completed. Took 0.005 secs. :libs:xx:clean (Thread[Daemon worker Thread 3,5,main]) started.

springboot或springCloud maven 打包分离依赖jar包及配置文件

使用springCloud的过程中,发布到生产环境的网速受限,如果每次将60,70M甚至更大的jar包上传,速度太慢了,采取jar包和配置文件分离的方式可以极大的压缩jar包大小,至于依赖的jar包则只需要上传一次,后期增加了jar包则将jar包加入到jar包文件夹内就可以了。配置文件也是一样,每次修改了才需要修改服务器文件,如果只是单纯的代码更新,我们直接打包上传源码jar包就可以了。直接上maven pom.xml build配置。 <build> <resources> <!-- Resource Filter --> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <!--指定资源的位置--> <resource> <directory>src/main/resources</directory> </resource> <!--无法分离的jar包如果jar包不大可以选择直接打入源码jar包--> <!--<resource> &lt;!&ndash;jar包路径&ndash;&gt; <directory>${project.basedir}/libs</directory> <targetPath>BOOT-INF/lib/</targetPath> <includes> <include>**/*.jar</include> </includes> </resource>--> </resources> <plugins> <!--打包jar--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <!--不打包资源文件--> <excludes> <exclude>*.**</exclude> </excludes> <archive> <manifest> <addClasspath>true</addClasspath> <!--MANIFEST.MF 中 Class-Path 加入前缀--> <classpathPrefix>lib/</classpathPrefix> <!--jar包不包含唯一版本标识--> <useUniqueVersions>false</useUniqueVersions> <!--指定入口类--> <mainClass>com.seawater.mybatisPlus.MybatisPlusApplication.java</mainClass> </manifest> <manifestEntries> <!--MANIFEST.MF 中 Class-Path 加入资源文件目录--> <!--本地依赖包需要手动 加入Class-Path ,否则无法找到--> <Class-Path>./resources/</Class-Path> </manifestEntries> </archive> <outputDirectory>${project.build.directory}</outputDirectory> </configuration> </plugin> <!--拷贝依赖 copy-dependencies--> <plugin> <groupId>org.

Hive throws: WstxParsingException: Illegal character entity: expansion character (code 0x8)

错误在第3202行 打开hive-site.xml位于第3202行, vim hive-site.xml +3202 发现是一个解释性质的说明文档,里面包含的特殊字符 for&#8; <description> Ensures commands with OVERWRITE (such as INSERT OVERWRITE) acquire Exclusive locks for&#8;transactional tables. This ensures that inserts (w/o overwrite) running concurrently are not hidden by the INSERT OVERWRITE. </description> 它抛出的错误,因为有词之间的特殊字符的和事务。要么删除字符或复制和粘贴(替换), 这是在两者之间<description>和</description>。 直接将for&#8;修改为for;

名企6年Java程序员的工作总结,写给在迷茫中的你!

很多年前,刚刚从大学毕业的时候,很多公司来校招。其中最烂俗的一个面试问题是:“你希望你之后三到五年的发展是什么?”。我当时的标准回答是(原话):“成为在某一方面能够独当一面的技术专家“。后来经历了几家不同的公司,换了不同的方向,才知道这个真是一个很难的问题。因为兵无常势,什么东西都是在不断的变化,一早的时候看好的东西可能会被淘汰。 (几乎)没有人能够看准技术的下一个方向,因为这个问题实在是太难了,能够做到这一点的你就成为了技术界的巴菲特了。比如说11年加入Google,14年加入Facebook,16年加入阿里巴巴。做到这一点的人肯定有资本也有眼光去做风险投资,就算不做风险投资那么财务自由也是妥妥的。 现在毕业六年,从北京到上海到硅谷,从国内互联网公司外企,看到了公司好的地方和坏的地方,这里只是根据自己的经历写一些大方向选择建议,仅供参考。 名企6年Java程序员的工作总结,写给在迷茫中的你! 一、行业背景很重要 行业背景非常重要;工作3年后必须确定自己的行业背景,比如一直从事电信行业,一直从事银行项目,一直从事ERP行业等等。 一个程序员不可能是一直写代码的,就是写代码也要知道业务逻辑,满足什么需求;俗话说隔行如隔山,每个行业的业务都不一样,甚至差别很大,比如你一直从事流媒体的研究,让你跳槽到一家银行项目,完了,一切从头学吧,以前的行业经验都用不上了;而且,一个公司公司招人,就是希望找到那些很容易上手,不需要培训业务很久的程序员;频繁跳槽的朋友,一定要注意这点; 一直在一个行业呆久了,就可以成为这个行业的专家;我们可以经常看到,一个项目组的某个leader,代码写的一般,但是却可以跟客户流畅的沟通,控制着新需求的提出,bug的修正等等;而客户也很愿意跟他打交道,因为那些老的项目只有他能维护,他甚至熟悉系统的每一张表结构——-可想在这个行业呆的时间有多久啦。 第二、合理的职业规划 什么是职业规划—-就是你短期或者长期的一个职业计划!大道理不讲,咱简单点。先问你几个问题: 你工作几年了,你愿意一直和新入行的新手一样就是个简单的程序员吗? 你愿意一直写代码,而不关心其他吗? 一个项目的前期需求,设计,后期部署维护,领导找到你,你说咱搞不定,行吗? 程序员不是敲代码的机器。第一年太多东西不懂,你可以一切听从老大的安排,敲敲代码,看看数据库,测试自己和别人的代码;但是第二年,你还是这样吗?不可能的,一年的经验你完全可以入行了,是时候该学习怎么进行需求分析,怎么设计数据库,怎么写各类文档,怎么写更好的代码?这是高级程序员的要求! 三、什么是高级程序员? 具有分析设计能力,能进行技术攻关,而且具有某行业深厚背景的程序员! 所有,一个项目立项后,你要积极的参与到前期设计中,跟老同志们一道思考分析问题,学习经验!OK,你这就成长啦! 千万不要认为程序员就是写代码的哦!!! 而且,通过一个项目的开发,你要能粗略的统计出一个功能的开发时间;比如一个模块有20个小功能点,你开发了80个小时,每个小功能点平均2小时——这时在前期就能评估工作量啦。当然每个人的效率和工作质量是不同的,因人而异,但是大概的工作量应该是可以统计出来的,用于统计一个项目的工作周期; 四、不要觉得业务代码一样很牛逼 有人认为写业务代码一样可以很牛逼,理由是业务代码一样可以有各种技巧,例如可以使用封装和抽象使得业务代码更具可扩展性,可以通过和产品多交流以便更好的理解和实现业务,日志记录好了问题定位效率可以提升10倍等等。 业务代码一样有技术含量,这点是肯定的,业务代码中的技术是每个程序员的基础,但只是掌握了这些技巧,并不能成为技术大牛,就像游戏中升级打怪一样,开始打小怪,经验值很高,越到后面经验值越少,打小怪已经不能提升经验值了,这个时候就需要打一些更高级的怪,刷一些有挑战的副本了,没看到哪个游戏只要一直打小怪就能升到顶级的。成为技术大牛的路也是类似的,你要不断的提升自己的水平,然后面临更大的挑战,通过应对这些挑战从而使自己水平更上一级,然后如此往复,最终达到技术大牛甚至业界大牛的境界,写业务代码只是这个打怪升级路上的一个挑战而已,而且我认为是比较初级的一个挑战。 所以我认为:业务代码都写不好的程序员肯定无法成为技术大牛,但只把业务代码写好的程序员也还不能成为技术大牛。 五、别以上班太忙没时间学习为借口 很多人认为自己没有成为技术大牛并不是自己不聪明,也不是自己不努力,而是中国的这个环境下,技术人员加班都太多了,导致自己没有额外的时间进行学习。 这个理由有一定的客观性,毕竟和欧美相比,我们的加班确实要多一些,但这个因素只是一个需要克服的问题,并不是不可逾越的鸿沟,毕竟我们身边还是有那么多的大牛也是在中国这个环境成长起来的。 我认为有几个误区导致了这种看法的形成: 上班做的都是重复工作,要想提升必须自己额外去学习 形成这个误区的主要原因还是在于认为“写业务代码是没有技术含量的”,而我现在上班就是写业务代码,所以我在工作中不能提升。 学习需要大段的连续时 很多人以为要学习就要像学校上课一样,给你一整天时间来上课才算学习,而我们平时加班又比较多,周末累的只想睡懒觉,或者只想去看看电影打打游戏来放松,所以就没有时间学习了。 实际上的做法正好相反:首先我们应该在工作中学习和提升,因为学以致用或者有实例参考,学习的效果是最好的;其次工作后学习不需要大段时间,而是要挤出时间,利用时间碎片来学习。 据不完全统计,截至目前(2017.07)为止,中国Java程序员的数量已经超过了100万。而且,随着IT培训业的持续发展和大量的应届毕业生进入社会,Java程序员面临的竞争压力越来越大。那么,作为一名Java程序员,怎样努力才能快速成长为一名高级的程序员或者架构师,或者说一名优秀的高级工程师或架构师应该有怎样的技术知识体系,这不仅是一个刚刚踏入职场的初级程序员,也是工作三五年之后开始迷茫的老程序员,都必须要面对和想明白的问题。 我总结出一个Java程序员的工作2-5年成长路线图 一、阅读源码 深入的Java学习,经典源码阅读不可少: 名企6年Java程序员的工作总结,写给在迷茫中的你! 二、分布式架构 随着业务越来越复杂,数据量越来越大,并发量越来越大,单体的架构模式显然再也无法对应,作为Java后端架构师,高并发+高可用+海量数据的分布式架构体系,是必不可少的: 名企6年Java程序员的工作总结,写给在迷茫中的你! 三、微服务技术体系 服务分层,微服务架构是架构升级的必由之路,Java技术体系,和微服务相关的技术有哪需要深入学习呢? 名企6年Java程序员的工作总结,写给在迷茫中的你! 四、性能优化 作为后端Java技术专家,解决性能问题才真正体现一个架构师的功力。只有深入学习JVM底层原理,Mysql底层优化以及Tomcat调优,做到知其然,知其所以然: 名企6年Java程序员的工作总结,写给在迷茫中的你!

在ArcGIS中选择要素时,因两个不同图层之间的要素有叠加,鼠标点击时同时选择多个要素怎么办?

如下图,若我只想选中绿色的面要素,但因和蓝色面要素所在的图层之间有套合叠加,导致鼠标点击绿色面要素时,外面的蓝色要素也一起被选中了,如何分开选择呢? 理论上很简单,我们只要将另一个图层设置为不可选中状态就可以了,那么ArcGIS可以执行这个操作吗?在【内容列表】中,切换到“按选择列出”模式,在蓝色面要素所在的图层后面单击“单击切换是否可选”按钮。详细理论请查看https://blog.csdn.net/qq_18461229/article/details/78034983

jmx基本知识

回顾下jmx知识吧~ package com.test; ackage com.ilucky.test.jvm.jmx.one; import java.io.IOException; import java.lang.management.ClassLoadingMXBean; import java.lang.management.CompilationMXBean; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryManagerMXBean; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryUsage; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; import java.lang.management.ThreadMXBean; import java.util.Arrays; import java.util.List; import java.util.Map.Entry; import javax.management.MBeanServerConnection; import javax.management.ObjectName; /** * ManagementFactory基本使用 * * @author IluckySi * */ public class MBeanDemo { public static void main(String[] args) { visitMBean(); showSystem(); showJvmInfo(); showMemoryInfo(); showClassLoading(); showCompilation(); showThread(); showGarbageCollector(); showMemoryManager(); showMemoryPool(); } /** 访问 MXBean有三种方法 */ public static void visitMBean() { System.

[转]伪代码的写法

伪代码的写法(附:12种排序算法详解) 转自:http://blog.sina.com.cn/s/blog_134451adb0102wfgu.html 伪代码(Pseudocode)是一种算法描述语言。使用伪代码的目的是为了使被描述的算法可以容易地以任何一种编程语言(Pascal,C,Java,etc)实现。因此,伪代码必须结构清晰、代码简单、可读性好,并且类似自然语言。 介于自然语言与编程语言之间。 它以编程语言的书写形式指明算法的职能。相比于程序语言(例如Java, C++,C, Dephi 等等)它更类似自然语言。它是半角式化、不标准的语言。我们可以将整个算法运行过程的结构用接近自然语言的形式(这里,你可以使用任何一种你熟悉的文字,中文,英文 等等,关键是你把你程序的意思表达出来)描述出来. 使用伪代码, 可以帮助我们更好的表述算法, 不用拘泥于具体的实现. 人们在用不同的编程语言实现同一个算法时意识到,他们的实现(注意:这里是实现,不是功能)很不同。尤其是对于那些熟练于不同编程语言的程序员要理解一个(用其他编程语言编写的程序的)功能时可能很难,因为程序语言的形式限制了程序员对程序关键部分的理解。这样伪代码就应运而生了。 当考虑算法功能(而不是其语言实现)时,伪代码常常得到应用。计算机科学在教学中通常使用虚拟码,以使得所有的程序员都能理解。 综上,简单的说,让人便于理解的代码。不依赖于语言的,用来表示程序执行过程,而不一定能编译运行的代码。在数据结构讲算法的时候用的很多。 语法规则 例如,类Pascal语言的伪代码的语法规则是: 在伪代码中,每一条指令占一行(else if,例外)。指令后不跟任何符号(Pascal和C中语句要以分号结尾)。书写上的“缩进”表示程序中的分支程序结构。这种缩进风格也适用于if-then-else语句。用缩进取代传统Pascal中的begin和end语句来表示程序的块结构可以大大提高代码的清晰性;同一模块的语句有相同的缩进量,次一级模块的语句相对与其父级模块的语句缩进。 算法的伪代码语言在某些方面可能显得不太正规,但是给我们描述算法提供了很多方便,并且可以使我们忽略算法实现中很多麻烦的细节。通常每个算法开始时都要描述它的输入和输出,而且算法中的每一行都给编上号码,在解释算法的过程中会经常使用算法步骤中的行号来指代算法的步骤。算法的伪代码描述形式上并不是非常严格,其主要特性和通常的规定如下: 1) 算法中出现的数组、变量可以是以下类型:整数、实数、字符、位串或指针。通常这些类型可以从算法的上下文来看是清楚的,并不需要额外加以说明。 2) 在算法中的某些指令或子任务可以用文字来叙述,例如,"设x是A中的最大项",这里A是一个数组;或者"将x插入L中",这里L是一个链表。这样做的目的是为了避免因那些与主要问题无关的细节使算法本身杂乱无章。 3) 算术表达式可以使用通常的算术运算符(+,-,*,/,以及表示幂的^)。逻辑表达式可以使用关系运算符=,≠,<,>,≤和≥,以及逻辑运算符与(and),或(or),非(not)。 4) 赋值语句是如下形式的语句:a<-b 。 这里a是变量、数组项,b是算术表达式、逻辑表达式或指针表达式。语句的含义是将b的值赋给a。 5) 若a和b都是变量、数组项,那么记号a<->b 表示a和b的内容进行交换。 6) goto语句具有形式 goto label(goto标号)它将导致转向具有指定标号的语句。 7) 条件语句有以下两种形式: if c then s或者 if c then s else s′ 这里c是逻辑表达式,s和s′是单一的语句或者是被括在do和end之间的语句串。对于上述两种形式,假若c为真,则s被执行一次。假若c为假,则在第一种形式中,if语句的执行就完成了,而在第二种形式中,执行s′。在所有的情况下,控制就进行到了下一个语句,除非在s或s′中的goto语句使控制转向到其它地方。 8) 有两种循环指令:while和for。 while语句的形式是 while c do s end 这里c是逻辑表达式,而s是由一个或更多个语句组成的语句串。当c为真时,执行s。在每一次执行s之前,c都被检查一下;假若c为假,控制就进行到紧跟在while语句后面的语句。注意,当控制第一次达到while语句时,假若c为假,则s一次也不执行。 for语句的形式是 for var init to limit by incr do s

从输入URL到显示页面的过程中发生了什么?

概览 关于这个问题,我看过很多文章,每个人分析的方法与总结的步骤都不相同。我这里按照自己的理解把过程分为了十个部分。因为我主要学习后端,所以最后几步前端的内容略写了。 一、URL解析 二、DNS域名解析 三、建立TCP连接 四、发送HTTP请求 五、访问重定向301/302(非必须) 六、服务器处理请求 七、返回响应结果 八、断开TCP连接 九、浏览器解析HTML 十、浏览器渲染界面 一、URL 解析 什么是URL? URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址。 比如 http://www.w3school.com.cn/html/index.asp,遵守以下的语法规则: scheme://host.domain:port/path/filename 各部分解释如下: scheme - 定义因特网服务的类型。常见的协议有http、https、ftp、file,其中最常见的类型是 http,而https则是进行加密的网络传输。host - 定义域主机(http 的默认主机是 www)domain - 定义因特网域名,比如 w3school.com.cnport - 定义主机上的端口号(http 的默认端口号是 80)path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。filename - 定义文档/资源的名称 扩展:HTTPS协议 我不知道把HTTPS放在这个部分是否合适,但是放在这里好像又说的过去。HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文。但是这个过程中存在一定的风险,HTTP报文是明文,如果中间被截取的话会存在一些信息泄露的风险。那么在进入TCP报文之前对HTTP做一次加密就可以解决这个问题了。HTTPS协议的本质就是HTTP + SSL(or TLS)。在HTTP报文进入TCP报文之前,先使用SSL对HTTP报文进行加密。从网络的层级结构看它位于HTTP协议与TCP协议之间。 关于HTTPS详细请看我另一篇博文:https://blog.csdn.net/CrankZ/article/details/81235216 扩展:什么是URL、URI、URN? URI(Uniform Resource Identifier)统一资源标识符URL(Uniform Resource Locator)统一资源定位符URN(Uniform Resource Name)统一资源名称 URL和URN 都属于 URI 二、DNS域名解析 DNS是什么 维基百科定义:域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。 因为,我们更习惯于记住一个网站的已经,比如www.baidu.com,而不是记住它的IP地址。但是计算机最终访问的IP地址,而不是像www.baidu.com等链接。 所以DNS的作用就是你给DNS一个域名,它能帮你找到相应的IP地址。域名->DNS->IP地址 DNS缓存解析流程 浏览器缓存系统缓存路由器缓存ISP DNS缓存递归查询 2.1浏览器缓存 浏览器会缓存DNS记录一段时间。 有趣的是,操作系统没有告诉浏览器储存DNS记录的时间,这样不同浏览器会储存个自固定的一个时间(2分钟到30分钟不等)。所以这时候浏览器就会检查域名是否在缓存当中。

ModbusTCP协议学习笔记

这篇在简书发过一次,增加了一点内容,尝试一下用CSDN 1 简介 modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的modbus协议:modbusTCP。 Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。 标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。 2 ModbusTCP数据帧 ModbusTCP的数据帧可分为两部分:MBAP+PDU。 2.1 报文头MBAP MBAP为报文头,长度为7字节,组成如下: 事务处理标识协议标识长度单元标识符2字节2字节2字节1字节 事务处理标识 :可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。 协议标识符 :00 00表示ModbusTCP协议。 长度 :表示接下来的数据长度,单位为字节。 单元标识符 :可以理解为设备地址。 2.2 帧结构PDU PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。 2.2.1 功能码 modbus的操作对象有四种:线圈、离散输入、输入寄存器、保持寄存器。 线圈:PLC的输出位,开关量,在MODBUS中可读可写离散量:PLC的输入位,开关量,在MODBUS中只读输入寄存器:PLC中只能从模拟量输入端改变的寄存器,在MODBUS中只读保持寄存器:PLC中用于输出模拟量信号的寄存器,在MODBUS中可读可写 根据对象的不同,modbus的功能码有: 0x01:读线圈0x05:写单个线圈0x0F:写多个线圈0x02:读离散量输入0x04:读输入寄存器0x03:读保持寄存器0x06:写单个保持寄存器0x10:写多个保持寄存器 2.2.2 PDU详细结构 0x01:读线圈 在从站中读1~2000个连续线圈状态,ON=1,OFF=0 请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)响应:MBAP 功能码 数据长度 数据(一个地址的数据为1位)如:在从站0x01中,读取开始地址为0x0002的线圈数据,读0x0008位 00 01 00 00 00 06 01 01 00 02 00 08回:数据长度为0x01个字节,数据为0x01,第一个线圈为ON,其余为OFF 00 01 00 00 00 04 01 01 01 01 0x05:写单个线圈 将从站中的一个输出写成ON或OFF,0xFF00请求输出为ON,0x000请求输出为OFF 请求:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)响应:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)如:将地址为0x0003的线圈设为ON

华为servicecomb快速上手(一)

Servicecomb介绍 ServiceComb 作为 Apache 开源组织下的一款微服务框架,其前身为华为云的 微服务引擎 CSE (Cloud Service Engine) 云服务。它意味着国内一款微服务框架在华为和 Apache 组织的共同努力下,随着微服务市场的火爆,一定会让越来越多的开发者所喜欢。(转) 官方网站介绍 华为将 ServiceComb 交给Apache 基金组织维护 下面是官网地址: 英文:http://servicecomb.incubator.apache.org/ 中文:http://servicecomb.incubator.apache.org/cn/ ServiceComb 的开放性设计思想(转) 编程模型和通信模型分离,不同的编程模型可以灵活组合不同的通信模型。应用开发者在开发阶段只关注接口开发,部署阶段灵活切换通信方式;支持 legacy 系统的切换,legacy 系统只需要修改服务发布的配置文件(或者 annotation),而不需要修改代码。现阶段支持 SpringMVC、JAX-RS 和透明 RPC 三种开发方式。内建 API-first 支持。通过契约规范化微服务开发,实现跨语言的通信,并支持配套的软件工具链(契约生成代码、代码生成契约等)开发,构建完整的开发生态。定义了常用的微服务运行模型,将微服务从发现到交互过程中的各种容错手段都封装起来。该运行模型支持自定义和扩展。ServiceComb 微服务解决方案 转自官方介绍 入门demo 官网下载service-center,并启动。项目脚手架快速搭建 http://start.servicecomb.io/provider项目 microservice.yaml和service APPLICATION_ID: start.servicecomb.io service_description: name: HelloServiceComb version: 0.0.1 properties: allowCrossApp: true servicecomb: handler: chain: Provider: {} highway: address: 0.0.0.0:9090 service: registry: address: http://127.0.0.1:30100 autodiscovery: false @RpcSchema(schemaId = "sayHello") public class RpcProvider implements RpcService { @Override public String helloServicecomb() { return "

获取ACCESS_TOKEN接口

1. 获取access_token access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。 access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。 https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET 详细参考: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183 转载于:https://www.cnblogs.com/szsq/p/9987221.html

Altium Designer 设置多层方法及各层介绍

序言:因为PCB板子的层分类有很多,所以通过帮助大家能更好地理解PCB的结构,所以把我所知道的跟大家分享一下 1.PCB各层简介 1. Top Layer顶层布线层(顶层的走线) 2. Bottom Layer底层布线层(底层的走线) 3. Mechanical 1机械层1(机械层有多种,作用不一) 上图:粉色的机械层用于禁止走线,绿色的机械层表示器件大小 5. Top Overlay顶层丝印层(丝印层可以印制信息,文字,甚至图片。不会对板子造成影响,只是辅助使用) 6. Bottom Overlay底层丝印层(同5) 7. Bottom Paste底层焊盘层(焊盘就是上锡的地方啦) 8. Top Solder顶层阻焊层域 用于限制加锡的范围 9. Bottom Solder底层阻焊层 10. Drill Gudie过孔引导层 11. KeepOutLayer禁止布线层(可以用来绘制PCB板的外框尺寸) 12. MultiLayer多层 2.多层板的设置 (此处以AD14为例) PCB页面——>设计——>层叠管理 打开以后 点开预设可以设置层数(如下图),也可以点击上图左下角的Add Layer自定义添加层 其中四层板也是十分常见的,上图的四层板可以看到它是两层信号层single,以及两层电源层(Plane) 四层板相比两层板,主要是多了电源层和底层以及新增两层与布线层之间的阻隔层。

Soundex编码(Soundex)

题目描述: Soundex编码方法根据单词的拼写将单词进行分组,使得同一组的单词发音很接近。例如,“can"与"khawn”,"con"与"gone"在Soundex编码下是相同的。 Soundex编码方法将每个单词转换成一串数字,每个数字代表一个字母。规则如下: 1代表B,F,P或V; 2代表C,G,J,K,Q,S,X或Z; 3代表D或T; 4代表L; 5代表M或N; 6代表R。 而字母A,E,I,O,U,H,W和Y不用任何数字编码,并且相邻的、具有相同编码值的字母只用一个对应的数字代表。具有相同Soundex编码值的单词被认为是相同的单词。 输入描述: 输入文件中的每行为一个单词,单词中的字母都是大写,每个单词长度不超过20个字母。 输出描述: 对输入文件中的每个单词,输出一行,为该单词的Soundex编码 样例输入: KHAWN PFISTER BOBBY 样例输出: 25 1236 11 代码 #include<iostream> #include <stdio.h> using namespace std; int main() { char ch[21]; int i,j,s[21],k; while(gets(ch)!=NULL){ i=0;j=0; while(ch[i]!='\0'){ switch (ch[i]){ case 'B':case 'F':case 'P':case 'V':{ s[j]=1; j++; break; } case 'C':case 'G':case 'J':case 'K':case 'Q': case 'S':case 'X':case 'Z':{ s[j]=2; j++; break; } case 'D':case 'T':{ s[j]=3; j++; break; } case 'L':{ s[j]=4; j++; break; } case 'M':case 'N':{ s[j]=5; j++; break; } case 'R':{ s[j]=6; j++; break; } case 'A':case 'E':case 'I':case 'O': case 'U':case 'W':case 'Y':{ s[j]=0; j++; break; } } i++; //cout<<s[j-1]; } k=0; for(j=0;j<i;j++){ if(s[j]==0){ k=s[j]; } else{ if(s[j]!

cuda安装教程+cudnn安装教程

cuda9.0+cudnn7.0安装教程 1、下载cuda9.0 下载链接:https://developer.nvidia.com/cuda-toolkit-archive 2、安装cuda 安装cuda时,第一次会让设置临时解压目录,第二次会让设置安装目录; 临时解压路径,建议默认即可,也可以自定义。安装结束后,临时解压文件夹会自动删除; 安装目录,建议默认即可; 注意:临时解压目录千万不要和cuda的安装路径设置成一样的,否则安装结束,会找不到安装目录的!!! 选择自定义安装 安装完成后,配置cuda的环境变量; 命令行中,测试是否安装成功; 步骤如下(部分过程图): 安装完成,先查看系统变量,然后添加cuda的系统变量: 查看: 添加系统变量后如下图所示: 测试: win+R nvcc -V nvcc --version 显示cuda版本号9.0 V9.0.176 说明安装成功! 3、cudnn下载 官网下载:https://developer.nvidia.com/rdp/cudnn-archive 4、cudnn安装 解压文件夹,将解压后的文件夹下的文件拷贝到cuda安装目录下,与之相对应的文件夹下。 完成! 5、参考链接: https://blog.csdn.net/u010618587/article/details/82940528 https://blog.csdn.net/weixin_39290638/article/details/80045236 https://blog.csdn.net/asd136912/article/details/79383161 https://blog.csdn.net/Eppley/article/details/79297503

Google Kickstart round H 2018

网址 第一次kickstart体验很迷,感觉题目比想象的简单了ORZ,但是还是发现了自己的很多不足,继续加油吧 A 暴力 写了trie树,用总方案数遍历减去所有不可行方案数即可,不写trie树应该也能过。 #include<iostream> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<set> #include<math.h> #include<queue> #include<map> #include<stack> #include<deque> #define go(i,a,b) for (int (i)=(a);(i)<=(b);(i)++) #define ll long long #define MOD 1000000007 #define N 10005 #include<fstream> using namespace std; ll pow2[55],ans; char s[500]; int cnt; void init(){ pow2[0]=1; for (int i=1;i<=50;i++){ pow2[i]=pow2[i-1]*2; //cout<<pow2[i]<<endl; } return; } struct node{ int t0,t1; bool istail; }t[20005]; void trie(){ int root=0; int len=strlen(s); for (int i=0;i<len;i++){ if (t[root].

LIS(最长上升子序列)nlogn求法

思想:贪心+二分 新建一个low数组,low[i]表示长度为i的LIS结尾元素的最小值。对于一个上升子序列,显然其结尾元素越小,越有利于在后面接其他的元素,也就越可能变得更长。因此,我们只需要维护low数组,对于每一个a[i],如果a[i] > low[当前最长的LIS长度],就把a[i]接到当前最长的LIS后面,即low[++当前最长的LIS长度]=a[i]。 那么,怎么维护low数组呢? 对于每一个a[i],如果a[i]能接到LIS后面,就接上去;否则,就用a[i]取更新low数组。具体方法是,在low数组中找到第一个大于等于a[i]的元素low[j],用a[i]去更新low[j]。如果从头到尾扫一遍low数组的话,时间复杂度仍是O(n^2)。我们注意到low数组内部一定是单调不降的,所有我们可以二分low数组,找出第一个大于等于a[i]的元素。二分一次low数组的时间复杂度的O(lgn),所以总的时间复杂度是O(nlogn)。 下面上LIS模板: #include<cstdio> #include <iostream> #include<cstring> #include<algorithm> #define MAXN 100005 using namespace std; int arr[MAXN],ans[MAXN],len; int main(){ int p = 0; while(~scanf("%d",&arr[++p])); p--; memset(ans,0,sizeof ans); ans[1] = arr[1]; len=1; for(int i=2; i<=p; ++i){ if(arr[i] > ans[len]) ans[++len]=arr[i];//如果大于末尾的数, 直接放在末尾,长度+1 else{ int pos=lower_bound(ans+1,ans+len+1,arr[i])-ans; //如果比末尾的数小,则找到数组中第一个比arr[i]大或相等的位置,并将该位置的值覆盖为arr[i] ans[pos] = arr[i]; } } printf("%d\n",len); return 0; } 这里有lower_bound()和upper_bound()的用法:lower_bound VS upper_bound(用法详解) 下面看一道例题,更深的理解下LIS思想 导弹拦截 题意很明确,求出所给序列的最大不上升子序列和最大上升子序列, 什么是最大不上升子序列呢? 举个栗子:90 103 99 83 102 70 86 70 99 71

Unity-Get/Set属性访问器详解

Unity-Get/Set属性访问器详解 目录 1.博文介绍 2.get/set理解 3.具体用法 4.推送 5.结语 1.博文介绍 本片博客主要介绍关于属性访问器get/set的一些知识,对get/set的概念还比较模糊的同学可以看一看本篇博客。 2.get/set理解 通常的来说在Unity内我们声明一些属性如下所示 private float num; public int index; 但是对于一些小伙伴们来说偶尔可能会看到如下的一些属性声明方式 public float Num { get { return Num; } set { Num= value; } } 那这个时候你可能就会有疑问了,这个get/set是什么鬼,为什么要这样写,他是干什么的。 不要紧,我们一点点来解释。 首先这个get我们可以理解为 “读”,如果你为一个属性声明了get方法,那么每当你调用该属性的时候,就会调用get内的方法,这里我们可以看到 get{ return Num;},引用该属性后就会调用该属性的get方法,在该属性的get方法内返回了该属性本身,所以我们就拿到了这个属性的值。 然后是这个set,我们可以理解为 “写”,如果你为一个属性声明了set方法,那么每当你设置该属性的值的时候,就会调用set内的方法,这个我们可以看到 set { Num = value;},这个value就是你在外部为该属性设置的值,比如:你在某个脚本里设置 Num 的值,Num = 1.1f ;那么设置的时候就会调用set方法,这个时候value就等于1.1f。 正常我们声明变量,有两种方式,就是private和public,其实这俩也是有get/set的,只不过隐藏了,他们都是可读可取的属性,现在我们知道get/set的用法之后,就可以把一个属性设置为只读,或者是只写的属性,又或者是可读可写的属性。 private float num//只读属性,只能读取该属性的值 { get { return num; } } private float num//只写属性,只能给该属性设置值 { set { num = value; } } private float num//可读可写的属性 { get { return num; } set { num = value; } } 3.

Java常见细节问题

1、变量:变量类型,变量名,变量值。 2、变量命名: (1)如果是多个单词组成,那么第一个单词首字母小写,其后单词的首字母大写。myName。 (2)变量命名时,尽量简短且能清楚的表达变量的作用,做到见名知意。学生姓名:stuName。 3、数据类型 (1)基本数据类型就是存储数据本身,(直接放抽屉里的东西)而引用类型变量就是保存数据的空间地址(存储这个抽屉里的钥匙,钥匙和抽屉一一对应)。 引用数据类型:类(class),接口(interface),数组,String(用来表示字符串)。 (2)浮点数默认为double,flaot变量赋值时应该在数值后面添加f。 float height=12.5f; (3)main中定义的变量必须先定义再输出。 4、类型装换 自动转换条件 (1)可兼容,比如double兼容int型,char型不可兼容int型。 (2)目标类型大于原类型,如double类型长度为8字节,int类型字节为4,因此double变量力可以 直接存放int型,反之不可 强制类型转换 double avg1=75.6; int avg2=(int)avg1; 所以此时avg1为75.6,avg2为75。 5、常量关键字:final 6、逻辑运算符: 如果(one>two)&&(one<three),如果左面是错的,那么系统则认为没有必要进行右边的操作。 同样(one>two)||(one<three),如果左面是对的,那么系统则认为没有必要进行右边的操作了。 7、switch语句 语法: 执行过程: 当 switch 后表达式的值和 case 语句后的值相同时,从该位置开始向下执行,直到遇到 break 语句或者 switch 语句块结束;如果没有匹配的 case 语句则执行 default 块的代码。 注意点: (1)switch 后面小括号中表达式的值必须是整型或字符型,括号里是已经定义好的变量。 (2)case 后面的值可以是常量数值,如 1、2;也可以是一个常量表达式,如 2+2 ;要是字符型的常量时,需要加单引号‘’。但不能是变量或带有变量的表达式,如 a * 2 (3)case 匹配后,执行匹配块里的程序代码,如果没有遇见 break 会继续执行下一个的 case 块的内容,直到遇到 break 语句或者 switch 语句块结束 (4)可以把功能相同的 case 语句合并起来,如: case '一': case '二': System.

VUE:自定义指令(directives )选项的用法

自定义指令分为全局指令和局部指令。全局指令可在任意vue组件内生效,局部指令仅在注册了指令的组件内生效。 全局指令和局部指令写法几乎相同。全局指令是在main.js内使用Vue.directive注册,局部指令是在组件的directives选项写入。 下面介绍一下指令的具体用法。 指令,常用于封装一些涉及dom的公共功能,比如表单的自动获取焦点,列表的下拉收缩等。 一、指令的钩子函数 指令对象共有五个钩子函数:bind、inserted、update、componentUpdated、unbind。这些参数均可选。 bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。 componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 unbind:只调用一次,指令与元素解绑时调用 二、钩子函数的参数 el:指令所绑定的元素,可以用来直接操作 DOM 。binding:一个对象,包含以下属性: name:指令名,不包括 v- 前缀。value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1"中,表达式为 "1 + 1"。arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。 除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。 三、简单的案例 一个实现了点击展开、选中收缩的下拉框. 代码如下: vue:

Spring boot配置alibaba durid数据源的问题

Spring boot配置alibaba durid数据源有两种方式 第一种,自己配置,自己注册数据线程池 1.增加相应jar包 <!-- mysql驱动包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency> <!-- alibaba druid数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.5</version> </dependency> 2.spring的properties文件 spring.datasource.url=jdbc:mysql://localhost:3306/splatform spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #连接池配置 spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 #连接等待超时时间 spring.datasource.maxWait=60000 #配置隔多久进行一次检测(检测可以关闭的空闲连接) spring.datasource.timeBetweenEvictionRunsMillis=60000 #配置连接在池中的最小生存时间 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false # 打开PSCache,并且指定每个连接上PSCache的大小 spring.datasource.poolPreparedStatements=true spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 spring.datasource.filters=stat,wall # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 3.注册对应配置类 package com.zhangda.core.config; import java.sql.SQLException; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.

Intellij IDEA 主题导入与删除

一、IntelliJ IDEA 导入主题 1. 下载主题 通过此地址下载自己喜欢的主题。 2. 在 IntelliJ IDEA 中导入主题 【File】 - 【Import Settings】 - 选择下载的主题 - 重启 IntelliJ IDEA 后生效。 3. 配置主题 通过Ctrl + Alt + S快捷键打开Settings面板 - 【Editor】 - 【Color Scheme】 - 【Scheme】 - 选择导入的主题(默认已选择刚才导入的主题)。 二、IntelliJ IDEA 删除主题 主题配置文件的位置默认在C:\Users\${userName}\.IntelliJIdea2018.2\config\colors目录下,找到相应的文件,并将其删除,重启 IntelliJ IDEA 后生效。 三、说明 下载了几个下载量靠前的主题尝试后,个人觉得还是 IntelliJ IDEA 自带的主题好看。所以,就个人而言,之后不再去设置其它主题。

函数的调用(汇编代码分析)

1.sum函数调用完为什么会回退到main函数的调用栈针上。 2.为什么调用完后会从下一行执行。 3.值是怎么传递的,是形参开辟内存,还是实参开辟。 # include<stdio.h> int sum(int first,int second) { int tmp; tmp = first+second; return tmp; } int main() { int a = 10; int b = 20; int rt = sum(a,b); return 0; } 1.设置断点,启动debug模式。 2.调试-》窗口-》反汇编得到下图所示汇编代码。 分析汇编代码: push:压栈 pop:出栈,把栈上数据给寄存器 call:1.压入下一行地址,2,jump跳转到(sum)函数栈顶 mov:把数值移动到寄存器 lea:挪指针 add:累加 sub:减 pc寄存器:存放一条指令的地址。 寄存器入栈,相当于在栈顶开辟内存,这块内存即为形参地址空间。 eax ebx ecx是存放数值的寄存器。 ebp栈底指针寄存器 esp栈顶指针寄存器 参数传递的方向:从右向左。函数的返回值由寄存器带回。 形参开辟内存在main函数上。

MySQL 安装失败 start service 执行失败

简单说一下安装MySQL的坑点,安装执行到最后一步的时候,执行不下去,最后打开客户端,就是闪退。或者说执行到第三步,直接是失败。start service就没有响应了,按照网上的方法,怎么也不对。这就是坑,只对一半。 以下是我用过的方法: MySQL 安装总结:Start service执行无响应或失败。 安装MySQL卸载后重新安装,每次到最后Start service的时候就会挂掉,出现无响应或者失败,主要是之前装过MySQL,没删除干净相关信息。 接下来整理一下我重新安装MySQL的信息步骤: 1.打开注册表方法,打开运行(cmd),输入regedit,进入注册表。 2.删除MySQL在注册表中的信息,主要是以下3个目录:(注册表中有哪一个就删哪一个) (1) HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL 目录删除 (2) HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL 目录删除 (3) HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL 目录删除 3.删除C盘中MySQL的信息:在ProgramData这个文件中。注:这个文件是个隐藏文件,需要显示隐藏文件。 4.卸载MySQL,然后删除C:\ProgramData\MySQL 文件 5.在电脑的环境高级变量设置里面的:系统参数的Path把MySQL安装时添加的配置删除。 6.在注册表中,点击编辑,查找一下,输入MySQL,根据实际情况,来判断是否删除注册,有的不是安装MySQL时产生的注册表,就不用删。注:有的不是安装MySQL产生的,不要删,如果找到的环境变量中的Path中MySQL,应该修改,把MySQL去掉,而不是删除对应的注册信息。 7.卸载MySQL数据库并删除他的安装目录,然后重启一下机器,再次安装。 8.在安装的过程中,有个一server name的值是MySQL,点击next的时候,会有警告弹出框,意思就是已经有这个名字了,需要换一个。这个时候不用害怕,只需要在选项中选择一个然后点击next即可。

ArcGIS for Android 100.3的学习与应用(三) 实现地图添加自定义指北针

图为高德地图实现指北针的效果,那么ArcGIS如何实现呢? 实现方式: 添加地图的旋转监听: map.addMapRotationChangedListener(new MapRotationChangedListener() { @Override public void mapRotationChanged(MapRotationChangedEvent mapRotationChangedEvent) { startIvCompass((float) map.getMapRotation());//map.getMapRotation()为地图旋转的角度 } }); 在mapRotationChanged()中执行 startIvCompass()指北针icon旋转方法; /*** *设置ImageView旋转动画 * @param bearing * lastBearing为上次icon旋转之后所处的角度 * bearing为要旋转到的角度位置 */ private void startIvCompass(float bearing) { bearing = 360 - bearing; rotateAnimation = new RotateAnimation(lastBearing, bearing, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setFillAfter(true); ivCompass.startAnimation(rotateAnimation); lastBearing = bearing; }

Linux下gcc编译生成动态链接库*.so文件并调用它

Linux下gcc编译生成动态链接库*.so文件并调用它 gcc -c test.c将生成test.o的目标文件 gcc -o app test.c将生成可执行程序app 动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。 1、动态库的编译 下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。 //so_test.h: #include "stdio.h" void test_a(); void test_b(); void test_c(); //test_a.c: #include "so_test.h" void test_a() { printf("this is in test_a...\n"); } //test_b.c: #include "so_test.h" void test_b() { printf("this is in test_b...\n"); } //test_c.c: #include "so_test.h" void test_c() { printf("this is in test_c...\n"); } 将这几个文件编译成一个动态库:libtest.so $ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so 2、动态库的链接 在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。 test.c: #include "so_test.h" int main()

练习8-2 计算两数的和与差 (10 point(s))

练习8-2 计算两数的和与差 (10 point(s)) 本题要求实现一个计算输入的两数的和与差的简单函数。 函数接口定义: void sum_diff( float op1, float op2, float *psum, float *pdiff ); 其中op1和op2是输入的两个实数,*psum和*pdiff是计算得出的和与差。 裁判测试程序样例: #include <stdio.h> void sum_diff( float op1, float op2, float *psum, float *pdiff ); int main() { float a, b, sum, diff; scanf("%f %f", &a, &b); sum_diff(a, b, &sum, &diff); printf("The sum is %.2f\nThe diff is %.2f\n", sum, diff); return 0; } /* 你的代码将被嵌在这里 */ 输入样例: 4 6 输出样例: The sum is 10.

学习笔记_关于switch在whlie中无限循环的解决办法_C语言

学习笔记_关于switch在whlie中无限循环的解决办法_C语言 今天在做作业的时候突然发现一个问题 #include<stdio.h> int main() { int a; while(1) { printf("请输入:"); scanf("%d",&a); switch(a) { case 1:printf("你输入了1 \n\n");break; case 2:printf("你输入了2 \n\n");break; default:printf("输入有误! \n\n");break; } } return 0; } 上面这段代码,应该除了输入1或者2,输入其他的都会输出“输入错误”,但是,如果不小心输入了字母或符号,程序就会进入无限循环,也就是说只能输入数字。 上网查了后发现,scanf函数是从缓冲区接受数值,而当我们输入字母或其他时,字符就一直留在缓冲区,再次循环,scanf再从缓冲区获取时还是字母,就相当跳过了scanf这一句,从而造成死循环。 经过测试后发现,只要把接受输入的变量定义在while循环里面,并给该变量赋值,在scanf之前清空缓冲区,这样程序就可以正常运行了。 #include<stdio.h> int main() { while(1) { int a = -1; fflush(stdin); //清理缓冲区 printf("请输入:"); scanf("%d",&a); switch(a) { case 1:printf("你输入了1 \n\n");break; case 2:printf("你输入了2 \n\n");break; default:printf("输入有误! \n\n");break; } } return 0; } 该文章仅为小白在学习上的个人见解,如果有错误,或者大神有更好的办法,还望不啬赐教。

解决webstorm中vue语法没有提示

首先看看webstrom内置的vue插件,打上勾,没有这个选项就要自己去下载插件了 如果插件还是没有语法提示,可以用下面的方法,自己添加语法进去 搜索 unknown HTML tag attributes ,将下面的指令复制到点开的窗口里 v-text v-html v-once v-if v-show v-else v-for v-on v-bind v-model v-ref v-el v-pre v-cloak v-on:click v-on:keyup.enter v-on:keyup @click @change number debounce transition :is 为了保险起见 , 我在unknown HTML tag 选项里也做了同样的配置 最终代码提示如下, 跟用了vue插件效果一样, 有提示就行 ,问题解决

java 24种设计模式(附实例代码)

目录 简单工厂模式 工厂方法模式 抽象工厂模式 建造者模式 单例模式 原型模式 适配器模式 装饰模式 策略模式 外观模式 职责链模式 总体来说设计模式分为三大类: 创建型模式、结构型模式、行为型模式 创建型模式:用于创建对象 结构型模式:处理类之间的关系 行为型模式:描述类或对象如何交互或怎样分配职责 六种:简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。关注对象的创建过程对类的实例化过程进行抽象,对用户隐藏类 的实例的创建细节创建型模式描述如何将对象的创建和使用分离,让用户在使用对象时无需关心对象的创建细节,从而降低系统 的耦合度,让设计方案更易于修改和扩展关注创建什么(What) 、由谁创建(Who) 、何时创建(When) 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 简单工厂模式 定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类 在简单工厂模式中用于创建实例的方法通常是静态(static)方法,因此又被称为静态工厂方法(Static Factory Method)模式要点:如果需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,而无须知道其创建细节简单工厂模式包含以下3个角色:• Factory(工厂角色)• Product(抽象产品角色)ConcreteProduct(具体产品角色)优点 ✓实现了对象创建和使用的分离 ✓客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可 ✓通过引入配置文件可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性模式缺点 ✓ 工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响 ✓增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度 ✓ 系统扩展困难,一旦添加新产品不得不修改工厂逻辑 ✓ 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展 实例: //抽象图表接口,充当抽象产品类 public interface Chart { public void display(); } //饼状图类,充当具体产品类 public class PieChart implements Chart { public PieChart() { System.out.println("创建饼状图!"); } public void display() { System.out.println("显示饼状图!"); } } //柱状图类,充当具体产品类 public class HistogramChart implements Chart{ public HistogramChart() { System.

Android全局监听键盘弹出/收起事件,支持在任何类

源码地址:https://github.com/HuCanui/KeyboradObserver 最近发现公司的app右下角有个小悬浮窗,这个悬浮窗是在Service里面控制显示隐藏的,当键盘弹窗输入时会影响输入。追求完美的我实在看不下去了,给自己提了个需求键盘弹出时隐藏悬浮窗,键盘退出时继续显示。 来!实现一把。通常做法实在activity里面去获取顶级View,然后设置监听OnGlobalLayoutListener,onGlobalLayout的时候检查下顶级View实际的高度是不是比实际的可见的高度大100dp。默认键盘高度大于100dp。 final View activityRoot = getWindow().getDecorView(); if (activityRoot == null) { return; } ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { private final Rect r = new Rect(); private final int visibleThreshold = Math.round(dp2px(activity, 100)); @Override public void onGlobalLayout() { activityRoot.getWindowVisibleDisplayFrame(r); int heightDiff = activityRoot.getRootView().getHeight() - r.height(); //键盘是否弹出 boolean isOpen = heightDiff > visibleThreshold; if (isOpen == wasOpened) { // keyboard state has not changed return; } wasOpened = isOpen; } }; 但。。。是,现在是在Service里面,我ca,怎么拿到当前页面RootView。不好意思,夸张了?

Spark Streaming整合kafka实战

2019独角兽企业重金招聘Python工程师标准>>> kafka作为一个实时的分布式消息队列,实时的生产和消费消息,这里我们可以利用SparkStreaming实时计算框架实时地读取kafka中的数据然后进行计算。在spark1.3版本后,kafkaUtils里面提供了两个创建dstream的方法,一种为KafkaUtils.createDstream,另一种为KafkaUtils.createDirectStream。 1.KafkaUtils.createDstream方式 构造函数为KafkaUtils.createDstream(ssc,[zk], [consumer group id], [per-topic,partitions] ) 使用了receivers来接收数据,利用的是Kafka高层次的消费者api,对于所有的receivers接收到的数据将会保存在Spark executors中,然后通过Spark Streaming启动job来处理这些数据,默认会丢失,可启用WAL日志,它同步将接受到数据保存到分布式文件系统上比如HDFS。 所以数据在出错的情况下可以恢复出来 。 A、创建一个receiver来对kafka进行定时拉取数据,ssc的rdd分区和kafka的topic分区不是一个概念,故如果增加特定主消费的线程数仅仅是增加一个receiver中消费topic的线程数,并不增加spark的并行处理数据数量。 B、对于不同的group和topic可以使用多个receivers创建不同的DStream C、如果启用了WAL(spark.streaming.receiver.writeAheadLog.enable=true) 同时需要设置存储级别(默认StorageLevel.MEMORY_AND_DISK_SER_2), 即KafkaUtils.createStream(….,StorageLevel.MEMORY_AND_DISK_SER) 1.1KafkaUtils.createDstream实战 (1)添加kafka的pom依赖 <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka_0-10_2.11</artifactId> <version>2.0.2</version> </dependency> (2)启动zookeeper集群 zkServer.sh start (3)启动kafka集群 kafka-server-start.sh /export/servers/kafka/config/server.properties (4)创建topic kafka-topics.sh --create --zookeeper node-1:2181 --replication-factor 1 --partitions 3 --topic kafka_spark (5)向topic中生产数据 通过shell命令向topic发送消息 kafka-console-producer.sh --broker-list node-1:9092--topic kafka_spark (6)编写SparkStreaming应用程序 KafkaUtils.createDstream方式(基于kafka高级Api-----偏移量由zk保存) package cn.testdemo.dstream.kafka import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.streaming.{Seconds, StreamingContext} import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream} import org.apache.spark.streaming.kafka.KafkaUtils import scala.collection.immutable //todo:利用sparkStreaming对接kafka实现单词计数----采用receiver(高级API) object SparkStreamingKafka_Receiver {

coco2017 数据集下载链接

http://images.cocodataset.org/zips/train2017.zip http://images.cocodataset.org/annotations/annotations_trainval2017.zip http://images.cocodataset.org/zips/val2017.zip http://images.cocodataset.org/annotations/stuff_annotations_trainval2017.zip http://images.cocodataset.org/zips/test2017.zip http://images.cocodataset.org/annotations/image_info_test2017.zip 

C#中的字节数组、16进制字符串、数值类型之间转换

//字节数组buff 转 16进制字符串line line = BitConverter.ToString(buff, 0, Length); line.Split(new char[] { '-' }) ; //16进制字符串 转 字节数组buff=System.Text.Encoding.ASCII.GetBytes("0x00a18402")或者Byte_data = Convert.ToByte(String_based16, 16); //字节数组 转 uint 等等pktTHDXP.DID = BitConverter.ToUInt32(buff, 0);

java jwt 如何设定过期时间

用metabase时候内嵌jwt协议,java库是jjwt,一直找不到实现过期的方法,终于找到 Jwt token = JwtHelper.encode("{\"resource\":{\""+resourceType+"\": "+dashboardId+"},\"params\":{},\"iat\":"+iat+",\"exp\":"+time+"}", new MacSigner(METABASE_SECRET_KEY)) 复制代码 这里一直缺少的是iat:发现token 的时间,exp:过期时间 都是timestamp秒,缺一不可 通过源码可以知道这些参数其实都是jwt的payload,有些自定义比如resource,params,有些默认比如过期时间 exp iat.

感性思维和理性思维

人的思维可以分为两部分∶感性思维和理性思维。 感性思维主要是靠自己的经验和直觉,去思考和判断。理性思维主要是靠已经掌握的科学的方法,去思考和判断。 感性思维活动包含:感觉、知觉、感性概念、本能思维倾向、习惯思维、联想、想象、情感活动、直觉、定量的度量、模糊的范畴思维、创造性思维。感性思维的特点是自然形成、敏感、自发产生、自动执行、孤立片面、分散并行。 理性思维包含:语言形式的概念、概念的分类、定性思维、范畴思维、逻辑隶属关系、因果推理、过程流程的思考和规划、数学与拓扑/集合/立体空间演算、色彩/旋律/布局的协调性、周期规律、清晰划界、语言组织和传播。特点是人为定义与划分、知识成体系性、形式化、可推理性、突出相互联系和相互制约关系、可传播性、可理解性。 理性思维与感性思维是相互衔接的,从感性过渡到理性,就像植物的根与冠并不是两个孤立的存在。动物也有感情,也会“喜怒哀乐”的感性表现,但绝对不会使用“演绎归纳”等理性思考方法。地球上只有一种生物具有理性思维的能力,这就是“人”。从感性思维到理性思维的进步,是地球上几十亿年来生物进化的最高结晶。就像人的两条腿,感性和理性是支撑思维的两大支柱,两者相互克制,缺少了哪一方面都不能构成完整的思维活动。 感性思维在思维活动中的作用。 人的思维活动起源于感觉,是感觉驱动的,感觉信号经过层层转化,成为神经活动兴奋发放的源泉,因此感觉来得自然、自动、自发。但是感觉信息是从四面八方聚集而来,分头作用,缺乏整合,有时根本就无法整合,因此分散、孤立、片面就成了感性思维的特点。动物有着丰富的感性思维,人类发展感性思维活动的进化历程源远流长,可以说生物在进化史中99%的时间都是在发展和优化感性思维,正因为此,人类的感性思维才如此发达。 理性思维在思维中的作用。 尽管感性思维直接、自动、并行,但是由于感性思维缺乏整体性和有效的规划性,感性思维的弱点难以克服。当人脑进化发展到一定程度,意识产生,标志着理性思维的萌芽。理性思维就是要在感性思维的基础上整合,形成有效的抽象,联络事物内部的逻辑关系,使思想体系成为具有广泛联系和因果关系、顺序关系、空间关系、时间关系的有机整体。尽管理性思维的发展时间不长,程度不深,但是由于正好弥补了感性思维的不足,所以理性思维代表着先进的思维方式,具有强大的生命力。 如何合理地运用感性思维和理性思维? 由于感性的功用是感觉摄取、知觉归纳、想象再造、联想引导、情感指导,因此要发挥感性思维的长处,就是充分运用这些功能进行思维活动;由于理性的功用是概念抽象、判断分类、推理导出结论、语言表述、知识传播,应当依靠理性思维产生思维结论和决策指导。依靠感性进行思维的前半段,依靠理性产生思维的后半段,这样的思维结构更加合理。 感性思维和理性思维影响我们的自我评价? 在感性思维中,更关注一个人的感受,所以我们经常使用“感觉”这个词,而在理性思维中,我们经常使用“认为”这个词。波尔州立大学的心理学教授托马斯·霍特格雷夫对此进行了研究,他第一次发现认为/感觉这种措辞上的变化会影响人们的自我评价,当使用“感觉”一词时,人们的自我评价更为消极。 霍特格雷夫试图弄清“认为”或“感觉”这两种语境对开放性的自我评价有什么影响。141名大学生参与了实验,他们被随机分为两组。其中一组的问题是“请用5分钟时间写下你认为自己是什么样的人”,另一组的问题是“请用5分钟时间写下你感觉自己是什么样的人”。在答题结束后,霍特格雷夫逐字逐句地对自我评价的内容进行分析。他发现,“感觉”组的大学生在自我的评价上要比“认为”组的大学生更加消极。在随后对两组大学生进行综合分析后,他还发现,在答案中,“感觉”一词的出现频率和自我评价成负相关,也即,使用“我感觉……”越多的大学生,越悲观。 接下来,霍特格雷夫进一步研究了“认为”或“感觉”语境对人们的自尊有什么影响。这一次的实验选用了另外84名大学生,他们也被随机分成两组,一组需要填完整10个以“我认为自己是——”开头的句子,另一组则填写以“我感觉自己是——”开头的句子。之后,他们还要完成一个自尊测验。霍特格雷夫预期,填写了感觉句子的大学生在自尊量表上的得分也要低一些。结果如他所料,填写了以感觉开头的句子后,大学生不仅在自我评价中报告了更多的消极面,在随后自尊量表上的得分也要低一些。但是,这种措辞变化只对女性被试在自尊量表上的得分有影响,对男性被试没有影响。 霍特格雷夫表示,“认为”和“感觉”能激活不同的心理过程,“感觉”更容易激活一个人去探索过去的情感经历。而语言中的情绪词中存在一种不平衡——消极词要远多于积极词。一旦开始探索情感经历,人们就容易陷入消极情绪中,在观察自己时会倾向于观察消极的一面。这就解释了为什么“感觉”容易导致负面的自我评价。

SpringBoot(二):集成Mybatis

1、先导入mybatis依赖(如果之前钩记了就不用导了) <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> 2、在application.yml加入mybatis配置 mybatis: mapper-locations: classpath:mapping文件包名/*.xml type-aliases-package: 实体类包的全路径名 3、数据库建表 CREATE TABLE tb_user( USER_ID INT PRIMARY KEY auto_increment, # 用户id USER_NAME VARCHAR(20) #用户姓名 ); 4、创建实体类(User) package club.djkplay.springboot2.pojo; public class User { private Integer user_Id; private String user_Name; public User() { } public User(Integer user_Id) { this.user_Id = user_Id; } public User(Integer user_Id, String user_Name) { this.user_Id = user_Id; this.user_Name = user_Name; } public Integer getUser_Id() { return user_Id; } public void setUser_Id(Integer user_Id) { this.

PHP 使用Laravel框架架构设计

学习视频:https://www.youtube.com/watch?v=pzY0FBafXd0 (需翻墙) Laravel简单架构: 简单的小项目可能会把数据库查询,业务逻辑,数据传给View几乎所有操作都放在Controller,如何项目后期需求变大,最后Controller会变得很臃肿,难懂,不易维护(同样,有些会把所有增删改查,功能类写在Model,Controller再从Model一个个的拿,导致Model很乱,Model有关联表的时候可能会引起一些不必要的数据库查询) 我自己的理解:用美宜佳卖商品给客人来理解,主要Controller是某个加盟商美宜佳门店,View是客人,Model是商品制造工厂(理解有些粗糙) Repository(商品仓库): 跟Eloquent/DB操作相关的,例如增删改查,直接和数据库打交道的基础操作抽出来放在Repository中,repository中文是仓库,我的理解就是我们要从Model拿数据,先放在仓库repository中,统一由仓库管理分配,发挥仓库的职责 Service (总部服务平台): 商业逻辑,不是简单的查询数据,而是特定的任务,例如判断用户是否是会员,设置用户权限等等,这些操作建议放在Service,之后Controller再调用它 个人理解:所以在Controller和Model/Eloquent中间垫两层,如果Repository理解为商品仓库的话,我的理解Service是类似总部内部的服务平台,加盟商Controller需要拿商品给客人View,不能直接去食品工厂Model拿,先通过仓库repository,然后总部服务平台Service进行打包啊,整理啊,发车啊(各种任务),最后再给到加盟商Controller手里 Presenter(充值业务): 一些比较固定,可以单独调用的,可以用Presenter抽出来,不需要让Model去做,下次修改也单独修改Presenter就行了, 例如时间戳转成Y-m-d H:i:s格式,可以单独用Presenter处理后用@inject插入到前端模板,而不是把转化过程写在模板上面 个人理解:所以在Controller和View中间可以加一层Presenter,我的理解有点类似:美宜佳商户(Controller)可以给客人(View)充公交卡,这种小事不需要劳费工厂(Model) Transformer(快餐小吃人工筛选): 转换器,例如在仓库repository中有一个获取所有用户信息的查询操作:$this->user->all(); 但有些地方我们不需要用到那么多个字段,我只想有name和email字段,难道我要去改all()里面的参数,变成$this->user->all(['name','email'])? 这样另外的地方又要全部字段,这不就冲突了?这时候Transformer就有用了,其实原理是对$this->user->all()获得的数据进行筛选后再输出,加了个筛选器。 之后要修改结果字段就直接在transform修改即可,当然还可以额外添加需要的字段:array_set() 个人理解:这一块我的理解就是有些客人需要点一些快餐,例如美宜佳里面的车仔面呀,烤肠呀,在卖出商品的时候需要根据客人的需求对小吃进行筛选再卖出去,不可能客人指点要一个烤肠,你把店里全部小吃拿给他,让他自个去筛选,中间卖出去的时候需要Transformer进行筛选再给出商品 Formatter(包装): 主要用于保持API返回格式的一致(使用方法和transform类似): 个人理解:Formatter这一块我的理解就是商品包装,客人买东西,买小吃,你需要对商品先进行包装,当然这个包装肯定需要保持一致

css实现背景backgroup渐变效果,兼容各个浏览器(直接生成)

笔者其实对于css一直是一知半解的状态。今天公司的需求需要让背景如图上所示。 通过度娘找到了一个强大的背景渐变手动设计的网站,在此分享 gradient-editor(国外开发者) 顺便献上自己css代码。或许有些用处 background: rgb(248,181,0); /* Old browsers */ background: -moz-linear-gradient(45deg, rgba(248,181,0,1) 4%, rgba(252,205,77,1) 13%, rgba(252,205,77,1) 13%, rgba(249,249,247,1) 36%, rgba(249,249,247,1) 36%, rgba(249,249,247,1) 36%, rgba(249,249,247,1) 36%, rgba(249,249,247,1) 37%, rgba(249,249,247,1) 62%, rgba(252,205,77,1) 85%, rgba(252,205,77,1) 85%, rgba(248,181,0,1) 100%, rgba(248,181,0,1) 100%, rgba(251,223,147,1) 100%, rgba(248,181,0,1) 100%); /* FF3.6-15 */ background: -webkit-linear-gradient(45deg, rgba(248,181,0,1) 4%,rgba(252,205,77,1) 13%,rgba(252,205,77,1) 13%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 37%,rgba(249,249,247,1) 62%,rgba(252,205,77,1) 85%,rgba(252,205,77,1) 85%,rgba(248,181,0,1) 100%,rgba(248,181,0,1) 100%,rgba(251,223,147,1) 100%,rgba(248,181,0,1) 100%); /* Chrome10-25,Safari5.1-6 */ background: linear-gradient(45deg, rgba(248,181,0,1) 4%,rgba(252,205,77,1) 13%,rgba(252,205,77,1) 13%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 36%,rgba(249,249,247,1) 37%,rgba(249,249,247,1) 62%,rgba(252,205,77,1) 85%,rgba(252,205,77,1) 85%,rgba(248,181,0,1) 100%,rgba(248,181,0,1) 100%,rgba(251,223,147,1) 100%,rgba(248,181,0,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ filter: progid:DXImageTransform.

WEEX UI 官网

https://alibaba.github.io/weex-ui/#/cn/weex-ui-report http://weex-project.io/cn/references/broadcast-channel.html weex

AGV-倍福beckhoff TWINCAT2及台达电机、传感器等使用总结

1、安装TWINCAT X64 2、将蓝屏补丁覆盖到 C:\TWINCAT\DRIVER 3、TC SYSTEM MANAGER 连接 创建一个demo项目: 1、WIN7 32位安装TWINCAT2(只能使用32位系统?64位WIN10无法设置网卡),蓝屏runtime补丁 打开system manager-options-show real time ethernet...,然后install网卡 然后choose target,如果知道倍福控制器IP(出厂默认开DHCP)则可以直接按IP添加,选按IP 硬件连接没问题,则system manager软件右下角连接状态变化 2、使用PLC control软件,创建工程,编辑代码,build 此处创建一个EL2008数字输出模块1口输出TRUE的demo。 build后得到一个tpy文件,保存IO变量、任务周期、PLC端口号等信息。是在system manager中为目标系统作硬件配置时需导入的接口文件。 3、使用system manager软件,配置项目 选择控制器,choose target system,界面右下方连接状态变化 添加plc程序,plc-configuration-append plc project,选择tpy文件,导入plc程序 此时点存储,会保存一个.tsm文件,(system manager工程?) 扫描IO模块,I/O-configuration-scan devices。只允许在config mode下能选择,菜单栏上set/reset twincat to config mode 映射IO和变量,可从I/O configuration-I/O device-device 1 -Term 1...或者plc configuratiion-项目-变量,linked to设置映射。需注意模块上对应的端子号 激活配置,上面的操作将程序与I/O对应,对应关系需写入控制器,点activate configuration,控制器进入run mode。 下载程序,在plc control软件-online-choose run-time system,选择需程序运行的控制器,此时界面下方状态变化。再online-login,下载程序至控制器,login有时会没用(BUG?)则保存工程,重启PLC control 运行程序,online-run,或F5 调试程序,可以设置断点、设置变量、强制设置变量 设置自启动: system-configuration - boot setting - run mode 任务TASK、程序、子程序:

File.exists() returns false when file exists

借用了下stackoverflow上的标题名,方便需要的同学搜索 - -! 原文地址:https://blog.csdn.net/ll413343176/article/details/84059549 转载请注明 英语能力强的可以先看下这两个帖子 https://stackoverflow.com/questions/919918/file-exists-returns-false-when-file-exists https://bugs.java.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097 使用相对路径时,如果user.dir发生变化会导致下面两个结果运行不一致 file.exists() == false file.getAbsoluteFile().exists() == true 来自oracle官网的解释为: EVALUATION Not a bug. If you need to resolve a filename against the value of the "user.dir" system property then you must use getAbsolutePath (or getAbsoluteFile, or getCanonicalPath, or getCanonicalFile). Simpler operations such as exists() always resolve against the directory in which the Java virtual machine was originally invoked (and no, there is no way to change that).

Arduino core for ESP8266 WiFi chip ESP8266 WiFi中文文档

https://github.com/esp8266/Arduino https://arduino-esp8266.readthedocs.io/en/2.4.2/ 这个项目为Arduino环境带来了对ESP8266芯片的支持。它允许您使用熟悉的Arduino函数和库编写草图,并直接在ESP8266上运行,不需要外部微控制器。ESP8266 Arduino core拥有使用TCP和UDP通过WiFi通信的库,设置HTTP、mDNS、SSDP和DNS服务器,做OTA更新,使用闪存中的文件系统,使用SD卡、伺服器、SPI和I2C外设。 ESP8266WiFi library ESP8266WiFi库 Quick Start 快速入门 #include <ESP8266WiFi.h> void setup() { Serial.begin(115200); Serial.println(); WiFi.begin("network-name", "pass-to-network"); Serial.print("Connecting"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.print("Connected, IP address: "); Serial.println(WiFi.localIP()); } void loop() {} 在线路WiFi。开始(“network-name”, “pass-to-network”)将"network-name"和"pass-to-network"替换为您想要连接的Wi-Fi网络的名称和密码。然后将草图上传到ESP模块,打开串口监视器应该能看到有IP输出。 #include <ESP8266WiFi.h> 包括ESP8266WiFi库。这个库提供了ESP8266特定的Wi-Fi例程,我们调用它来连接网络。 实际连接到Wi-Fi是通过调用:` WiFi.begin("network-name", "pass-to-network"); 连接过程可能需要几秒钟的时间,我们正在检查,以完成以下循环: while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } while()循环将在WiFi.status()不是WL_CONNECTED时继续循环。只有当状态更改为WL_CONNECTED时,循环才会退出。 最后一行将打印出DHCP分配给ESP模块的IP地址: Serial.println(WiFi.localIP()); 注意:如果连接被建立,然后由于某种原因丢失,ESP将自动重新连接到最后使用的接入点,一旦它再次联机。这将由Wi-Fi库自动完成,无需任何用户干预。 Who is Who 工作模式 连接到Wi-Fi网络的设备称为工作站(STA)。连接到Wi-Fi由一个接入点(AP)提供,它充当一个或多个站点的集线器。另一端的接入点连接到有线网络。接入点通常与路由器集成在一起,提供从Wi-Fi网络到internet的访问。每个接入点都由一个SSID(服务集标识符)识别,它本质上是连接设备(站)到Wi-Fi时选择的网络名称。 ESP8266模块可以作为一个站运行,所以我们可以连接到Wi-Fi网络。它还可以作为软接入点(soft- ap)运行,以建立自己的Wi-Fi网络。因此,我们可以将其他站连接到这种ESP模块。ESP8266还可以在站和软接入点模式下运行。这提供了建立例如网状网络的可能性 ESP8266WiFi库提供了广泛的C方法(功能)和属性集合来配置和操作车站和/或软接入点模式下的ESP8266模块。 Class Description 类描述 Station (STA)模式 站(STA)模式用于使ESP模块连接到由接入点建立的Wi-Fi网络。

python27的pip不能用,ride运行没有信息,UnicodeDecodeError编码问题

基于py2的自动化测试编码问题很严重,如果你对编码规范不是很了解,安装不出错误还好,出错的话网上的解答方案不是很齐全。这里我把所有遇到的问题都列出来。如果出现这样的问题就对应改就好了。 Robotframework 之pip安装(一) Robotframework 之exe安装(二) Robotframework安装过程中错误解决方案(三) 一、pip不能用,出现一下错误 步骤① Python -m pip install --upgrade pip 使用出错 即出现以下错误: UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xb4 in position 7: ordinal not in range(128) You are using pip version 9.0.3, however version 18.1 is available. You should consider upgrading via the ‘python -m pip install --upgrade pip’ command. 步骤② 解决方案:找到下面文件F:\Python27\Lib\mimetypes.py 编辑该文件,在import下加入以下代码并保存: if sys.getdefaultencoding() != 'gbk': reload(sys) sys.setdefaultencoding('gbk') 看图片: 步骤③ 再次运行上面的命令即ok 然后用命令安装robotframework、ride等必要的软件,具体参考 Robotframework 之pip安装(一)

在 vscode 中使用 Git :拉取、提交、克隆

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 PS:转载此文后,网友在评论中提到还有其它方法,不过目前个人尚在研究中,有兴趣的朋友们也可自行一探究竟 ... ------------------------------------------------------------------------- 1、将代码放到码云 到码云里新建一个仓库,完成后码云会有一个命令教程按上面的来就行了码云中的使用教程: Git 全局设置: git config --global user.name "ASxx" git config --global user.email "123456789@qq.com" 创建 git 仓库: mkdir wap // 项目在本地的路径 cd wap git init touch README.md git add README.md git commit -m "first commit" git remote add origin https://git.oschina.net/name/package.git // 远程仓库地址 git push -u origin master 已有项目: cd existing_git_repo git remote add origin https://git.oschina.net/name/package.git git push -u origin master 下面说下详细的本地操作步骤: 1、用vs打开你的项目文件夹 2、配置git 打开Git Bash输入以下命令

日志工具logAPI 及 logback的使用

日志工具logAPI 及 logback的使用 一、logAPI的使用 1、代码 import java.io.IOException; import java.util.logging.FileHandler; import java.util.logging.SimpleFormatter; public class MyTestLogAPI{ private final static java.util.logging.Logger loggerAPI = java.util.logging.Logger.getLogger("MyTestLogBack"); public static void main(String[] args) { System.out.println("hello,world!"); try { FileHandler fileHandler = new FileHandler("d:/logapitest.txt"); //为处理器设置日志格式:Formatter SimpleFormatter sf = new SimpleFormatter(); fileHandler.setFormatter(sf); loggerAPI.addHandler(fileHandler); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } loggerAPI.info("loggerapi hello"); } } 二、logback的使用

Python android 多国翻译提取整合工具

Python android 多国翻译提取整合工具 前提功能 1功能 2代码实现 前提 使用了 BeautifulSoup, 我很懒 功能 1 提取 string.xml 资源文件的内容 <string name="app_name">App Name</string> -> App Name 功能 2 整合 翻译文件到源文件, 翻译文件每行代表一个翻译,不能有空行, 原理就是 按行替换资源文件的内容 <string name="app_name">App Name</string> + 应用名 -> <string name="app_name">应用名</string> 代码实现 from bs4 import BeautifulSoup is_write_translate = False source_path = "strings.xml" source_string_path = "资源文件.txt" translate_path = "xxxx.txt" source_translate_path = "new_string.xml" def write_to_file(path, text): with open(path, 'a', encoding='utf-8') as f: f.writelines(text + '\n') def get_xml_string_to_file(): file = open(source_path, 'r', encoding='utf-8') soup = BeautifulSoup(file, "

ZUC密码算法 - Python实现

这段时间一直在做密码学实验,写了三个算法:SMS4、ZUC、SM3。这些算法效率不高,也没有经过安全审计,可能有很多潜在的BUG,不过算法的总体思路还算清晰,写完实验报告就删掉的话,自己感觉也挺可惜的,所以就发到CSDN上来,初学者可以在学习的时候拿来做个参考。 此实现参照国密局的ZUC标准文档编写,标准文档在百度文库可以找到。 算法整体流程图: init()函数的流程图: 源码包含在两个文件里。第一个文件:ConstParameters.py,定义了一些常量;第二个文件Functions.py是算法用到的功能模块,运行环境为Windowns 10 - 1809,Python 3.7.1 # -*- coding: utf-8 -*- """ Created on Fri Nov 2 15:29:33 2018 @author: wang """ D = ['100010011010111', '010011010111100', '110001001101011',\ '001001101011110', '101011110001001', '011010111100010',\ '111000100110101', '000100110101111', '100110101111000',\ '010111100010011', '110101111000100', '001101011110001',\ '101111000100110', '011110001001101', '111100010011010',\ '100011110101100'] S1 = [[0x3E, 0x72, 0x5B, 0x47, 0xCA, 0xE0, 0x00, 0x33, 0x04, 0xD1, 0x54, 0x98, 0x09, 0xB9, 0x6D, 0xCB, ], [0x7B, 0x1B, 0xF9, 0x32, 0xAF, 0x9D, 0x6A, 0xA5, 0xB8, 0x2D, 0xFC, 0x1D, 0x08, 0x53, 0x03, 0x90, ], [0x4D, 0x4E, 0x84, 0x99, 0xE4, 0xCE, 0xD9, 0x91, 0xDD, 0xB6, 0x85, 0x48, 0x8B, 0x29, 0x6E, 0xAC, ], [0xCD, 0xC1, 0xF8, 0x1E, 0x73, 0x43, 0x69, 0xC6, 0xB5, 0xBD, 0xFD, 0x39, 0x63, 0x20, 0xD4, 0x38, ], [0x76, 0x7D, 0xB2, 0xA7, 0xCF, 0xED, 0x57, 0xC5, 0xF3, 0x2C, 0xBB, 0x14, 0x21, 0x06, 0x55, 0x9B, ], [0xE3, 0xEF, 0x5E, 0x31, 0x4F, 0x7F, 0x5A, 0xA4, 0x0D, 0x82, 0x51, 0x49, 0x5F, 0xBA, 0x58, 0x1C, ], [0x4A, 0x16, 0xD5, 0x17, 0xA8, 0x92, 0x24, 0x1F, 0x8C, 0xFF, 0xD8, 0xAE, 0x2E, 0x01, 0xD3, 0xAD, ], [0x3B, 0x4B, 0xDA, 0x46, 0xEB, 0xC9, 0xDE, 0x9A, 0x8F, 0x87, 0xD7, 0x3A, 0x80, 0x6F, 0x2F, 0xC8, ], [0xB1, 0xB4, 0x37, 0xF7, 0x0A, 0x22, 0x13, 0x28, 0x7C, 0xCC, 0x3C, 0x89, 0xC7, 0xC3, 0x96, 0x56, ], [0x07, 0xBF, 0x7E, 0xF0, 0x0B, 0x2B, 0x97, 0x52, 0x35, 0x41, 0x79, 0x61, 0xA6, 0x4C, 0x10, 0xFE, ], [0xBC, 0x26, 0x95, 0x88, 0x8A, 0xB0, 0xA3, 0xFB, 0xC0, 0x18, 0x94, 0xF2, 0xE1, 0xE5, 0xE9, 0x5D, ], [0xD0, 0xDC, 0x11, 0x66, 0x64, 0x5C, 0xEC, 0x59, 0x42, 0x75, 0x12, 0xF5, 0x74, 0x9C, 0xAA, 0x23, ], [0x0E, 0x86, 0xAB, 0xBE, 0x2A, 0x02, 0xE7, 0x67, 0xE6, 0x44, 0xA2, 0x6C, 0xC2, 0x93, 0x9F, 0xF1, ], [0xF6, 0xFA, 0x36, 0xD2, 0x50, 0x68, 0x9E, 0x62, 0x71, 0x15, 0x3D, 0xD6, 0x40, 0xC4, 0xE2, 0x0F, ], [0x8E, 0x83, 0x77, 0x6B, 0x25, 0x05, 0x3F, 0x0C, 0x30, 0xEA, 0x70, 0xB7, 0xA1, 0xE8, 0xA9, 0x65, ], [0x8D, 0x27, 0x1A, 0xDB, 0x81, 0xB3, 0xA0, 0xF4, 0x45, 0x7A, 0x19, 0xDF, 0xEE, 0x78, 0x34, 0x60, ],] S2 = [[0x55, 0xC2, 0x63, 0x71, 0x3B, 0xC8, 0x47, 0x86, 0x9F, 0x3C, 0xDA, 0x5B, 0x29, 0xAA, 0xFD, 0x77, ], [0x8C, 0xC5, 0x94, 0x0C, 0xA6, 0x1A, 0x13, 0x00, 0xE3, 0xA8, 0x16, 0x72, 0x40, 0xF9, 0xF8, 0x42, ], [0x44, 0x26, 0x68, 0x96, 0x81, 0xD9, 0x45, 0x3E, 0x10, 0x76, 0xC6, 0xA7, 0x8B, 0x39, 0x43, 0xE1, ], [0x3A, 0xB5, 0x56, 0x2A, 0xC0, 0x6D, 0xB3, 0x05, 0x22, 0x66, 0xBF, 0xDC, 0x0B, 0xFA, 0x62, 0x48, ], [0xDD, 0x20, 0x11, 0x06, 0x36, 0xC9, 0xC1, 0xCF, 0xF6, 0x27, 0x52, 0xBB, 0x69, 0xF5, 0xD4, 0x87, ], [0x7F, 0x84, 0x4C, 0xD2, 0x9C, 0x57, 0xA4, 0xBC, 0x4F, 0x9A, 0xDF, 0xFE, 0xD6, 0x8D, 0x7A, 0xEB, ], [0x2B, 0x53, 0xD8, 0x5C, 0xA1, 0x14, 0x17, 0xFB, 0x23, 0xD5, 0x7D, 0x30, 0x67, 0x73, 0x08, 0x09, ], [0xEE, 0xB7, 0x70, 0x3F, 0x61, 0xB2, 0x19, 0x8E, 0x4E, 0xE5, 0x4B, 0x93, 0x8F, 0x5D, 0xDB, 0xA9, ], [0xAD, 0xF1, 0xAE, 0x2E, 0xCB, 0x0D, 0xFC, 0xF4, 0x2D, 0x46, 0x6E, 0x1D, 0x97, 0xE8, 0xD1, 0xE9, ], [0x4D, 0x37, 0xA5, 0x75, 0x5E, 0x83, 0x9E, 0xAB, 0x82, 0x9D, 0xB9, 0x1C, 0xE0, 0xCD, 0x49, 0x89, ], [0x01, 0xB6, 0xBD, 0x58, 0x24, 0xA2, 0x5F, 0x38, 0x78, 0x99, 0x15, 0x90, 0x50, 0xB8, 0x95, 0xE4, ], [0xD0, 0x91, 0xC7, 0xCE, 0xED, 0x0F, 0xB4, 0x6F, 0xA0, 0xCC, 0xF0, 0x02, 0x4A, 0x79, 0xC3, 0xDE, ], [0xA3, 0xEF, 0xEA, 0x51, 0xE6, 0x6B, 0x18, 0xEC, 0x1B, 0x2C, 0x80, 0xF7, 0x74, 0xE7, 0xFF, 0x21, ], [0x5A, 0x6A, 0x54, 0x1E, 0x41, 0x31, 0x92, 0x35, 0xC4, 0x33, 0x07, 0x0A, 0xBA, 0x7E, 0x0E, 0x34, ], [0x88, 0xB1, 0x98, 0x7C, 0xF3, 0x3D, 0x60, 0x6C, 0x7B, 0xCA, 0xD3, 0x1F, 0x32, 0x65, 0x04, 0x28, ], [0x64, 0xBE, 0x85, 0x9B, 0x2F, 0x59, 0x8A, 0xD7, 0xB0, 0x25, 0xAC, 0xAF, 0x12, 0x03, 0xE2, 0xF2, ],] # -*- coding: utf-8 -*- "

tensorflow变量——Variable

1.tensorflow变量——Variable (1)在tensorflow中,变量(tf.Variable)的作用就是保存和更新神经网络中的参数。 tensorflow中的变量也需要指定初始值。 在神经网络中,一般给参数赋予随机初始值,即使用随机数给tensorflow中的变量初始化。 示例: weights = tf.Variable(tf.random_normal([2,3], stddev=2)) 上面这段代码调用了tensorflow变量的声明函数tf.Variable。在变量声明函数中给出了初始化这个变量的方法。 tf.random_normal([2,3], stddev=2)会产生一个2x3矩阵,矩阵中的元素是均值为0、标准差为2的随机数。 tf.random_normal函数可以通过参数mean来指定平均值,在没有指定时默认为0。 (2)tensorflow随机生成函数 tf.random_normal:正态分布 tf.truncated_normal:正态分布,但如果随机出来的值偏离平均值超过2个标准差,那么这个数将被重新随机 tf.random_uniform:均匀分布 tf.random_gamma:Gamma分布 (3)tensorflow常数生成函数 tf.zeros:产生全为0的数组 tf.zeros([2,3],int32)->[[0,0,0][0,0,0]] tf.ones:产生全为1的数组 tf.ones([2,3],int32)->[[1,1,1],[1,1,1]] tf.fill:产生一个全部为给定数字的数组 tf.fill([2,3],9)->[[9,9,9],[9,9,9]] tf.constant:产生一个给定值的常量 tf.constant([1,2,3])->[1,2,3] (4)tensorflow可以通过tf.initialize_all_variables函数实现初始化所有变量的过程 示例: init_op = tf.initialize_all_variables() sess.run(init_op) (5)在tensorflow中,变量的声明函数tf.Variable是一个运算,这个运算的结果就是一个张量,所以变量是一个特殊的张量。 通过tf.all_variables函数可以拿到当前计算图上所有的变量。 变量的类型(type)在变量构建之后就不可再更改。

iOS中FMDB的使用

在iOS开发中,如果本地需要做大量的缓存,FMDB用的是比较多的,怎么集成到项目中我这里就不说了,主要说一下FMDB使用的一个思路和自己遇到的坑。 在我自己开发聊天系统的时候,我一般是用FMDB用来缓存最近联系人列表和用户的聊天消息列表。因为聊天系统,涉及到的读和写比较频繁,所以我会封装一个单例类用来处理每个部分的数据存储和读写。 下面是用来管理最近联系人缓存的功能实现,其余的模块也可以按照这样的模式来,封装好方法,操作的时候直接调方法即可,比较方便。 先看一下.h文件的代码,这样大致就可以知道这个类主要用来干什么: #import <Foundation/Foundation.h> @class FMDatabase; @interface simpleChatCache : NSObject +(instancetype)sharedChatCache; //设置用户uid -(BOOL)initialize:(NSString*)myUserID; -(void)uninitialize; //获取所有用户信息 -(void)getUserAll:(void(^)(NSMutableArray*))callback; //插入或者更新新的数据 -(void)upsert:(NSDictionary*)data; //设置某个用户未读信息条数为0 -(void)setUnreadNum:(NSString*)targetUserID andNum:(int)num; //设置某个群未读信息条数为0 -(void)setGroupUnreadNum:(NSString *)targetGroupid andNum:(int)num; //获取未读消息数 -(void)getUnreadNum:(NSString*)targetUserID andCallback:(void(^)(int))callback; //获取某个群未读条数 -(void)getGroupUnreadNum:(NSString *)targetGroupid andCallback:(void(^)(int))callback; //删除某人的聊天记录 -(void)remove:(NSString*)targetUserID; //删除某一条群聊 -(void)removeGroup:(NSString *)groupid; //清理数据,除了世界聊天 -(void)clearCachesWithoutWorld; @end .m文件: #import "simpleChatCache.h" #import "FMDB.h" FMDatabaseQueue* __g_DB = nil; @interface simpleChatCache() { NSString* _tableName; NSString* _userID; } @end @implementation simpleChatCache +(instancetype)sharedChatCache { static simpleChatCache *sharedRunner; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedRunner = [[simpleChatCache alloc] init]; if(!

Java笔试题——2的100次方,不用大数据类(Biginteger)来解答

Java笔试题——2的100次方,不用大数据类(Biginteger)来解答 package cn.hncu.offer; public class Two100 { public static void main(String[] args) { int a[]=new int[1];//初始化数组 a[0]=1;//为第一个设置初始化值 int n=100; for(int i=0;i<n;i++){//n次方 for(int j=0;j<a.length;j++){//对数组里面的每一个值都乘上2 a[j]*=2; } for(int j=0;j<a.length-1;j++){//判断是否大于等于10 if(a[j]>=10){//如果是则前面一位进1,自己对10 取余数 a[j]%=10; a[j+1]++; } } if(a[a.length-1]>=10){//最后一位大于等于10,则数组大小增加一位,并且最大位置置1 a[a.length-1]%=10; int temp[]=new int[a.length+1];//临时数组,用来转化 System.arraycopy(a, 0, temp, 0, a.length); a=temp; a[a.length-1]=1; } } for(int i=a.length-1;i>=0;i--){//倒序输出则是结果 System.out.print(a[i]); } } } 在这里给大家提供一个学习交流的平台,java交流群: 558787436 具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。 在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。 如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。

扩充二叉树外部路径,内部路径

外部路径长度:从扩充的二叉树的根到每个外部结点的路径长度之和称为外部路径长度(E) 内部路径长度:扩充的二叉树里从根到每个内部结点的路径长度之和称为内部路径长度(I), 它们之间的关系满足E=I+2N(N为内部结点数)。 外部节点:即叶节点 内部节点:除内部节点外的节点 路径长度: 除结点 k0外的任何结点 k∈K,都存在一个结点 序列 k0,k1,…,ks,使得 k0 就是树根,且 ks=k,其中有序对 <ki-1,ki>∈ r (1≤i≤s) 。 这样的结点序列称为从根到结点 k 的一条路径, 其路径长度为 s (包含的边数)

xamarin.forms 使用ZXing扫描二维码

1. Android工程包含ZXing.Net.Mobile.Forms 2. 在C# 工程中, 包含ZXing.Net.Mobile 3. 在Android工程的MainActivity.cs中, 添加下面代码: global::ZXing.Net.Mobile.Forms.Android.Platform.Init(); ZXing.Mobile.MobileBarcodeScanner.Initialize(this.Application); using System; using Android.App; using Android.Content.PM; using Android.Runtime; using Android.Views; using Android.Widget; using Android.OS; namespace TestScan.Droid { [Activity(Label = "TestScan", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { protected override void OnCreate(Bundle bundle) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(bundle); global::Xamarin.Forms.Forms.Init(this, bundle); global::ZXing.Net.Mobile.Forms.Android.Platform.Init(); ZXing.Mobile.MobileBarcodeScanner.Initialize(this.Application); LoadApplication(new App()); } } } 4.

SQLServer高级查询

SQLServer高级查询 SQL Top select top n * from 表名 SQL Like select 列名 from 表名 where 列名 like 模式(按照我们写的规矩查询) SQL 通配符 详情在下方 SQL In select 字段 from 表名 where 字段 in (value1,value2,value3…); SQL Between select 字段 from 表名 where 字段 between value1 and value2; SQL Aliases(as) select * from student as user SQL Join select 表一.,表二. from 表一,表二 where 这俩张表的关系(主外键) SQL Inner Join select 表一.,表二. from 表一 inner join 表二 on 这俩张表的关系(主外键) SQL Left Join select 表一.

生成对抗网络(GAN)的变体pix2pix思想

1.概述 pix2pix 是对抗生成网络的一种变体,它的结构类似于CGAN,但又有别于CGAN。先来说一下它能做哪些事情,顾名思义就是将一张图片转成另一张图片(千万不要理解成像素变像素啊),或者说将一个场景转换成另一场景。pix2pix 能做的事情有很多,比如说将素描画轮廓转换成图片,将黑夜场景转换成白天场景,自动上色,超分辨率等等。具体的可以在pix2pix的在线演示体验。下面列几个应用例子。 也可以按照自己的意愿直接画图,然后生成图片,先点击图片中的clear, 然后自己画图, 点击process 稍等片刻就能生成对应得实物图。 2.理解pix2pix 还是通过该模型的两个输入网络来直观理解pix2pix. pix2pix 同样是由两个网路组成,生成网络G, 判别网络D, 假设我们现在要将A类型的图片转换成B类型的图片,两个网络的输入输出分别是: G: 输入图片a(A类型), 输出生成的图片G(a) D: 输入图片b, 和一个A类型的图片a, 在a和b项对应得条件下,判断b图片是否是真正的B类型的图片。 要记着D的最终目的就是判断生成的图片是否是B类型的图片(前提是a, b是对应着的,比如画一个男生的素描轮廓(a), 得到一个男生的实物图(B),这就是对应的含义)。 下面是pix2pix 结构图。 先写这么多,希望大家能对pix2pix有个直观的理解,具体的细节请参考原论文。

Redis5.0.0集群搭建-centos7

一.安装redis 1.下载redis 打开redis官网 https://redis.io/ 下载最新版 cd /usr/local/src wget http://download.redis.io/releases/redis-5.0.0.tar.gz 2.编译安装 注意要有gcc环境,没有需要安装 tar -zxvf redis-5.0.0.tar.gz cd redis-5.0.0 make && make install 二.创建节点 创建四个节点测试,复制redis-conf并修改端口 cd /usr/local/ mkdir redis_cluster //创建集群目录 cd redis_cluster mkdir 7000 7001 7002 7003 //分别代表四个节点 其对应端口 7000 7001 7002 7003 cp /usr/local/redis-3.2.1/redis.conf ./redis_cluster/7000/ //拷贝到7001目录 cp /usr/local/redis-3.2.1/redis.conf ./redis_cluster/7001/ //拷贝到7002目录 cp /usr/local/redis-3.2.1/redis.conf ./redis_cluster/7002/ //拷贝到7003目录 cp /usr/local/redis-3.2.1/redis.conf ./redis_cluster/7003/ 分别修改配置文件 daemonize yes //redis后台运行 pidfile /var/run/redis_7000.pid //pidfile文件对应7000,7002,7003,7004 port 7000 //端口7000,7002,7003,7004 cluster-enabled yes //开启集群 把注释#去掉 cluster-config-file nodes_7000.

Flow Field的详解

流场的动机 计算机游戏中的多个AI算法会产生相互矛盾的结果。 AI必须解决这些冲突并找到同时解决方案。 流场的定义 流场是矢量网格在该流场中捕获对运动的一个影响,例如磁吸引力。当你身处流场中,流场会告诉你此时如何向哪个方向走。流场包含一个三维样本空间,在每个点返回一个向量,表示对感兴趣对象的吸引力或远离要避免的对象的排斥。 流场的两个组成部分: 围绕静态对象构建的静态数据集 静态字段是时不变的:对于任何给定的输入向量,它将始终返回相同的输出向量。我们可以将它用作函数:我们给它一个表示位置的(x,y)向量,它返回一个表示速度的(x,y)向量。 围绕动态对象构建的动态生成的数据集 动态场可以随时间变化,以产生给定输入矢量的不同输出矢量。它通常由输入矢量以外的参数控制。 展现流场 存储流场:使用网格存储表示流场状态的数据(向量)采样流场:插值数据点之间的值 双线性插值 双线性插值将在网格点处定义的两个变量的函数插值到两者之间的连续空间。假设函数的值在网格点Q11 =(x1,y1),Q12,Q21和Q22处定义。我们想要找到P =(x,y)点的值。具体的操作步骤如下: (1)X方向的线性插值 (2)Y方向的线性插值 (3)对f(x,y)进行期望估计 混合场 加权加法(+) 将所有组件字段考虑在内,并提供对某些字段进行优先级排序的功能。 条件操作(OR) 允许一个字段完全覆盖其他字段。 场乘积(*) 字段中每个点的缩放值是对另一个字段进行采样的结果 例子 使用流场去创建一个平滑路径 避免碰撞 动态对象避免 ​​​​​​​非镜像径向排斥场 - 中心有死区镜像径向排斥场 - 避免死区横向排斥 Reynolds’s 肿瘤 分离:避免拥挤附近的鱼对齐:转向附近鱼的平均航向凝聚:转向附近成员的平均位置 流场来源 可视化和编辑工具可以用来创建流场。从2-D样本转换为3-D样本刷子可以用来创建一个良好的流场。 

matplotlib绘图,设置坐标格式,比如科学计数法、公式表示等

matplotlib绘图 前言导入必要包未设置坐标格式科学计数表示 前言 绘制实验结果时,很多时候默认设置得到的图形,并不能满足我们的需求。如果我们希望绘制出来的图形更加骚一点,更好看一点,我们怎么做呢。接下来我将介绍绘图时设置横纵坐标的表示方式,包括使用科学计数法和用公式表示方法的。 科学计数表示的纵坐标 导入必要包 导入必要的包,其中FuncFormatter就是设置坐标格式的函数 import seaborn as sns import matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter ### 今天的主角 import numpy as np sns.set_style('whitegrid') ###可以设置白色网格风格使图形更漂亮 未设置坐标格式 下面为未设置坐标格式的代码,我们可以得到相应的实验结果。 A = np.random.randint(10000, 50000, size=(1000)) f, ax = plt.subplots(1, 1) ax.scatter(range(len(A)), A , color='k', label='A', marker='o', s=10) ax.set_xlim([0, 1000]) plt.show() 结果 科学计数表示 下面代码的核心主要在FuncFormatter, 可以看出formatnum包含两个参数,x就是我们的坐标值,pos是位置。return返回的字符串就是我们想要的表示形式。如果了解过latex,可以看出公式的部分主要和latex的表示方式相近,$$钱号里面写我们要表达的格式, $10^{4} $就是我们要的指数表示。 $ .1f% $是系数,其实去除钱号也行,可是会导致字体大小不一样,所以这里就没有去除。 这里只写了y坐标的表示,控制x也一样 A = np.random.randint(10000, 50000, size=(1000)) f, ax = plt.subplots(1, 1) ax.

C - 结构体内存分配

最近又捡起了C语言,遇到了大量对结构体操作的业务,在操作期间,发现对结构体在内存中的分配仍然存有一定的疑问。,经过学习,特把有关结构体内存分配的相关知识记录下来。 内存对齐:要了解结构体的内存分配,首先需要了解内存对齐的概念。之所以会有内存对齐的概念,是因为,在操作系统中,数据的存放时按照字节存放的,而结构体又不像数组,结构体中可以存放不同类型的数据,它的大小也不是简单的各个数据成员大小之和,限于读取内存的要求,而是每个成员在内存中的存储都要按照一定偏移量来存储,根据类型的不同,每个成员都要按照一定的对齐数进行对齐存储,最后整个结构体的大小也要按照一定的对齐数进行对齐。关于具体的概念以及为什么要采用内存对齐的方式可以参考博文:https://blog.csdn.net/Misszhoudandan/article/details/81570548。 下面就结合具体的例子来描述结构体的内存空间是怎么分配的: 1、请看下面的结构体: struct MsgTest { char a; int b; }; MsgTest占多少个字节呢?刚开始我以为是5字节(char 1字节+int 4字节),但实际上是8字节,请看下图: 由上图可以看出,char类型的元素a的起始地址为0x43fd50,而int型元素b的起始地址为0x43fd54,也就是说,系统为元素a总共分配了4个字节的内存(虽然a本身只占用了一个字节长度的内存),剩下的3字节长度的内存就是基于内存对齐的概念进行填充的,不计入操作。 2、接下来看如下的结构体: struct MsgTest { char a; char b; int c; }; 按照上节讲述的原则,那这个结构体所占的内存应该是12字节,但实际上他占了多少个字节呢?请看下图: 这个结构体也是占了8字节。为什么会这样呢,那是因为基于内存对齐的概念,每一个元素应该是按照4字节的标准进行补齐,但是元素a和元素b各占1字节,所以还剩下2字节需要补齐,右上图也可以看出,元素a和元素b的内存只相差了一个字节。实际上,在该结构体中即使是如下样式: struct MsgTest { char a; char b; char c; char d; int e; }; 它所占的内存仍然是8个字节: 3、下面是一些其他格式的结构体: 1): 2): 在该结构体中,a占了4字节,b占了40字节(16进制为28),c占了4字节,d占了8字节,e占了8字节。 3): 可以看一下如下的题目,各位可以先算一下占多少个字节: 需要注意的是,对char*类型的元素,在内存中存放的其实是它的地址(占4字节),_int64类型的占8字节,unsigned其实是unsigned int的简写,也占了4字节。 参看答案如下所示:

String[]与List<String>的区别及相互转换

String[]只能存放String格式数据,而且一般的是固定大小长度的; List指的是集合,<>是泛型,里面存放一个实体类可以是String,int或者自定义的; List<String> list=new List<String>(); String为你想要的对象,里面可以有属性,方法等,这就是面向对象。 而String[]只是存放值而已,不是对象 String[]是数组,定长,不可变 List<String> 是泛型 ,非定长,可变 String[]转List<String> String[] arr = new String[]{"s1","s2","s3"}; List<String> list = Arrays.asList(arr); List<String>转String[] List<String> list = new ArrayList<String>(); list.add("s1"); list.add("s2"); list.add("s3"); String[] arr = list.toArray(new String[list.size()]);

VUE:混入 (mixins)选项的用法

在vue组件内,如果想将一些公共功能,如组件、方法、钩子函数等复用,混入是一个很好的选择。下面简单介绍一下混入的方式及特点。 首先来看看官方文档的介绍: 具体的说,你可以将一个对象作为混入的选项,在组件中复用。因为vue实例也是对象,所以你可以将vue实例作为混入选项传递进去。 组件中的mixins接收一个数组作为值。 <template> <div class="hello"> <h1>{{ msg }}</h1> <h1>{{ form.a }}</h1> <button @click="buttonClick">current</button> </div> </template> <script> import fun from './mixins/methods.vue' // import { constants } from 'http2'; export default { name: "HelloWorld", mixins:[fun], created(){ console.log('这是当前组件') }, data() { return { msg: "Welcome to Your Vue.js App" } }, methods:{ buttonClick(){ console.log(this.form.a) console.log(this.msg) this.clickFn(); this.exm(); }, exm(){ console.log('这是组件的exm方法') } } } </script> 以上代码将一个vue实例作为混入选项。 <script> export default { created(){ console.

lua的异常处理机制

lua中的错误处理主要有几个方法:pcall() ; xpcall() ; error() ; assert() 测试代码如下: --lua异常处理 ------------pcall函数 抛出错误但是程序不会停止 --[[function method2() print(a[2]) end local a,b = pcall(method2) if a then print("函数没有错误") else print("函数有错误") print(b) --打印出错误信息 end]] ----------------xpcall函数 抛出错误但是程序不会停止 --[[function method4() print(a[1]) --输出 报错:attempt to index global 'a' (a nil value) method6 false -- print(2) --输出 2 true end function method6() print("method6") end function method5(err2) print(err2) method6() end local status = xpcall(method4,method5) --当发生错误时,调用第二个参数(一个错误处理函数) print(status) --函数返回true或者false]] ---------------error函数 error(message,level) 遇到错误程序会停止 --[[ function method3() local ming = io.

debug:state machine losing else

state_0 : if( cnt == 7) state_next = state_1; // else state_next = state_0; 此处若losing else 则会发生critical error, 无论cnt是否到7,都会直接跳转到state_1, 从而导致state_0错误。 modelsim仿真并未测试出错误,但FPGA上电实测必然出错。 小心。 正常情况下,state_current是register,state_next只是中间过渡的LUT; 错误情况下,state_next将变成锁存器,LDCE(vivado),严重危害电路时序。

matlab中将RGB图像转化为灰度图像

MyYuanLaiPic = imread('e:/image/matlab/Cluo.jpg');%读取RGB格式的图像 MyFirstGrayPic = rgb2gray(MyYuanLaiPic);%用已有的函数进行RGB到灰度图像的转换 [rows , cols , colors] = size(MyYuanLaiPic);%得到原来图像的矩阵的参数 MidGrayPic = zeros(rows , cols);%用得到的参数创建一个全零的矩阵,这个矩阵用来存储用下面的方法产生的灰度图像 MidGrayPic = uint8(MidGrayPic);%将创建的全零矩阵转化为uint8格式,因为用上面的语句创建之后图像是double型的 for i = 1:rows for j = 1:cols sum = 0; for k = 1:colors sum = sum + MyYuanLaiPic(i , j , k) / 3;%进行转化的关键公式,sum每次都因为后面的数字而不能超过255 end MidGrayPic(i , j) = sum; end end imwrite(MidGrayPic , 'E:/image/matlab/Cluo.png' , 'png'); %显示原来的RGB图像 figure(1); imshow(MyYuanLaiPic); %显示经过系统函数运算过的灰度图像 figure(2); imshow(MyFirstGrayPic); %显示转化之后的灰度图像 figure(3); imshow(MidGrayPic); 运行结果:

matlab查看某一函数功能的几种方法

前沿:本文主要介绍使用help,edit,doc,lookfor来查看某一函数功能的4种方法,其中doc+某一函数命令的方式比较常用。提示:全文以plot函数为例。 首先,启动MATLAB,出现以下命令行窗口(Command Window),工作区(Work Place)等。 方法一: help 使用help+函数命令的方式,查看某一函数的介绍。在命令行窗口输入help plot,便可得到plot函数的有关介绍。 方法二: edit 使用edit+函数命令的方式,查看某一函数的介绍。在命令行窗口输入edit plot,同样得到plot函数的有关介绍,只不过这是查看的plot函数的m文件。 方法三: doc 使用doc+函数命令的方式,查看某一函数的介绍。在命令行窗口输入doc plot,同样得到plot函数的有关介绍,只不过这是通过MATLAB帮助系统(帮助文档)查看的plot函数介绍。 方法四: lookfor 使用lookfor+函数命令的方式,查看某一函数的介绍。在命令行窗口输入lookfor plot,此时将出现所有与plot函数有关的M文件,从中找plot,点击查看plot的介绍。 综上,使用方法三(doc+函数)介绍比较全面。 参考:https://jingyan.baidu.com/article/a378c960e7ece5b328283027.html

IPMI无法执行命令

今天部署IPMI出现设备无法创建,这个问题以前遇到过,大部分是模块没有载入,以下是我排错的步骤: 引用 ipmitool lan print 1 Could not open device at /dev/ipmi0 or /dev/ipmi/0 or /dev/ipmidev/0: No such file or directory Get Channel Info command failed 查看模块是否载入: 引用 [root@25 ~]#lsmod |grep ipmi ipmi_devintf 11973 0 ipmi_si 32317 0 ipmi_msghandler 33317 2 ipmi_devintf,ipmi_si 手动创建设备: 引用 [root@25 ~]#mknod /dev/ipmi0 c cat /proc/devices | grep ipmidev |cut -d " " -f 1 0 再次Print,问题解决!!!! 引用 [root@25 ~]# ipmitool lan print Set in Progress : Set Complete

在一个元素上:hover,改变另一个元素的css属性

如果二者是父子关系,可以写成这种: .face:hover .eye-bottom { margin-top: 30px; } 如果是兄弟关系: .face:hover+.ear-wrap { transform: rotate(-30deg); } 如果是兄弟的儿子: .face:hover+.ear-wrap .ear { transform: rotate(-30deg); } 是用css的选择器来实现的。

vue中通用设置本机IP代替local host

1.查找hosts文件 查找完成过后再hosts文件中进行新增设置 前半部分是本机IP,后半部分是自定义的域名,以后就可以使用你自定义的域名代替本机IP进行使用了 PS:在使用vue-cli的vue项目中的config文件夹中的index.js中设置host为你自定义的域名

深坑之Webview,解决H5调用android相机拍照和录像

最近在开发过程中遇到一个问题,主要是调用第三方的实名认证,需要拍照和录像; 办过支付宝大宝卡和腾讯的大王卡的都知道这玩意,办卡的时候就需要进行实名认证,人脸识别; 本来第三方平台(xxx流量公司)说的是直接用WebView加载这个H5界面就完事了,我心想这么简单,那不是分分钟的事,放着后面做(公司就我一个安卓,所以开发都是我说的算_,独立开发有的时候还是挺爽); 结果到项目快要上线的时候,只想说一句mmp,根本调不了相机,这个时候怎么搞,只有自己去实现了,才发现自己已经进了webview的深坑; 到处找资料,发现webview根本不能让h5自己调用,ios是可以的,项目经理就说是我的锅,真特么又一句mmp(关键是这个H5还特么不能改,不能提供给我调用的方法); 进入正题,首先来了解webview,这里我分享两篇大佬的博客 1,WebView开车指南 2,WebView详解 看完这两篇基本你已经可以随意操作webview了, 但是,当你调用相机的时候你才发现这只是入坑的开始 第一个坑 调用相机之后,文件回调不了,其实根本就是没有回调.这个时候你要去检查你的webview的Settings了关键代码,是否给足了权限; WebSettings settings = webView.getSettings(); settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); settings.setDomStorageEnabled(true); settings.setDefaultTextEncodingName("UTF-8"); settings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true settings.setAllowFileAccess(true); // 是否可访问本地文件,默认值 true // 是否允许通过file url加载的Javascript读取本地文件,默认值 false settings.setAllowFileAccessFromFileURLs(false); // 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false settings.setAllowUniversalAccessFromFileURLs(false); //开启JavaScript支持 settings.setJavaScriptEnabled(true); // 支持缩放 settings.setSupportZoom(true); 其中settings.setDomStorageEnabled(true);这个方法当时我没加,血崩了一次; 第二个坑 WebChromeClient的openFileChooser()只调用了一次 首先了解为什么这个方法只调用了一次,看这篇博客就可 Android开发深入理解WebChromeClient之onShowFileChooser或openFileChooser使用说明 看了他基本你就了解怎么回事了 第三个坑 怎么区分是要调用相机是需要拍照还是录视频 这个时候你就要看WebViewClient的 shouldOverrideUrlLoading()方法了,我是通过拦截url来判断url里面是拍照还是录制视频来加一个flag 这样你调用你的相机的时候就可以分别处理了 第四个坑 android 7.0的FileProvider的坑 看洪阳大佬的这篇博客基本就了解了 Android 7.0 行为变更 通过FileProvider在应用间共享文件吧 最后附上我自己的代码吧 package com.sihaiwanlian.cmccnev.feature.verify.activitys; import android.annotation.TargetApi; import android.

Flask外部访问服务器最简单的操作

Flask 的应用 外部可访问的服务器 如果你运行了这个服务器,你会发现它只能从你自己的计算机上访问,网络中其它任何的地方都不能访问。在调试模式下,用户可以在你的计算机上执行任意 Python 代码。因此,这个行为是默认的。 如果你禁用了 debug 或信任你所在网络的用户,你可以简单修改调用 run() 的方法使你的服务器公开可用,如下: app.run(host='0.0.0.0') 这会让操作系统监听所有公网 IP。 服务器的实例要开启5000端口 公网IP:5000 这样就能在互联网上看到你的网页了!

【MC3】关于Arduino串口Serial的几个常用Method方法列举

1.1 Serial.begin( baud ) 功能为设置端口通信传输速率。【注意接收端的速率】,数据参数单位为波特率(bit per second) 1.2 Serial.end(); 禁止串口传输函数。此时串口传输的pin脚可以作为数字IO脚使用。 1.3 Serial.print() / Serial.println() 通过打印的形式把函数送出。其中,Serial.println() 等价于 Serial.print("\r\n") 需要注意的是:不加说明的情况下,数据以十进制送出Serial.print(x, DEC); 其他尚有 Serial.print(78, BIN) 得到 "1001110" Serial.print(78, OCT) 得到 "116" Serial.print(78, DEC) 得到 "78" Serial.print(78, HEX) 得到 "4E" Serial.print(1.23456, 0) 得到 "1" Serial.print(1.23456, 2) 得到 "1.23" Serial.print(1.23456, 4) 得到 "1.2346" Serial.print('N') 得到 "N" Serial.print("Hello world.") 得到 "Hello world." 1.4 Serial.available() 与 Serial.read() 通常一起工作 Serial.available() 返回值int,数据的个数。无数据,返回 0 。 Serial.read(); 返回串口缓存中第一个可读字节,无数据,返回-1,整数类型。 Serial.available() 的意思是:返回串口缓冲区中当前剩余的字符个数。一般用这个函数来判断串口的缓冲区有无数据,当Serial.available()>0时,说明串口接收到了数据,可以读取;

python HTML格式发送邮件

登录qq邮箱:设置->账户 找到如图片处开启smtp 通过第三方发送邮件都需开启POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务,本人用的qq邮箱进行发送详情请点击http://service.mail.qq.com/cgi-bin/help?subtype=1&no=167&id=28 以下是代码: import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header msg_from = '**********@qq.com' # 发送方邮箱 passwd = 'mizfilyvxaxajgfe' # 填入发送方邮箱的授权码 msg_to = '**************@sina.cn' # 收件人邮箱 # 创建一个带附件的实例 message = MIMEMultipart() message['From'] = Header("冰石头", 'utf-8') message['To'] = Header("收件人名称", 'utf-8') subject = 'Python SMTP 邮件测试' # 主体内容 #subject = unicode(subject)# 更改主题编码 message['Subject'] = Header(subject, 'utf-8') ''' mail_msg = """ <p>冰石头正在进行邮件发送测试...</p> <p><a href="http://blog.csdn.net/zql_1111?ref=toolbar">冰石头</a></p> """ message.

c++ 通过函数获得数组的大小

question ? 怎么样写一个函数返回数组的大小 思考: 1. 因为当把一个数组传入函数的时候, 传入的其实是一个首地址的指针, 所以一般方法不能实现 2. 但是注意到 c++ 虽然不能通过函数参数得到一个数组对象 ,但是 c++ 可以得到" 一个数组的引用" 3. 比如:void arrPreffence(int (&arr)[3]) int (&arr)[3] 就是一个具有三个成员的数组的引用 4. 注意到上面的数组的引用的大小是固定的, 怎么使其一般化 =》 模板函数 5. 那么我们可以得到下面的函数 #include <iostream> using namespace std; ​​​​​​​template<typename T, size_t N> size_t m_rray_size(T(&arr)[N]) { return N; } // 补充问题: stl容器都有一个 begin(), end()来作为迭代使用 // 写 那么 写两个函数 m_begin(数组), m_end(数组)来实现类似功能, 如下 // for(auto x = m_begin(arr); x != m_end(arr); x++) { // // }

实时计算 Flink性能调优

自动配置调优 实时计算 Flink新增自动调优功能autoconf。能够在流作业以及上下游性能达到稳定的前提下,根据您作业的历史运行状况,重新分配各算子资源和并发数,达到优化作业的目的。更多详细说明请您参阅自动配置调优。 首次智能调优 创建一个作业。如何创建作业请参看快速入门。 上线作业。选择智能推荐配置,指定使用CU数为系统默认,不填即可。点击下一步。 数据检查,预估消耗CU数。 在运维界面启动作业,根据实际业务需要指定读取数据时间。 说明:实时计算作业启动时候需要您指定启动时间。实际上就是从源头数据存储的指定时间点开始读取数据。指定读取数据时间需要在作业启动之前。例如,设置启动时间为1小时之前。 待作业稳定运行10分钟后,且以下状态符合要求,即可开始下一次性能调优。 运行信息拓扑图中IN_Q不为100%。 数据输入RPS符合预期。 非首次性能调优 停止>下线作业。 重新上线作业。选择智能推荐配置,指定使用CU数为系统默认,不填即可。点击下一步。 数据检查,再次预估消耗CU数。 在运维界面启动作业,待作业稳定运行十分钟后,即可再一次性能调优。 说明: 自动配置调优一般需要3到5次才能达到理想的调优效果。请完成首次性能调优后,重复非首次性能调优过程多次。每次调优前,请确保足够的作业运行时长,建议10分钟以上。指定CU数(参考值) = 实际消耗CU数*目标RPS/当前RPS。 实际消耗CU数:上一次作业运行时实际消耗CU目标RPS:输入流数据的实际RPS(或QPS)当前RPS:上一次作业运行时实际的输入RPS 手动配置调优 手动配置调优可以分以下三个类型。 资源调优作业参数调优上下游参数调优 资源调优 资源调优即是对作业中的Operator的并发数(parallelism)、CPU(core)、堆内存(heap_memory)等参数进行调优。 分析定位资源调优节点 定位性能瓶颈节点 性能瓶颈节点为Vertex拓扑图最下游中参数IN_Q值为100%的一个或者多个节点。如下图,7号节点为性能瓶颈节点。 分析性能瓶颈因素 性能瓶颈的可分为三类。 并发(parallelism)不足CPU(core)不足MEM(heap_memory)不足 如下图,7号节点的性能瓶颈是资源(CPU和/或MEM)配置不足所导致。 说明:判断性能瓶颈因素方法 瓶颈节点的资源健康分为100,则认为资源已经合理分配,性能瓶颈是并发数不足所导致。瓶颈节点的资源健康分低于100,则认为性能瓶颈是单个并发的资源(CPU和/或MEM)配置不足所导致。无持续反压,但资源健康分低于100,仅表明单个并发的资源使用率较高,但暂不影响作业性能,可暂不做调优。 通过作业运维页面中Metrics Graph功能,进一步判断性能瓶颈是CPU不足还是MEM不足。步骤如下。 运维界面中,点击TaskExecutor,找到性能瓶颈节点ID,点击查看详情。 选择Metrics Graph,根据曲线图判断CPU或者MEM是否配置不足(很多情况下两者同时不足)。 调整资源配置 完成了性能瓶颈因素判断后,点击开发>基本属性>跳转到新窗口配置,开始调整资源配置。 批量修改Operator 点击GROUP框,进入批量修改Operator数据窗口。 说明: GROUP内所有的operator具有相同的并发数。GROUP的core为所有operator的最大值。GROUP的_memory为所有operator之和。建议单个Job维度的CPU:MEM=1:4,即1个核对应4G内存。 配置修改完成后点击应用当前配置并关闭窗口。 单个修改Operator 点击Operator框,进入修改Operator数据窗口。 配置修改完成后点击应用当前配置并关闭窗口。 参数调整说明 您只需调整parallelism、core和heap_memory三个参数,即能满足大部分的资源调优需求。 Parallelism source节点 资源根据上游Partition数来。例如source的个数是16,那么source的并发可以配置为16、8、4等。不能超过16。中间节点 根据预估的QPS计算。对于数据量较小的任务,设置和source相同的并发度。QPS高的任务,可以配置更大的并发数,例如64、128、或者256。sink节点 并发度和下游存储的Partition数相关,一般是下游Partition个数的2~3倍。如果配置太大会导致数据写入超时或失败。例如,下游sink的个数是16,那么sink的并发最大可以配置48。Core 即CPU,根据实际CPU使用比例配置,建议配置值为0.25,可大于1。Heap_memory 堆内存。根据实际内存使用状况进行配置。其他参数 state_size:默认为0,group by、join、over、window等operator需设置为1。direct_memory:JVM堆外内存,默认值为0, 建议不要修改。native_memory:JVM堆外内存,默认值为0,建议修改为10MB。chainingStrategy:chain策略,根据实际需要修改。 作业参数调优 在开发页面的右侧选择作业参数。 输入调优语句。 优化解决问题调优语句MiniBatch提升吞吐,降低对下游压力仅对Group by有效。 blink.miniBatch.allowLatencyMs=5000

梯度下降算法过程详细解读

看了很多博文,一谈到梯度下降,大多都在画图,类比“下山”。对于一开始想要了解“梯度下降”是个什么玩意儿时,这种类比法是非常有助于理解的。但是,当我大概知道了梯度下降是什么东西之后,我就好奇了,梯度下降究竟是怎样寻找到模型的最优参数的?不能一想到梯度下降,脑海中就只有“下山”的画面,“下山”不是目的,目的在于“下山”的过程中确立参数。下面就简单概述一下,梯度下降过程是如何一步一步寻找到模型的最优参数。 1.梯度下降相关概念: 假设函数(hypothesis function): 所谓假设函数,就是监督学习中,我们拟合样本特征映射到目标变量的函数,记为 hθ(x),θ为函数的参数。例如,一个简单的线性回归拟合函数可以表示为:hθ(x) = θ0 + θ1·x; 损失函数(loss function): 又称为代价函数。通常用损失函数来度量拟合的程度,从而评估模型拟合的好坏,记为 J(θ)。注意,损失函数是关于 θ 的函数!也就是说,对于损失函数来讲,θ不再是函数的参数,而是损失函数的自变量!例如,对于线性回归的损失函数可以表示为: J(θ) = 1/(2 *n) * ∑ ( hθ(xi) − yi )2 其中 n 表示样本数量, xi 表示第 i 个样本特征,yi 表示第 i 个样本对应的目标变量的真实值, hθ(xi) 为假设函数。 当我们计算损失时,是将每个样本中的特征 xi 和对应的目标变量真实值 yi 带入损失函数,此时,损失函数中就只剩下 θ 是未知的。 例如,我们的假设函数为: hθ(x) = θ0 + θ1·x1 + θ2·x22 ,其中一个样本为 x1 = (1,2),对应的目标变量 y1= 10。将x1 和y1 带入损失函数,则对于该样本 x1 拟合的损失表示为: θ0 + θ1 + 4*θ2 -10 ;此时,损失函数就是关于θ 的函数了。 每一个样本都会有一个拟合损失,将所有样本的损失相加,就是整个样本集的拟合损失。

Python之OpenCV读取视频抽帧保存

=================== 20200701更新 ======================= # -*- coding:utf8 -*- import cv2 import os import shutil def get_frame_from_video(video_name, interval): """ Args: video_name:输入视频名字 interval: 保存图片的帧率间隔 Returns: """ # 保存图片的路径 save_path = video_name.split('.mp4')[0] + '/' is_exists = os.path.exists(save_path) if not is_exists: os.makedirs(save_path) print('path of %s is build' % save_path) else: shutil.rmtree(save_path) os.makedirs(save_path) print('path of %s already exist and rebuild' % save_path) # 开始读视频 video_capture = cv2.VideoCapture(video_name) i = 0 j = 0 while True: success, frame = video_capture.

日志中获取request中请求参数(url参数和body参数)------post获取请求body(二)

1.创建自定义过滤器 import com.jdcloud.apim.openapi.util.RequestWrapper; import org.springframework.core.annotation.Order; import javax.servlet.*; import java.io.IOException; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; //将过滤器注册到springboot的启动项中,顺序为第一个。这里有两种方法 //方法一:通过注解的方式 @Order(1) @WebFilter(filterName = "httpServletRequestFilter", urlPatterns = "/*") public class RequestReplacedFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ServletRequest requestWrapper = null; // logger.debug("复制request.getInputStream流"); if (request instanceof HttpServletRequest) { requestWrapper = new RequestWrapper((HttpServletRequest) request); } //获取request请求中的流,将取出来的字符串保存在缓存中,同时再将该字符串再次转换成流,然后把它放入到新request对象中。 if (requestWrapper == null) { chain.

为什么复制构造函数的参数必须是引用类型?

如果一个函数是通过值传递(pass by value)的话,那么它真正传递的其实是实参的副本,该副本产生必定会调用复制构造函数。那么,试想一下,如果我们的复制构造函数是通过值传递的话,它就会调用它本身来产生一个副本,就这样会无限递归下去,而如果传递引用,就不会产生副本,也不会调用复制构造函数,问题得以解决。

Android调用C++实现共享内存(Native层)

Android下匿名共享内存java层接口利用MemoryFile实现进程间内存共享;利用MemoryFile可以参考这篇文章:https://blog.csdn.net/qq_24451593/article/details/80514566 MemoryFile是java层封装的接口,它实现共享内存主要调用了如下函数: int fd = open("/dev/ashmem",O_RDWR); ioctl(fd, ASHMEM_SET_NAME,name); ioctl(fd,ASHMEM_SET_SIZE, size); //addr为共享内存地址 addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 创建出来的fd转换成ParcelFileDescriptor通过AIDL传递给另一个进程;另一个进程将ParcelFileDescriptor转换成该进程对应fd,调用mmap来使用该共享内存。 注:进程A的fd与进程B的fd是不一样的,但是都对应同一文件 既然知道了MemoryFile实际调用函数,那么我们就可以在native层用C++代码实现共享内存。 (1)C++代码实现 android_shm.cpp #include "android_shm.h" #define ASHMEM_DEVICE "/dev/ashmem" //ret= 0 创建成功;ret=-1,失败; //注:ret =1,共享内存已经存在,但是目前这个没用,暂时放这 int create_shared_memory(const char* name, U64 size, int node, char*& addr, U64& shm_id){ U64 fd = open(ASHMEM_DEVICE, O_RDWR); if(fd < 0){ return -1; } U64 len = ioctl(fd, ASHMEM_GET_SIZE, NULL); if(len > 0){ addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); shm_id = fd; return 1; }else{ int ret = ioctl(fd, ASHMEM_SET_NAME,name); if(ret < 0){ close(fd); return -1; } ret = ioctl(fd,ASHMEM_SET_SIZE, size); if(ret < 0){ close(fd); return -1; } addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); shm_id = fd; } return 0; } int open_shared_memory(const char* name, int node, char*& addr, U64& shm_id){ U64 size = ioctl(shm_id, ASHMEM_GET_SIZE,NULL); if(size > 0){ addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0); }else{ return -1; } return 0; } int close_shared_memory(U64& shm_id, char*& addr){ U64 size = ioctl(shm_id, ASHMEM_GET_SIZE, NULL); if(size <0){ return -1; } int ret = munmap((void*)addr, size); if(ret == -1){ return -1; } ret = close(shm_id); if(ret == -1){ return -1; } return 0; } android_shm.

Angular——cannot read property 'style' of null at....

前言 小编最近在用angular组件的ts中控制界面模块显示的时候遇到了这个问题,如下图 这个问题的原因是因为没有正确的获取模块的id,可以直接从报错这点过去,直接看到是哪里的问题,点击红线就可以了,如下 跳转到这个位置 经查看,是id名字的原因,问题解决 总结 不怕不知道,就怕不知道,路还长,得走稳点。

服务器配置个人总结

记录配置服务器的经历 2018-11-3 因项目对服务器的要求,尝试了移动,电信,云服务器的搭建,并测试,选择云服务器。 服务器版本是 Windows2012版,X86系统,mysql56,jdk1.8,tomcat8; 1.远程连接服务器,输入IP和密码; 2.拿到的服务器是已经安装好mysql的,所以不需要安卓mysql。 3.安装jdk,自定义文件夹,我放到了D盘根目录,D:\jdk ,D:\jre; 4.安装tomcat,用exe程序选择jre安装; 5.在tomcat/bin/startup.bat 和tomcat/bin/startdown.bat 文件中配置jdk路径和tomcat 路径 (SET JAVA_HOME=D:\jdk SET TOMCAT_HOME=D:\apache\apache-tomcat-7.0.59),这样再启动tomcat时就不会出现闪退情况; 6.把项目移动到tomcat/webapps/test 下面,配置tomcat/conf/server.xml 文件,默认localhost。 7.云服务器解析域名,添加一条记录,记录值为当前服务器的IP,先在本地 ping IP,ping通则域名解析正确。 8.在conf/server.xml 配置域名,改变端口号为80,在<Host name="localhost" appBase="webapps".../> 下面添加 <Host name="解析的域名" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context docBase="项目在webapps下的路径" path="" reloadable="true" > </Context> <Alias>解析的域名</Alias> </Host> 9.打开浏览器使用域名访问,如果显示无法连接,查看防火墙是否启用,关闭防火墙,即可使用域名访问项目。 10.为了配置时方便,我使用了Notepad++,数据库管理工具使用 navicat ;

正定矩阵与半正定矩阵定义与判别

1.正定矩阵和半正定矩阵 若所有特征值均大于零,则称为正定。 定义:A是n阶方阵,如果对任何非零向量x,都有>0,其中表示x的转置,就称A为正定矩阵。 性质: 正定矩阵的行列式恒为正;实对称矩阵AA正定当且仅当AA与单位矩阵合同;两个正定矩阵的和是正定矩阵;正实数与正定矩阵的乘积是正定矩阵。 根据正定矩阵的定义及性质,判别对称矩阵A的正定性有两种方法: 求出A的所有特征值。若A的特征值均为正数,则A是正定的;若A的特征值均为负数,则A为负定的。 计算A的各阶顺序主子式。若A的各阶顺序主子式均大于零,则A是正定的;若A的各阶顺序主子式中,奇数阶主子式为负,偶数阶为正,则A为负定的。 2.半正定矩阵 若所有特征值均不小于零,则称为半正定。 定义:设A是实对称矩阵。如果对任意的实非零列向量x有≥0,就称A为半正定矩阵。 对于半正定矩阵来说,相应的条件应改为所有的主子式非负。顺序主子式非负并不能推出矩阵是半正定的。 性质: 半正定矩阵的行列式是非负的;两个半正定矩阵的和是半正定的;非负实数与半正定矩阵的数乘矩阵是半正定的。

如何用cin读入空格

在我们使用cin读入字符时,默认是跳过中间的空格以及可能的制表符和换行符,那么,如何让其不跳过空格呢。我们可以使用操作符noskipws来实现。 cin>>noskipws;//设置cin读取空白符; char ch; while(cin) cout<<ch; cin>>skipws; //恢复默认状态。 这样,程序就会读取空格了。

CentOS7上部署.Net Core项目

1. 安装CentOS https://www.baidu.com/ 百度解决 2. 安装.Net Core Sdk 2.1 添加.NET相关 为了安装.NET,需要注册微软签名密钥和添加微软相关的支持。这个操作每台机器只能做一次。 打开命令行,输出以下命令,注册Microsoft需要的依赖环境;: sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh -c 'echo -e "[packages-microsoft-com-prod]\nname=packages-microsoft-com-prod \nbaseurl=https://packages.microsoft.com/yumrepos/microsoft-rhel7.3-prod\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc">/etc/yum.repos.d/dotnetdev.repo' 2.2 安装.NET SDK ①更新可用的安装包:sudo yum update ②安装.NET需要的组件,libunwind和libicu库:sudo yum install libunwind libicu ③安装.NET SDK(ps:我的开发环境是2.1.403,cmd:dotnet –version查看): sudo yum install dotnet-sdk-2.1.4 ④安装完成之后,检测是否安装成功(ps:上面命令会默认安装2.1.4开头的最新版): dotnet --version 3.使用VS2017发布ASP.NET Core MVC程序 4.部署ASP.NET Core 应用程序到CentOS服务器 将发布的文件夹传输到服务器,我这里用的是xftp(也可以用FileZilla等其他的ftp工具) 将发布的文件夹传输到服务器你想放的位置 5. 安装配置Nginx进行反向代理 5.1安装Nginx ①使用如下命令安装CentOS的 EPEL仓库:yum install epel-release ②使用如下命令安装Nginx:yum install nginx ③Nginx安装完成后, 系统并不会启动Nginx, 使用如下命令启动Nginx: systemctl start nginx ④使用如下命令设置系统启动后, 默认启动Nginx: systemctl enable nginx

js 获取n位随机数

一、n位Number类型的随机数 function randomn(n) { if (n > 21) return null return parseInt((Math.random() + 1) * Math.pow(10,n-1)) } 二、n位String类型的数字随机数 // RegExp(pattern, attributes)attributes-gim(全局匹配、区分大小写的匹配、多行匹配) function randomn(n) { if (n > 21) return null var re =new RegExp("(\\d{" + n + "})(\\.|$)") var num = (Array(n-1).join(0) + Math.pow(10,n) * Math.random()).match(re)[1] return num // Array(n > num ? (n - ('' + num).length +1) : 0).join(0) + num 补位 } 三、n位字母数字随机数 function randomn(n) { let res = '' for (; res.

数据结构(八)平衡二叉树

文章目录 平衡二叉树0. 为何要使用AVL树?1. 定义2. 平衡二叉树的调整0. 遵循原则1. RR 单旋2. LL 单旋3. LR 双旋4. RL 双旋 练手题 平衡二叉树 0. 为何要使用AVL树? 二叉搜索树的搜索效率与其树的深度相关,而二叉搜索树的组成又与其插入序列相关,在极端情况下,二叉搜索树退化为一条单链(比如插入序列是 1 2 3 … n),使得搜索效率大大降低,为了避免这种情况出现,我们采用二叉平衡树对插入结点进行调整,使得树的深度尽可能小 1. 定义 平衡因子 BF(T) = h L _L L​ - h R _R R​,其中 h L _L L​、h R _R R​ 分别是左右子树的高度平衡二叉树(AVL 树) 空树,或者任一结点左、右子树高度差的绝对值不超过 1,即 |BF(T)|≤1 的树 2. 平衡二叉树的调整 0. 遵循原则 从离插入结点最近的结点调整 1. RR 单旋 当"插入结点"(BR)是"被破坏平衡结点"(A)右子树的右子树时,即 RR 插入时,采用 RR 旋转调整 其基本思路是把 B 的左子树腾出来挂到 A 的右子树上,返回 B 作为当前子树的根

javax.persistence.EntityManager 用法

javax.persistence.EntityManager 是一个PA接口 发布 接口EntityManager 接口用于与持久化上下文交互。 一个EntityManager实例与持久化上下文相关的。一个持久化上下文是一组中的实体实例的任何持久的实体的身份有一个独特的实体实例。在持久性上下文中,实体实例及其生命周期管理。这个EntityManagerAPI是用于创建和删除持久的实体实例,根据主键找到实体,并查询实体。 实体可以通过一个给定的管理设置EntityManager实例是由一个存储单元定义。一个存储单元定义的所有类相关或由应用程序分组设置,且必须放在他们的映射到一个数据库。 如: public class UserServiceImpl implements UserService { @PersistenceContext private EntityManager entityManager; public List<GrantedAuthority> getAuthoritiesByUserId(Long userId) { List<GrantedAuthority> gaList = new ArrayList<GrantedAuthority>(); String sql = "select distinct ra.authority as 'authority' from user_role ur,role r,role_authority ra where ur.roles_id=r.id and r.id=ra.role_id and ur.users_id="+userId; Query query = entityManager.createNativeQuery(sql); List<String> authorityList = query.getResultList(); for(String authority:authorityList){ gaList.add(new GrantedAuthorityImpl(authority)); } return gaList; } private void testEntityManager(){ Query query = entityManager.

继承jpa Repository 写自定义方法查询

今天在写jpa查询的时候,遇到了添加自定义方法,项目启动报错原因,现总结如下: 首先定义实体类 @Entity @Table(name = "user") Class User{ @Id @GeneratedValue int id; @Column String age; @Column String school; @Column String userName; set,get方法 (省略) } public interface UserRepository extends JpaRepository<User, Long> { List<User> findByUsernameLike(String username); List<User> aaa(); } 启动项目时,项目报错提示信息为:org.springframework.data.mapping.PropertyReferenceException: No property aaa found for type com.fpi.safety.common.entity.po.User 再将List<User> aaa();方法去掉后,项目又可以正常启动运行 是什么原因呢? 经查找,原来是继承jpa,必须满足一些规则,规则如下 Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find,findBy,read,readBy,get,getBy,然后对剩下的部分进行解析。 假如创建如下的查询:findByUserName(),框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,假设查询实体为User 1:先判断userName(根据POJO规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步; 2:从右往左截取第一个大写字母开头的字符串此处是Name),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设用户为查询实体的一个属性; 3:接着处理剩下部分(UserName),先判断用户所对应的类型是否有userName属性,如果有,则表示该方法最终是根据“User.userName”的取值进行查询;否则继续按照步骤2的规则从右往左截取,最终表示根据“User.userName”的值进行查询。 4:可能会存在一种特殊情况,比如User包含一个的属性,也有一个userNameChange属性,此时会存在混合。可以明确在属性之间加上“_”以显式表达意思,比如“findByUser_NameChange )“或者”findByUserName_Change()“ 从上面,我们可以得知,jap在解析是,aaa在user类中是没有属性的,所以报错No property aaa found. 如果我们想要使用jap框架,又不想再多增加一个自定义类,则必须符合其命名规则 如果,你记不住jpa的规则也没关系,你可以自己再多写一个类来实现自定义查询方法 如下: . 自定义一个接口,该接口用来声明自己额外定义的查询。 public interface UseerRepositoryTwo {

Redis 笔记

Redis nosql数据库支持分布式 string 、list 、set 、sorted set 、hash 其他机器访问本机Redis服务器 修改本机IP为共同IP 删除 del key 设置过期时间 expire key timeout(单位为妙) 查看过期时间 ttl key 查看当前Redis中的所有key keys * 列表操作 lpush 插入列表左边 rpush 插入列表右边 lrange key start stop 返回列表key中指定区间的 元素,区间以偏移 lpop key 从最左边弹出一个元素 rpop key 从最右边弹出一个元素 lrem key count value 删除指定个数的key lindex key index 指定返回第几个元素 llen key 获取列表中的元素个数 集合操作 sadd team 1 添加元素 smembers set 查看元素 srem set member 移除元素 scard set 查看元素个数 sinter set1 set2 获取两个集合的交集

Python 笔记

MongoDB概念介绍 三元素:数据库,集合,文档 多线程 线程相当于车厢,进程相当于火车 threading模块 threading.tread(target=方法名) 查看多少个线程 threading.enumerate() 查看当前线程的名字 threading.current_thread() 通常书写方法是继承threading.thread类 共享全局变量,需要使用global指定 创建锁 glock=threading.lock() 上锁 glock.acquire() 释放锁 glock.release() 会修改的值需要加锁 condition锁 threading.condition notify通知正在等待的线程 默认第一个 notify_all通知所有线程 queue线程安全队列 Queue先进先出队列 put 加数据,如果满了,会一直阻塞 qsize 队列大学 empty 是否为空 full 是否满了 get 获取一个数据,如果队列里没有值,会一直 阻塞 gil全局解释器锁 ajax页面抓取 ajax异步的js和xml selenium常用操作 driver.close()关闭当前页面 driver.quit()关闭浏览器 find_element_by_id 根据id查找某个元素 find_element_by_class_name g根据类名查找元素 find_element_by_name 根据name属性的值查找元素 find_element_by_tag_name 根据标签名来查找 元素 find_element_by_xpath 根据xpath语法来获取元素 上述都是选择一个标签,多个为elements 如果只数据,那么推荐奖网页源代码扔给是想要解 析网页中的lxml来解析。因为lxml底层使用的是c语 言,所有解析效率会更高 如果是想要对元素进行一些操作,比如给一个文本 框输入值,或者是点击某个按钮,那么就必须使用 selenium给我们提供的查找元素的方法。 cookie操作 获取所有的cookie信息 driver.get_cookie() 根据cookie的key获取value driver.driver.get_cookie(key) 删除所有的cookie driver.delete_all_cookie() 删除某个cookie

IDEA Git 合并分支的部分提交到主干

在开发过程中不同需求迭代上线时我们需要在不同分支上开发。当某个分子的部分功能需要临时上线时,我们就要合并分支的部分代码带主干,这种情况应该如何实现呢? 我们需要用到Git的Cherry-pick功能 IDEA中使用Git的Cherry-pick功能合并分支的部分提交到主干 先将代码切换到主干-》右击项目-》Git-》Repository-》Merge Changes-》选择No commit-》Merge 右击项目-》git-》Show History-》在任意一个提交历史上右击-》Select in Git Log-》右击要合并的提交-》Cherry-Pick-》提交 以上操作就是合并分支部分代码到主干的过程。

Exception in thread "main" java.lang.NoClassDefFoundError: XXX

Exception in thread "main" java.lang.NoClassDefFoundError: XXX编译时没有报错,一运行就不听话 网上找了一大堆,各种解决方案都不是适合我,但是一片文章列举出了可能产生的原因 https://blog.csdn.net/q542441... 看了包肯定是有的,环境变量配置看了好几遍也没错,代码写的也没啥问题, 最后在控制台点开(原来这里还能点开,身为小菜的我大开眼界) 搜了一下这几个包的路径,发现引用包的路径是这个样子的:xx/D:/xx, 这个D:明显是windows下的,而我用的是mac(似乎发现问题的我抑制住内心的澎湃),用mac配置环境变量的小伙伴都是知道:mac里冒号是环境变量里路径的分割,当包本身的路径中有:时候,运行的时候,去环境变量里找,遇到D:就分割了,仓库路径就错了。所以我赶快上网搜了一下idea怎么看maven的setting.xml文件...(file->other setting->default setting->build,xxx->maven) 我先改了上图的Local repository, 重新pom了我要的包,然而并没有什么用,发现还是xx/D:/xx这样的路径,那就看看这个setting.xml文件暗藏啥玄机吧,赶紧在文件中搜了D: 哈哈原来在localRepository这里配置的本地仓库路径有个D:(这是同事拷给我的,我啥也不懂直接就用了),删掉D:,把之前没用xx/D:/xx的也删掉,重新引用下,运行起来就好了

Python--遍历列表时删除元素的正确做法

一.问题描述 这是在工作中遇到的一段代码,原理大概和下面类似(判断某一个元素是否符合要求,不符合删除该元素,最后得到符合要求的列表): a = [1,2,3,4,5,6,7,8] for i in a: if i>5: pass else: a.remove(i) print(a) 运行结果: 二.问题分析 因为删除元素后,整个列表的元素会往前移动,而i却是在最初就已经确定了,是不断增大的,所以并不能得到想要的结果。 三.解决方法 1.遍历在新的列表操作,删除是在原来的列表操作 a = [1,2,3,4,5,6,7,8] print(id(a)) print(id(a[:])) for i in a[:]: if i>5: pass else: a.remove(i) print(a) print('-------------------------') print(id(a)) 运行结果: 2.filter 内建函数filter()官方文档参考:https://docs.python.org/3/library/functions.html#filter a = [1,2,3,4,5,6,7,8] b = filter(lambda x: x>5,a) print(list(b)) 运行结果: 3.列表解析 a = [1,2,3,4,5,6,7,8] b = [i for i in a if i >5] print(b) 运行结果: 4.倒序删除 因为列表总是“向前移”,所以可以倒序遍历,即使后面的元素被修改了,还没有被遍历的元素和其坐标还是保持不变的。 a = [1,2,3,4,5,6,7,8] print(id(a)) for i in range(len(a)-1,-1,-1): if a[i] > 5: pass else: a.

zoj 3543 E - Number String

链接:https://cn.vjudge.net/contest/264706#problem/E 思路:很容易就可以想到dp来做,一开始想到的是用dp[ i ][ j ] 表示长度为i 末尾元素为j 的序列,但是其实可以发现这样表示根本就没有办法向下推。然后就gg 了,其实这个题 dp[ i ][ j ] 表示的是长度为 i 末尾元素为 j 的(1到 i )的符合条件的全排列方式,这样就可以完全保证 没有用到重复的元素。 这样递推的话,如果是I 那么我就找比前一位比j 小的所有方案加和。如果是D 那么我就找前一位>=j&&<=i-1的方案加和。 推荐一篇博客: https://blog.csdn.net/a497406594/article/details/38317993 代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod= 1e9+7; char str[1010]; ll dp[1005][1005]; int main(){ while(~scanf("%s",str+2)){ int len=strlen(str+2)+1; for(int i=0;i<=len+2;i++) { for(int j=0;j<=len+2;j++) { dp[i][j]=0; } } dp[1][1]=1; for(int i=2;i<=len;i++){ if(str[i]=='I'||str[i]=='?') { ll ss=0; for(int j=1;j<=i;j++) { dp[i][j]=(dp[i][j]+ss)%mod; ss=(ss+dp[i-1][j])%mod; } } if(str[i]=='D'||str[i]=='?

小白学Linux——实践2(开机启动)

vsftpd服务自启动的三种方法 linux系统ftp工具是必备软件,vsfpt是诸多ftp工具中最受站长欢迎,使用非常方便的工具之一。我们都不想系统重启或者某些原因导致FTP不能正常工作,那么将VSFTP加入开机启动是非常必要的。vsftpd有两种启动方式 自启动或者由xinetd服务启动,修改配置文件中的listen可以设置启动方式 listen=YES则为自启动,NO则由xinetd启动。需要注意的是,采用自启动的方式命令:/usr/local/sbin/vsftpd启动后当前终端会被占据。永久打开或则关闭使用下面命令即可: chkconfig iptables on chkconfig iptables off 即时生效:重启后还原 service iptables start service iptables stop 上面那个只是终端显示方式,下面开始正题,开机默认VSFTP服务自动启动: 方法一-常用方便的方法 [root@localhost /]# chkconfig --list|grep vsftpd vsftpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off 上面显示vsftpd 在linux任何工作等级下都没有自启动 [root@localhost /]# chkconfig vsftpd on 上面这条命令设置vsftpd自启动 [root@localhost /]# chkconfig --list|grep vsftpd vsftpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off 上面显示表明vsftpd在Linux工作2,3,4,5等级下都会自启动服务。 方法二- 修改rc.local文件1: 修改文件 /etc/rc.local , 把行/usr/local/sbin/vsftpd & 插入文件中,以实现开机自动启动。 方法三-修改rc.local文件2: 修改/etc/rc.local,加入/etc/rc.d/init.d/vsftpd start 上面就是为大家介绍的linux中vsftpd自启动(开机启动)的三种方法,希望对大家有帮助

小白学Linux——实践1(在Linux中有7种启动级别)

在Linux中有7种启动级别: 修改文件/etc/inittab。 修改系统启动级别:修改系统默认启动到3多用户状态,在Linux中有7种启动级别,默认是X-Window,像是Windows的窗口模式,而Linux的操作和配置一般都采用输入命令的方式来完成,需要更改默认启动级别才可以实现。 第1步:以管理员身份进入Linux,修改文件:/etc/inittab文件。 第2步:找到“id:5:initdefault:”,其中的5就是X-Window,为默认运行级别,把5改为3即可。 7总运行级别介绍如下: 0 - halt (Do NOT set initdefault to this) 1 - Single user mode 2 - Multiuser, without NFS (The same as 3, if you do not have networking) 3 - Full multiuser mode 4 - unused 5 - X11 6 - reboot (Do NOT set initdefault to this) 各个运行级的详细解释: 0 为停机,机器关闭。 1 为单用户模式,就像Win9x下的安全模式类似。 2 为多用户模式,但是没有NFS支持。 3 为完整的多用户模式,是标准的运行级。 4 一般不用,在一些特殊情况下可以用它来做一些事情。例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置。 5 就是X11,进到X Window系统了。

小白学习Linux ——理论2(vi命令)

vi命令 vi命令是UNIX操作系统和类UNIX操作系统中最通用的全屏幕纯文本编辑器。Linux中的vi编辑器叫vim,它是vi的增强版(vi Improved),与vi编辑器完全兼容,而且实现了很多增强功能。 vi编辑器支持编辑模式和命令模式,编辑模式下可以完成文本的编辑功能,命令模式下可以完成对文件的操作命令,要正确使用vi编辑器就必须熟练掌握着两种模式的切换。默认情况下,打开vi编辑器后自动进入命令模式。 从编辑模式切换到命令模式使用“esc”键,从命令模式切换到编辑模式使用“A”、“a”、“O”、“o”、“I”、“i”键。 vi编辑器提供了丰富的内置命令,有些内置命令使用键盘组合键即可完成,有些内置命令则需要以冒号“:”开头输入。常用内置命令如下: Ctrl+u:向文件首翻半屏; Ctrl+d:向文件尾翻半屏; Ctrl+f:向文件尾翻一屏; Ctrl+b:向文件首翻一屏; Esc:从编辑模式切换到命令模式; ZZ:命令模式下保存当前文件所做的修改后退出vi; :行号:光标跳转到指定行的行首; ?:光标跳转到最后一行的行首; x或X:删除一个字符,x删除光标后的,而X删除光标前的; D:删除从当前光标到光标所在行尾的全部字符; dd:删除光标行正行内容; ndd:删除当前行及其后n-1行; nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字; p:粘贴文本操作,用于将缓存区的内容粘贴到当前光标所在位置的下方; P:粘贴文本操作,用于将缓存区的内容粘贴到当前光标所在位置的上方; /字符串:文本查找操作,用于从当前光标所在位置开始向文件尾部查找指定字符串的内容,查找的字符串会被加亮显示; ?name:文本查找操作,用于从当前光标所在位置开始向文件头部查找指定字符串的内容,查找的字符串会被加亮显示; a,bs/F/T:替换文本操作,用于在第a行到第b行之间,将F字符串换成T字符串。其中,“s/”表示进行替换操作; a:在当前字符后添加文本; A:在行末添加文本; i:在当前字符前插入文本; I:在行首插入文本; o:在当前行后面插入一空行; O:在当前行前面插入一空行; :wq:在命令模式下,执行存盘退出操作; :w:在命令模式下,执行存盘操作; :w!:在命令模式下,执行强制存盘操作; :q:在命令模式下,执行退出vi操作; :q!:在命令模式下,执行强制退出vi操作; :e文件名:在命令模式下,打开并编辑指定名称的文件; :n:在命令模式下,如果同时打开多个文件,则继续编辑下一个文件; :f:在命令模式下,用于显示当前的文件名、光标所在行的行号以及显示比例; :set number:在命令模式下,用于在最左端显示行号; :set nonumber:在命令模式下,用于在最左端不显示行号; 语法 vi(选项)(参数) 选项 +<行号>:从指定行号的行开始先是文本内容; -b:以二进制模式打开文件,用于编辑二进制文件和可执行文件; -c<指令>:在完成对第一个文件编辑任务后,执行给出的指令; -d:以diff模式打开文件,当多个文件编辑时,显示文件差异部分; -l:使用lisp模式,打开“lisp”和“showmatch”; -m:取消写文件功能,重设“write”选项; -M:关闭修改功能; -n:不实用缓存功能; -o<文件数目>:指定同时打开指定数目的文件; -R:以只读方式打开文件; -s:安静模式,不现实指令的任何错误信息。 参数 文件列表:指定要编辑的文件列表。多个文件之间使用空格分隔开。 知识扩展 vi编辑器有三种工作方式:命令方式、输入方式和ex转义方式。通过相应的命令或操作,在这三种工作方式之间可以进行转换。 命令方式 在Shell提示符后输入命令vi,进入vi编辑器,并处于vi的命令方式。此时,从键盘上输入的任何字符都被作为编辑命令来解释,例如,a(append)表示附加命令,i(insert)表示插入命令,x表示删除字符命令等。如果输入的字符不是vi的合法命令,则机器发出“报警声”,光标不移动。另外,在命令方式下输入的字符(即vi命令)并不在屏幕上显示出来,例如,输入i,屏幕上并无变化,但通过执行i命令,编辑器的工作方式却发生变化:由命令方式变为输入方式。 输入方式 通过输入vi的插入命令(i)、附加命令(a)、打开命令(o)、替换命令(s)、修改命令(c)或取代命令(r)可以从命令方式进入输入方式。在输入方式下,从键盘上输入的所有字符都被插入到正在编辑的缓冲区中,被当做该文件的正文。进入输入方式后,输入的可见字符都在屏幕上显示出来,而编辑命令不再起作用,仅作为普通字母出现。例如,在命令方式下输入字母i,进到输入方式,然后再输入i,就在屏幕上相应光标处添加一个字母i。 由输入方式回到命令方式的办法是按下Esc键。如果已在命令方式下,那么按下Esc键就会发出“嘟嘟”声。为了确保用户想执行的vi命令是在命令方式下输入的,不妨多按几下Esc键,听到嘟声后再输入命令。 ex转义方式 vi和ex编辑器的功能是相同的,二者的主要区别是用户界面。在vi中,命令通常是单个字母,如a,x,r等。而在ex中,命令是以Enter;键结束的命令行。vi有一个专门的“转义”命令,可访问很多面向行的ex命令。为使用ex转义方式,可输入一个冒号(:)。作为ex命令提示符,冒号出现在状态行(通常在屏幕最下一行)。按下中断键(通常是Del键),可终止正在执行的命令。多数文件管理命令都是在ex转义方式下执行的(例如,读取文件,把编辑缓冲区的内容写到文件中等)。转义命令执行后,自动回到命令方式。例如: :1,$s/I/i/g 按Enter键

小白学习Linux ——理论1

小白学习Linux ——理论1 Linux学习目标: Linux操作系统介绍与安装。 Linux常用命令。 Linux常用软件安装。 Linux网络。 防火墙。 Shell编程等。 LinuxOS介绍与安装***** Linux OS介绍与安装 Linux是什么? Linux是一套作业系统,不是应用程序。 Linux的基本思想有两点:第一,一切都是文件;第二,每个软件都有确定的用途。 Linux版本: 主、次版本为奇数:发展中版本(development)、主、次版本为偶数:稳定版本(stable) EXP:3.10.0-123.el7.x86_64 主版本.次版本.释出版本-修改版本 不过,这种奇数、偶数的编号格式在 3.0 推出之后就失效了。从 3.0 版开始,核心主要依据主线版本 (MainLine) 來开发,开发完后会往下一個主线版本进行。 可以使用『 uname -r 』來查阅核心版本,然后对照下列链接來了解其对应值喔! https://www.kernel.org/releases.html Android其实就是Linux核心的一支,只是专门用来针对手机/平板这类的 ARM 机器所设计的。 GNU:GNU’s Not Unix 自由软件工程项目 Shell:命令行解释器,遵循一定的语法将输入的命令加以解释并传给系统。默认bash Linux中,每个硬件设备都被当成一个文件!EXP:IDE硬盘文件名称/dev/da[a-d];硬盘分区名称/dev/hda1,/dev/hda2…数字表示硬盘内的某个分区。 IDE硬盘 /dec/hd[a-d] SCSI硬盘与串口硬盘、U盘 /dev/sd[a-p] 光驱/dev/cdrom 软驱/dev/fd[0-1] 打印机 /dev/lp[0-2] 鼠标/dev/mouse 磁带机/dev/ht0(IDE) /dev/st0(SCSI) 硬盘分区的特点: 最多可以有4个primary分区! 只能有一个extended分区! extended存在的目的是为了创建logical! 创建logical的目的是能有多于4个分区,logical最多可以有64个! primary(主分区)+extended(扩展分区)最多有四个。 Logical(逻辑分区)的数字代号必从5开始 Primary=P;Extended=E;Logical=L P+E+L+L:/dev/hda1,/dev/hda2,/dev/hda5,/dev/hda6 Linux的硬盘分区需求: Linux可以安装在硬盘分区里面任意一个或对各可以写数据的硬盘分区。最少有两个分区 /:根分区,linux操作系统的文件夹,相当于windows系统的windows目录 /boot:启动分区,里面装在linux内核及开机引导程序grub,用于开机引导,100~200M /usr:相当于windows的应用程序目录programe files /home:linux各个用户的家目录:用户登录后进入的目录,自己的目录 /var:可变目录,放日志等经常会发生变化的文件 Swap:交换分区,相当于windows的虚拟内存文件,内存大小的2倍