1、根据后端返回的json数据,然后来生成html,再渲染页面。 比如一个简单的轮播图的数据:
传统的方法是拼接字符串方式,如下:
由于这种结构简单还好,拼接的时候要注意引号问题,一旦需求发生变化,这里修改起来也是很麻烦
结构复杂的就需要模板引擎来改善这种情况。
2、轻量化的template.js模板引擎使用,简单举一个小例子如下: 引用template — — ajax请求数据后 赋值给data — — 然后绑定数据
绑定数据格式 <%= title %> 循环获取数据 1、<%for(var i in items){%> <%}%> 2、<%items.forEach(function(item){%> <%})%> 完整代码在这里:
Oracle版本是11G
这个要取决于你的jdk,如果你的jdk是 JDK 1.4 、1.5用ojdbc5.jar,如果jdk是1.6、1.7、1.8用ojdbc6.jar 。
1.参考(我的示例代码在页面底端)
可参考8x8 Bayer matrix: https://github.com/libretro/glsl-shaders/blob/master/dithering/shaders/bayer-matrix-dithering.glsl
BayerFilter: https://en.wikipedia.org/wiki/Bayer_filter
2.Ordered Dithering(有序抖动法,It is an image dithering algorithm)
wiki:https://en.wikipedia.org/wiki/Ordered_dithering
一篇不错的抖动算法描述:https://blog.csdn.net/paris_he/article/details/40341233
Arbitrary size threshold maps can be devised with a simple rule: First fill each slot with a successive integers. Then reorder them such that the average distance between two successive numbers in the map is as large as possible, ensuring that the table "wraps" around at edges.[citation needed] For threshold maps whose dimensions are a power of two, the map can be generated recursively via:
Python3 多线程、多进程的使用场景 多线程与多进程的使用场景 io 操作不占用CPU(从硬盘、从网络、从内存读数据都算io)
计算占用CPU(如1+1计算)
python中的线程是假线程,不同线程之间的切换是需要耗费资源的,因为需要存储线程的上下文,不断的切换就会耗费资源。。
python多线程适合io操作密集型的任务(如socket server 网络并发这一类的);
python多线程不适合cpu密集操作型的任务,主要使用cpu来计算,如大量的数学计算。
那么如果有cpu密集型的任务怎么办,可以通过多进程来操作(不是多线程)。
假如CPU有8核,每核CPU都可以用1个进程,每个进程可以用1个线程来进行计算。
进程之间不需要使用gil锁,因为进程是独立的,不会共享数据。
进程可以起很多个,但是8核CPU同时只能对8个任务进行操作。
多进程 测试多进程 import multiprocessing import time def run(name): time.sleep(2) print ('heelo',name) if __name__ == '__main__': for i in range(10): #起了10个进程 p = multiprocessing.Process(target=run,args=('bob%s' %i,)) p.start() 执行结果: heelo bob1 heelo bob0 heelo bob2 heelo bob3 heelo bob5 heelo bob4 heelo bob6 heelo bob7 heelo bob8 heelo bob9 ##2秒左右就执行完成了,有几核CPU,同时就可以处理几个进程;当然要考虑你的电脑还开启了N多个其他应用程序,不过CPU计算比较快。 import multiprocessing import time,threading def thread_run(): print (threading.
springboot中使用application.yml或者 application.properties配置文件,就能够简单的配置log日志的打印格式,输出文件名以及路径了。但是如果要求分级别输出,配置日志回滚策略等自定义比较高的操作就需要引入logback-spring.xml或者logback.xml;spring官方推荐使用logback-spring.xml
说明:
logback和logback-spring.xml都可以用来配置logback,但是2者的加载顺序是不一样的。
logback.xml > application.properties > logback-spring.xml
logback.xml > application.yml > logback-spring.xml
logback.xml加载早于application.properties,所以如果你在logback.xml使用了变量时,而恰好这个变量是写在application.properties时,那么就会获取不到,只要改成logback-spring.xml就可以解决。但是如果你想使用其他日志框架,要跳过springboot集成的日志框架,那就需要用logback.xml了,还有剔除掉依赖包的引入,这里就不详细说明了。
补充一下各日志框架对应的配置文件
Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovyLog4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xmlLog4j2:log4j2-spring.xml, log4j2.xmlJDK (java Util Logging):logging.properties springboot中使用的是Logback日志框架,暂时不去评论框架的优缺点。官方推荐优先使用带有-spring的文件名作为你的日志配置文件,并且放在src/main/resources下面。这里我们虽然使用了logback-spring.xml,但是依然不能直接用 ${****}(例如${spring.application.name})来获取application中已经加载的变量,需要使用spring的标签springProperty引入需要用到的变量,然后再用 ${****}获取。例如:
<!--读取application.yml中配置的项目id--> <springProperty scope="context" name="application.name" source="spring.application.name"/> 这里的 source就是application里面的变量名,name是在本xml中的命名,也可以保持跟source一致,本文中做别名以区分。对比普通的property 标签就可以发现springProperty标签的相似之处和区别
<!--自定义项目id--> <property name="project.name" value="service-feign-promise"/> 下面是Logback日志配置步骤,干货(本文使用的是application.yml)
1、修改application.yml
spring: profiles: active: dev #开发环境 application: name: service-feign-promise #日志输出配置 logging: config: classpath:logback-spring.xml level: root: INFO com.paixi.promise.mapper: DEBUG org.springframework: INFO 可以看到,日志的配置中,不再配置文件输出路径,多配置了一个config项,这是引导至logback-spring.xml中,由此文件负责日志的各种配置。level项还是要保留的,这里的level不是指记录输出到log文件的级别,是指源码的要输出的级别。
比喻:log文件或者控制台是收货人,源码是发货人。那么这里的level就是决定是否发货,发什么货;而logback-spring.xml中配置的level就是决定我们的log文件或者控制台是否收货,收的是什么货。光发货不收货,或者光收货不发货都是不能成功完成交易的。当然了,这里只是个比喻,其原理远比这里复杂,就不多说了。
2、配置logback-spring.xml
先不多说了,先把源码贴出来吧,以表诚意,也是给自己做个笔记以免忘记。哈哈哈
源码中已经注释了许多,在源码的后面也会对一部分的标签作详细的说明,有兴趣的可以移步。也可以在使用的过程中百度或者谷歌一下都可以找到的。
声明:此配置文件参考了两位网友的博客:
[root@]# smartctl --all /dev/sda
smartctl 6.5 2016-05-07 r4318 [x86_64-linux-3.10.0-957.1.3.el7.x86_64] (local build)
Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org
Smartctl open device: /dev/sda failed: DELL or MegaRaid controller, please try adding '-d megaraid,N'
您在 /var/spool/mail/root 中有新邮件
[root@]# smartctl --all /dev/sda -d megaraid,N
smartctl 6.5 2016-05-07 r4318 [x86_64-linux-3.10.0-957.1.3.el7.x86_64] (local build)
Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org
/dev/sda: Unknown device type 'megaraid,N'
=======> VALID ARGUMENTS ARE: ata, scsi, nvme[,NSID], sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,p][,x][,N], usbprolific, usbsunplus, marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID, cciss,N, auto, test <=======
目录
1、Linux下查看文件和文件夹大小
1.1、示例:
du -h --max-depth=1 /home/work/ 仅列出/home/work/ 目录下面所有的一级目录文件大小;
du -h --max-depth=1 /home/work/* 列出/home/work/ 下面所有一级目录的一级目录文件大小。
1.2、df和du命令参数选项
2、其他用法简要介绍
3、查看linux文件目录的大小和文件夹包含的文件数 4、查看内存使用情况 free -h命令和示例
1 Linux下查看文件和文件夹大小
2 删除系统日志等
场景:在sts中执行自动部署时候maven提示No space left on device错误,后来经检查发现是磁盘空间满了,用下面的方法分析发现tomcat下面的logs目录占用了很大的空间,删除多余的日志问题解决!
1、Linux下查看文件和文件夹大小 当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择。
df 可以查看一级文件夹大小、使用比例、档案系统及其挂入点,但对文件却无能为力。
du 查询文件或文件夹的磁盘使用空间。
两者配合使用,非常有效。比如用df查看哪个一级目录过大,然后用df查看文件夹或文件的大小,如此便可迅速确定症结。
1.1、示例: [work@test01 logs]$ df -h 查看根目录的磁盘使用情况
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/cl-root 232G 138G 95G 60% /
devtmpfs 7.8G 0 7.8G 0% /dev
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 7.
Ubuntu 挂载NFS目录,用来读取服务器资源
sudo mount -o ro -t nfs 192.168.*.20:/vault2/datasets /mnt/data/datasets/ 但当系统重启时候,挂载会消失。
如果需要永久挂载,可以添加如下内容到 /etc/fstab 文件中
# device mountpoint fs-type options dump fsckorder 192.168.*.20:/vault2/dataset /mnt/data/datasets/ nfs ro 0 0 参考 How to setup nfs
Options->File Type Options
作者:逆向驿站
微信公众号:逆向驿站
知乎:逆向驿站
玩过汇编,mov指令一定最常见,而movsx、movzx、movs新手可能就有些蒙圈,上网查资料,可能也会被一些专业名词困扰,这里就用好理解的语言来解释一下各种mov
速查版 公众号回复:mov
即可获得
详解说明 mov就不说了,说下下面两种
movsx和movzx 作用都是扩展,而前者是补符号后扩展,后者是补0后扩展
先看高级语言C语言中是如何扩展的,我定义了一个char类型 c1,1个字节宽度,即8位,无符号数最大取值范围0-255,有符号数最大取值-128-127,如下图源码,未进行扩展结果则出错,如下
进行扩展,则正常,如下
再看汇编语言中
movzx是不看符号,直接高位补0,低位赋值
如下例子,是ax的值0xFFFF虽然是负数,但movzx高16位全补0,低16位赋值原本的ax的值0xFFFF,最终结果是0x0000FFFF,动图如下
movsx先看符号,高位正号全补0、负号全补1,然后低位赋值
如下例子,是ax的值0xFFFF是负数,所以扩展的时候高16位全部补1,即16进制的FFFF,而低16位赋值原本的ax的值0xFFFF,最终结果是0xFFFFFFFF,动图如下
movs指令 movsb:movs byte ptr es:[edi],byte ptr ds:[esi]的简写
movsw:movs word ptr es:[edi],word ptr ds:[esi]的简写
movsd:movs dword ptr es:[edi],dword ptr ds:[esi]的简写
movs指令执行后,esi和edi的值都会自增相应数据宽度,即b自增1,w自增2,而d自增4
通常结合rep循环指令对一片内存迅速赋值,初始化
最后,喜欢这里的请推荐给你身边的朋友吧(渗透测试、逆向破解、病毒分析、信息安全等) 欢迎关注微信公众号:逆向驿站
相关文章
● ASM汇编常用跳转指令-极速查
● CrackMe-005精解(下)
● CrackMe-005精解(上)
● CrackMe-004精解
● CrackMe-003精解
● CrackMe-002精解
● CrackMe-001精解
去年七月,博主拉着行李来到帝都开始了北漂生活。
初入社会,第一次面试就显地极为老实磕巴紧紧张张。看着面试试题上熟悉而又陌生,疏远而又亲近的知识点,我愣是没有写出一个一二来。内心徘徊了十几分钟,还是喊面试官交卷了。面试官是一位看上去四十岁的中年人,手里拿着笔眉头紧锁在我的笔试题上勾勾叉叉。
“你连这个都不会吗?”,面试官指着题目看着我颇为不满的问道。
“额.....我会的,只不过现在忘记了....”,我小心翼翼的说道。
面试官估计对我很失望,一直比较凶的询问我,我本来就紧张的手脚冒汗,这下更是语无伦次,回答的磕磕巴巴,连准备好的作品都忘了展示了。
最后面试官让我回去等通知我就知道肯定没戏了。结束后我便开始总结自己在面试中的问题,查漏补缺补充知识点,开始迎接接下来的面试。下面就基本和普通群众保持一致了,四处碰壁,我把每次的碰壁都形容为吃经验,碰着碰着后面就习惯了。
找工作一个星期后便入职了,去一家公司做Android开发,工资也是少的可怜,毕竟还没有毕业,初入行业自然不会很高。我并不是很在意收入,作为新人,还是以学习为主,收入保障基本的生活条件就好了。就这样,在开发完一个公司的Android项目后,我被告知接下来我需要开始学习逆向反编译了.......这个时候我才明白,原来我在公司里真正的工作不是Android开发,而是Android逆向!
等到后面我才了解这差不多是逆向的行情,基本上都是招一些开发人员进来,然后告知是逆向工程,这样以“骗”的形式来培养自己的逆向工程师!就这样,我就稀里糊涂的从一名Android开发工程师转到了Android逆向工程师,,,
在此之前我几乎没有听说过逆向工程,在学校学习的课程唯一和逆向沾边的是汇编语言,老师还告诉我们,你们不用学汇编,反正以后你们的工作不会接触到这方面.......我还真的是认真听老师的话,汇编课从来没听过,想在想起来看,感觉简直是上天给我开了个玩笑!
八月开始,我就开始正式的学习逆向技术。学习也是自学,公司里基本没人懂这个,更别提带我,不过好在的是我个人学习能力一直不错,先规划了一下学习进度:首先学习相关逆向工具的使用,apktool,AndroidKiller,jadx,IDA等等;下面开始学习掌握Smali语法规则,上手翻译一篇Smali文件下来,也是掌握了七七八八;最后就开始上手项目,一边做一边不断地学习,就这样,我开始了第一个逆向项目:破解百度手机助手。
以前在学校里,我是不写CSDN的,从来都是网上搜看别人写的博客。工作后,我便开始了CSDN博客的写作,一方面为了记录自己的学习和工作过程,另一方面也是为了和大家分享技术知识。看过我之前博客的小伙伴可能很熟悉,百度手机助手还是最初的教案对象。
百度的项目其实并不是很难,如果让我现在去破解,可能大概两三天,慢一点三四天就会完成了,但是刚开始的时候,一切都不熟悉,一切都刚刚起步的情况下,我还是花了两个星期的时间才把百度搞定。
逆向的工作总体来说是非常枯燥的,特别的枯燥,如果没有很好的忍耐力和定力,估计你连一天都坐不下去。我的工作基本上就是在翻看各种源码。Android源码,App源码,一些框架的源码,等等,不休不止。
估计很少人会看自己以前写的代码,我曾将在一篇博客中说到,现在大家都很喜欢创造代码,写过的代码很少会回头看上一遍。包括我也是,以前自己写的代码都是一写而过,只有出现问题的时候才会想着去看看,哪里出现了未知bug。你可能会说,我写的代码没有漏洞啊,为什么还要去看?根本就不需要好吧!
这里的漏洞根本不是你们定义的,而是我们逆向工程师来定义。漏洞并不是bug,也不会导致程序崩溃,但是它可以被别有用心的人利用,成为破坏者的帮凶。
我有时候总是喜欢感慨,现在的逆向技术已经过去了黄金时代。我们经常使用的逆向工具和技术,对比现在的安全防范手段,已经是差了整整数代。每一年安全防范技术都在推陈出新,逆向破解技术却一直都停步不前。去吾爱破解的论坛上,你会看到至今经常使用的逆向工具,七八年前,甚至十年前都已经出来了。
社会总是在不停的进步中,国家现在越来越重视互联网安全问题,很多法律法规的出台来约束互联网规范。所以我也经常笑自己,每日都是游走在法律的边缘。这其实是好事,对于逆向行业来说,规范自己的技术,不能肆意妄为的破坏,提高整个行业的形象,这也是好事。
可是在差不多在十几年前,那个时候中国互联网刚刚起步,那是一个高手频出,翻江倒海的年代。那个时候活跃的顶级大牛黑客,现在听到他们的名字还是那么的如雷贯耳,令人钦佩不已,听到他们的传奇故事依旧是那么的神采飞扬。致敬那个时代。
现在也有朋友问我,你们逆向到底干的是什么啊?我也就只能回答:“找漏洞,破解别人的代码。”至少目前,我一直都是在做这样的事情。翻看别人的代码,看看可以从哪里破解下手,这里也就是找漏洞。
但有时候找到了漏洞但是不一定有用,这时候你还需要接着重新找漏洞。这个工作是最为枯燥无聊。你可能找了一小会就发现了关键漏洞,你也可能找了一整天还是一无所获。
我这里就笑称是碰运气,就看你的运气好不好看了。运气好,你可以很快破解掉,运气不好,那就等着吧,等到也许花儿都谢了,你会找得到。
在逆向这个小众的行业内,其实出路不仅仅只有一条破解别人的代码,实质上它还可以做到保护。正所谓一攻一防。
总有人在拼了命的保护代码,也总有人在拼了命的破解代码。在逆向的道路上,一直到是鲜血淋淋,披荆斩棘。从来都没有所谓的绝对完美代码,也从来都没有绝对的破解之道。我们其实都是这个时代的勇士。
这半年,我和大家一路分享了好多安全攻防的知识,从腾讯那里开始,一直有点评他们的安全策略,一直到最近的小米MIUI系统,我们可以看到,安全防范一直都是被大厂倍为重视。毕竟谁也不希望自己的产品被破解,自己的代码被改写。攻防攻防,到最后还是防。
逆向的这半年,我其实成长了很多。以前有很多的写代码的老毛病,坏习惯现在都被改正了过来。有时候我在写代码的时候就会想,这样写安全性高不高?是否可以破解掉?这样就会让我越加的重视开发模式和系统架构,一个好的架构真的是让代码的安全性蹭蹭往上升。
也许每个逆向工程师的梦想都是希望自己写的代码牢固可靠,坚不可摧。毕竟经常破解别人的代码,自己的代码如果被破解了,就相当于自己狠狠被打脸了一样。哈哈!
还记得自己刚刚面对逆向工程的时候,那个时候总感觉很无助,压力非常的大。痛苦自己为什么不好好干自己的开发,跑过来干这个逆向工程!有过一整天都没进展的情况,非常的压抑,睡觉都不安稳的程度。脑子里就想着破解思路,从哪里下手。等到有进展了,出结果了,就会松了一口气,而来的就是轻松感。
我现在其实还有好多逆向知识和技术没有掌握,在逆向面前,我还是一个懵懵懂懂的孩子。但是我还是会不停的成长,一直成长。接下来新的一年里,我希望自己能够学到更多的逆向知识,面对更加困难的挑战,自己能够快速提高!
也希望在新的一年里,家人能够快快乐乐平平安安,小伙伴们都能圆圆满满!
一起加油吧,2019!
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) -- 将元素 x 推入栈中。pop() -- 删除栈顶的元素。top() -- 获取栈顶元素。getMin() -- 检索栈中的最小元素。 示例:
MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin(); --> 返回 -2. 第一种思路:(只使用一个栈) 每次入栈2个元素,一个是入栈的元素本身,一个是当前栈元素的最小值。
class MinStack { //每次入栈两个元素,第一个元素是本身,另一个元素是当前栈的最小值 public Stack<Integer> stack; /** initialize your data structure here. */ public MinStack() { stack = new Stack<>(); } public void push(int x) { if(stack.isEmpty()){ stack.push(x); stack.push(x); }else{ int tmp = stack.
物联网,万物互联。这里涉及到的最基本的东西就是如何将所有的物联网设备连接在一起。最简单、最广泛使用的就是互联网。
ESP8266 WIFI串口通信模块应该是使用最广泛的一种WIFI模块之一了。为什么呢?
因为ESP8266模块是一款高性能的WIFI串口模块,可以不用知道太多WIFI相关知识就可以很好的上手。说白了,只是个WIFI转串口的设备,你只要知道串口怎么编程使用,就可以了,实现了所谓的透明传输。
但是就是这么一个很常见的模块,网上很多的博客写的都是错的,或者都是很不详细的。
模块名称:ESP8266 WIFI串口通信模块
参考资料:ESP8266 WIFI串口通信模块官方资源、ATK-ESP8266资源包(提取码: nhsh)
知识储备:【STM32】串口通信基本原理(超基础、详细版)
其他模块:USB转TTL模块
项目下载链接:见本文文末
WIFI模块的调试 准备工作 USB转TTL模块与ESP8266 WIFI模块的接线:
现在市面上使用比较的ESP8266有两个版本,分别是官方的ESP8266(两排8引脚)、ATK-ESP8266(一排6引脚)。其实并没有太大的区别,只是将其中的一些引脚进行额外布局而已。
如果是官方的ESP8266模块,接线方式如下:
如果是ATK-ESP8266(正点原子)模块,接线方式如下:
这六个引脚只需要4个就行了:RXD、TXD、GND、VCC,分别和USB转TTL模块的TXD、RXD、GND、VCC相连接就行了。
需要注意两点:
1、ESP8266的RXD(数据的接收端)需要连接USB转TTL模块的TXD,TXD(数据的发送端)需要连接USB转TTL模块的RXD,这是基本的;
2、关于VCC的选取,在USB转TTL模块上有3.3V和5V两个引脚可以作为VCC,但是一般选取5V作为VCC。如果选取3.3V,可能会因为供电不足而引起不断的重启,从而不停的复位。
AT指令 在使用USB转TTL模块与电脑连接之后,就可以使用串口调试助手进行WIFI模块的调试了。首先有一点,AT指令不区分大小写,均以回车、换行结尾。下面介绍常用的AT指令:
常用AT指令 指令名响应含义ATOK测试指令AT+CWMODE=<mode>OK设置应用模式(需重启生效)AT+CWMODE?+CWMODE:<mode>获得当前应用模式AT+CWLAP+CWLAP:<ecn>,<ssid>,<rssi>返回目前的AP列表AT+CWJAP=<ssid>,<pwd>OK加入某一APAT+CWJAP?+CWJAP:<ssid>返回当前加入的APAT+CWQAPOK退出当前加入的APAT+CIPSTART=<type>,<addr>,<port>OK建立TCP/UDP连接AT+CIPMUX=<mode>OK是否启用多连接AT+CIPSEND=<param>OK发送数据AT+CIPMODE=<mode>OK是否进入透传模式 需要补充几点:
1、ESP8266的应用模式:ESP266支撑单AP模式、单STA模式和混合模式。简单的来说就是:
AP:可以将ESP8266作为热点,可以让其他的设备连接上它;STA:可以连接上当前环境下的WIFI热点。 2、什么是透传模式?
透传就是指不需要关心wifi协议是如何实现的。所需要做的就是A通过串口发数据,B通过串口收数据,整个过程中A串口和B串口就像是用导线直接连接起来了一样。则对于开发人员来看,就是完全透明的。
更简单地理解就是:
如果不开启透传模式,我们怎么发送数据呢?在每次发送数据前都必须先发送指令AT+CIPSEND=<param>,例如:
AT+CIPSEND=4 OK > //在 > 后面输入要上传的数据 但是一旦开启了透传模式,我们就不需要在每次发送数据前都发送指令AT+CIPSEND=<param>了,只需要发送一次AT+CIPSEND,之后发送的所有内容全部当成是数据了!
但是这也存在一个问题,要是我后来又想发送命令了,但是却也当成是数据发送过去了。这可怎么办?
这就要退出透传模式了。怎么退出,发送数据"+++"就可以了。注意:此时“+++”后面,不接“发送新行”!
WIFI模块的使用 ESP8266的一般使用顺序 这里的“一般”指的是:ESP8266连接当前环境的热点,与服务器建立TCP连接,传输数据。
AT+CWMODE=1:设置工作模式(STA模式)AT+RST:模块重启(生效工作模式)AT+CWJAP="111","11111111":连接当前环境的WIFI热点(热点名,密码)AT+CIPMUX=0:设置单路连接模式AT+CIPSTART="TCP","xxx.xxx.xxx.xxx",xxxx:建立TCP连接AT+CIPMODE=1:开启透传模式AT+CIPSEND:透传模式下,传输数据+++:退出透传模式 ESP8266的封装代码 关于与单片机的引脚连接:ESP8266与USART3(引脚PB10、PB11)连接。
首先是USART的配置:
#include "delay.h" #include "usart3.h" #include "stdarg.h" #include "stdio.h" #include "string.h" #include "timer.h" //串口接收缓存区 u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN个字节. u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节 //通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
文章目录 SASL_SCRAM+ACL实现动态创建用户及权限控制使用SASL / SCRAM进行身份验证1. 创建SCRAM Credentials创建broker建通信用户(或称超级用户)创建客户端用户fanboshi查看SCRAM证书删除SCRAM证书 2. 配置Kafka Brokers客户端配置kafka-console-producerkafka-console-consumer ACL配置授予fanboshi用户对test topic 写权限, 只允许 192.168.2.* 网段授予fanboshi用户对test topic 读权限, 只允许 192.168.2.* 网段授予fanboshi用户, fanboshi-group 消费者组 对test topic 读权限, 只允许 192.168.2.* 网段查看acl配置删除配置再次测试 如何查看我们创建了哪些"用户"参考文献 SASL_SCRAM+ACL实现动态创建用户及权限控制 研究了一段时间Kafka的权限控制. 之前一直看SASL_PLAINTEXT, 结果发现这玩意不能动态创建用户. 今天没死心与查了查,发现这个人也问了这个问题
https://stackoverflow.com/questions/54147460/kafka-adding-sasl-users-dynamically-without-cluster-restart
于是研究了下SCRAM. 写了这篇完整的文档
本篇文档中使用的是自己部署的zookeeper, zookeeper无需做任何特殊配置
使用SASL / SCRAM进行身份验证 请先在不配置任何身份验证的情况下启动Kafka
1. 创建SCRAM Credentials Kafka中的SCRAM实现使用Zookeeper作为凭证(credential)存储。 可以使用kafka-configs.sh在Zookeeper中创建凭据。 对于启用的每个SCRAM机制,必须通过添加具有机制名称的配置来创建凭证。 必须在启动Kafka broker之前创建代理间通信的凭据。 可以动态创建和更新客户端凭证,并使用更新的凭证来验证新连接。
创建broker建通信用户(或称超级用户) bin/kafka-configs.sh --zookeeper 192.168.2.229:2182 --alter --add-config 'SCRAM-SHA-256=[password=admin-secret],SCRAM-SHA-512=[password=admin-secret]' --entity-type users --entity-name admin 创建客户端用户fanboshi bin/kafka-configs.sh --zookeeper 192.168.2.229:2182 --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=fanboshi],SCRAM-SHA-512=[password=fanboshi]' --entity-type users --entity-name fanboshi 查看SCRAM证书 [root@node002229 kafka]# bin/kafka-configs.
const限定符 const是一种类型修饰符,用于说明永不改变的对象。const对象一旦定义,就无法再赋新值,所以必须被初始化。 const int ival = get_size(); // 正确:运行时初始化 const int ival1 = 42; // 正确:编译时初始化 // error: uninitialized const 'ival2' const int ival2; // ival2应该被初始化 const对象能参与一切不改变其内容的操作:
const int cival = ival; // 正确:ival是否为const对象都无关紧要 ival1 = cival; // 正确:拷贝cival的值,但值本身并没有被改变 默认情况下,const对象仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同的文件中分别定义了独立的变量。如果想只在一个文件中定义的const对象能在其他多个文件中声明并使用,则对const对象的声明和定义都添加extern关键字。
// ××××××××××××××××××× file.h ××××××××××××××××××× extern const int bufSize; // 声明const对象 extern int i; // 声明非const对象 // ××××××××××××××××××× file1.cc ××××××××××××××××××× // 定义的时候也必须加上extern加以限定使其被其他文件使用 // 否则会报错:"在main.cc:对'bufSize'未定义的引用" extern const int bufSize = fcn(); // 非const对象则不需要在定义的时候添加extern限定 int i = 20; // ××××××××××××××××××× main.
注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响;
1.@Order的注解源码解读 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Documented public @interface Order { /** * 默认是最低优先级,值越小优先级越高 */ int value() default Ordered.LOWEST_PRECEDENCE; } 注解可以作用在类(接口、枚举)、方法、字段声明(包括枚举常量);注解有一个int类型的参数,可以不传,默认是最低优先级;通过常量类的值我们可以推测参数值越小优先级越高; 2.Ordered接口类 package org.springframework.core; public interface Ordered { int HIGHEST_PRECEDENCE = -2147483648; int LOWEST_PRECEDENCE = 2147483647; int getOrder(); } 3.创建BlackPersion、YellowPersion类,这两个类都实现CommandLineRunner 实现CommandLineRunner接口的类会在Spring IOC容器加载完毕后执行,适合预加载类及其它资源;也可以使用ApplicationRunner,使用方法及效果是一样的
package com.yaomy.common.order; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** * @Description: Description * @ProjectName: spring-parent * @Version: 1.0 */ @Component @Order(1) public class BlackPersion implements CommandLineRunner { @Override public void run(String.
编译器遇到fatal error C1900: “P1”(第“20150812”版)和“P2”(第“20130802”版)之间 Il…….的错误 发生情况描述:
操作系统:win7 旗舰版 64bit
编译环境:vs2008
错误发生描述:
今天需要调用开源crypto++库,然后网上下载下来,自己进行编译,解压开源库的代码,然后用VS2008直接打开.sln文件,提示版本太低,这时我就用了一个高版本的vs2015 进行编译,生成了lib文件,这时在调用的项目中增加该生产的lib文件,这时提示该信息(fatal error C1900: “P1”(第“20150812”版)和“P2”(第“20130802”版)之间 Il…….),
解决方法:
重新想方法用vs2008编译crypto++成lib,然后vs2008中调用该lib(已解决)
其它问题:该lib给其它同事调用,仍然是vs2008,但是仍然提示该错误信息,最后分析结果为,同事的vs2008没有安装sp1
**总结:
可能是生成lib的vs版本与调用lib的vs版本不一致可能是vs2008没有安装sp1补丁包**
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) btn1: TButton; procedure btn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} //DLL的静态调用 Function MyMax ( X , Y : integer ) : integer ; stdcall ; external 'Project1.dll' ; //第一步:声明函数 procedure TForm1.btn1Click(Sender: TObject); begin ShowMessage ( IntToStr(MyMax(30,50)) ) ; //第二步:调用声明函数 end; end.
之前写小程序的时候出现过一种情况,配置了多个页面,但是app.js中设置的globalData只有在几个页面能获取到,有些页面获取不到。调试的方法是将那些获取不到的页面作为启动首页配置到aap.json中。这样如果还是获取不到那就是自己的代码有问题,如果获取到了,就可能是在加载这个页面之前的其他页面里面的代码有问题,依次查找各个页面最终会找到问题的。
修改完ssh登陆端口后,gitlab下载报错,修改gitlab ssh默认端口
1.vim /etc/gitlab/gitlab.rb
2.启动红线内的修改22 端口
gitlab_rails['gitlab_shell_ssh_port'] = 220 3.重新编译
gitlab-ctl stop gitlab-ctl reconfigure gitlab-ctl start ok!!!
出现场景:
springboot整合redis,启动项目时
出现原因:
redis的一系列配置不正确
解决方案:
首先在window安装redis,找到安装目录下的
redis.windows.conf redis.windows-service.conf 1)修改 protected-mode yes 改为:protected-mode no
2)注释掉 #bin 127.0.0.1
3)application.yml的redis配置中的spring.redis.timeout中连接超时时间(毫秒)中时间设置不能为0
4)redis如果没有密码,则需把密码的设置注释
我的配置如下(仅供参考)
# redis配置 # Redis服务器地址 spring.redis.host=192.168.110.1 # Redis服务器连接端口 #spring.redis.port=8895 spring.redis.port=6379 # Redis服务器连接密码 #spring.redis.password=123456 # 连接池最大连接数(使用负值表示没有限制) spring.redis.jedis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.jedis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.jedis.pool.max-idle=20 # 连接池中的最小空闲连接 spring.redis.jedis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=5000 然后重新启动redis的服务,运行通过防火墙,运行项目即可
说在最后的话:编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~
这两天在学习SFTGAN,对论文的解读在师兄的论文阅读笔记中有写到,这里就不赘述啦。使用的代码地址:https://github.com/xinntao/BasicSR
因此下面是我从代码中得出的对SFTGAN网络的一些粗略的理解,暂时记录下来,若有不正之处劳烦指正。
SFTGAN是一个生成对抗网络,其G网络(生成网络)结构如图所示:
代码:
class SFTLayer(nn.Module): def __init__(self): super(SFTLayer, self).__init__() self.SFT_scale_conv0 = nn.Conv2d(32, 32, 1) self.SFT_scale_conv1 = nn.Conv2d(32, 64, 1) self.SFT_shift_conv0 = nn.Conv2d(32, 32, 1) self.SFT_shift_conv1 = nn.Conv2d(32, 64, 1) def forward(self, x): # x[0]: fea; x[1]: cond scale = self.SFT_scale_conv1(F.leaky_relu(self.SFT_scale_conv0(x[1]), 0.1, inplace=True)) shift = self.SFT_shift_conv1(F.leaky_relu(self.SFT_shift_conv0(x[1]), 0.1, inplace=True)) return x[0] * (scale + 1) + shift class ResBlock_SFT(nn.Module): def __init__(self): super(ResBlock_SFT, self).__init__() self.sft0 = SFTLayer() self.conv0 = nn.Conv2d(64, 64, 3, 1, 1) self.
Dim xlApplication = CreateObject("Excel.Application") Dim xlBooks = xlApplication.Workbooks.Add Dim xlSheet = xlBooks.Worksheets(1) Dim strFilePath = comSaveFileDialog(Me, , , TG.eDIALOGKBN.XLS) Dim iCnt As Integer = 0 //Excel表示 xlApplication.Visible = False xlBooks = xlApplication.Workbooks.Add xlSheet = xlBooks.ActiveSheet //Excel合并单元格 xlSheet.Range(xlSheet.Cells(1, 1), xlSheet.Cells(1, 2)).Merge(Reflection.Missing.Value) //Excel背景颜色 xlSheet.Cells(1, 1).Interior.Color = System.Drawing.Color.FromArgb(171, 171, 171).ToArgb() For Each dr As DataRow In Me.ToriData.Select() iCnt += 1 xlSheet.Cells(iCnt, 1).Value = iCnt //Excel对齐设定 xlSheet.Cells(iCnt, 1).HorizontalAlignment = DL_EXCEL_XLHALIGNRIGHT //Excel单元格线 xlSheet.Cells(iCnt, 1).Borders.LineStyle = 1 Next //xlApplication.
前言 还记得在2018月3月份火爆reddit的deepfake吗?将视频中的头换成另一个人的头像,虽然可能有些粗糙和模糊,但是在分辨率不要求很高的情况下可以达到以假乱真的效果。
举个栗子,如下图中将希拉里换成特朗普的一段演讲视频。
另外还有实现川普和尼古拉脸相换:
当然这只是DeepFake的冰山一角,Deepfake当初火起来的原因可以说是广大拥有宅男心态的程序员们一起奋斗的结果。那就是,呃,可以将你想要的某张脸换到AV中去。当然这里就不进行演示了,并且相关的reddit论坛已经被禁止。所以这里就不多进行讨论啦。
本文为 https://github.com/Oldpan/Faceswap-Deepfake-Pytorch 代码的搭配教程(填一下之前埋得坑),这里简单对此进行讲解下,填补一下之前的空缺。
相关研究 其实有关深度学习的换脸相关的研究已经很普及了,有基于GAN的也有基于Glow的,但本质上都是生成模型,只是换了一种实现方式,而这个DeepFake呢,使用的是机器学习中的自编码器,拥有与神经网络类似的结构,鲁棒性较好,我们可以通过学习它来对生成网络有一个大概的了解,这样之后碰到相似的网络或者构造就好上手了。
技术讲解 人脸互换是计算机视觉领域中一个比较热门的应用,人脸互换一般可以用于视频合成、提供隐私服务、肖像更换或者其他有创新性的应用。最早之前,实现人脸互换是通过分别分析两者人脸的相似信息来实现换脸,也就是通过特征点匹配来提取一张脸中例如眉毛、眼睛等特征信息然后匹配到另一张人脸上。这种实现不需要进行训练,不需要的数据集,但是实现的比较差,无法自己修改人脸中的表情。
而在最近发展的深度学习技术中,我们可以通过深度神经网络提取输入图像的深层信息,从而读取出其中隐含的深层特征来实现一些新奇的任务,比如风格迁移(style transfer)就是通过读取训练好的模型提取图像中的深层信息来实现风格互换。
也有使用神经网络进行人脸互换(face-swap),其中使用VGG网络来进行特征提取并实现人脸互换。这里我们通过特殊的自编码器结构来实现人脸互换,并且达到不错的效果。
基础背景:自编码器 自编码器类似于神经网络,可以说是神经网络的一种,经过训练后能够尝试将输入复制到输出。自编码器和神经网络一样,有着隐含层 h h h,可以将输入解析成编码序列,从而复现输入。自编码器内部有一个函数 h = f ( x ) h=f(x) h=f(x)可以进行编码,同时也有一个函数 r = g ( h ) r=g(h) r=g(h)实现解码,如下图所示。
(自编码器的结构,x为输入,f为编码函数,将x编码为隐含特征变量h,而g为解码网络,通过将隐变量h进行重构得到输出结果r,我们也可以看到数字2被放入编码器之后得到其隐含层的编码也就是Compressed representation,之后通过解码器重新生成出来)
现代的自编码器从宏观上也可以理解为随机映射 P e n c o d e r ( h / x ) P_{encoder}(h/x) Pencoder(h/x)和 P d e c o d e r ( x / h ) P_{decoder}(x/h) Pdecoder(x/h)。之前自编码器一般用于数据降维或者图像去噪。但是近年来由于神经网络的发展,更多的潜变量被研究,自编码器也被带到了生成式建模的前沿,可以用于图像生成等方面。
实现的方式概述 注意以下的热部署方式在IDEA是默认没有打开自动编译的,手动编译需要快捷键(Ctrl+Shift+F9),自动编译的修改配置如下:(注意刷新不要太快,会有1-2秒延迟)。
File-Settings-Compiler-Build Project automatically
二、spring-boot-devtools 在pom中直接引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> 设置以下两项(第一项如已设置直接设置第二项)
1) “File” -> “Settings” -> “Build,Execution,Deplyment” -> “Compiler”,选中打勾 “Build project automatically” 。
2) 组合键:“Shift+Ctrl+Alt+/” ,选择 “Registry” ,选中打勾 “compiler.automake.allow.when.app.running” 。
之后直接正常run即可!
三、spring-loaded 在Plugins中添加依赖
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- spring热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.6.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
如果依赖提示not found,先在上面写让maven下载下来,再移到Plugin里面来
命令行窗口启动
找到pom.xml的路径,IDEA的话打开Pom后在标签页鼠标悬停即可看到,或者在pom上右击->file Path
在这个路径下打开cmd窗口(win下可以通过shift快速在对应路径打开),输入启动命令
mvn spring-boot:run 这样就可以在IDE里修改代码实现热加载了!
还有一种复杂的方式是通过启动参数指定jar包的位置,感觉更加复杂,暂不赘述。
四、发布spring-boot程序 1.jar形式
通过maven直接INSTALL,把项目打包并且相关的依赖也打到同一个jar里面(推荐shade插件)。
启动:
java -jar Demo-0.
注:由于我进行的并不是规范爬虫,每次爬都是有点心虚,所以下手对象也是一些不法网站QAQ,其中涉及敏感信息,所以就不给出网站URL,哈哈
import requests from bs4 import BeautifulSoup import time import socket import os import re import bs4 def getText(url): try: header = {'User-Agent': 'Mozilla/5.0'} r = requests.get(url, timeout=20, headers=header, stream=True) r.raise_for_status() return r.content except: print("申请视频错误") def writeFile(path, content): if not os.path.exists(path): with open(path, "wb") as file: file.write(content) file.flush() else: pass def dealUrl(url, dir): if not os.path.exists(dir): os.mkdir(dir) str = url.split("/") ss = str[-1].split(".") mv = str[-2] + "_" + ss[0] + "
A curated list of awesome mathematics resources.
Contents ContentsGeneral Resources Learning PlatformsLearn to LearnToolsQuestions and AnswersEncyclopediaBooksBlogsMiscLecture Notes Foundations of Mathematics Set TheoryLogicCategory TheoryHomotopy Type TheorySurreal NumbersNumber Theory Algebraic Number TheoryAnalytic Number TheoryAlgebra Abstract AlgebraGroup TheoryLinear AlgebraRing TheoryGalois TheoryLie AlgebrasCombinatorics Graph TheoryGeometry and Topology Differential GeometryAlgebraic GeometryTopologyAlgebraic TopologyAnalysis Real AnalysisHarmonic AnalysisComplex AnalysisFunctional AnalysisMeasure TheoryOrdinary Differential EquationsPartial Differential EquationsProbability and Statistics Probability TheoryStatisticsStatistical LearningStochastic processesNumerical AnalysisSignal processingMathematics for Computer ScienceMathematical BiologyMathematical PhysicsLicense General Resources Learning Platforms Khan AcademyCourseraMIT OpenCourseWareedX Learn to Learn Understanding Mathematics Tools SymbolabDesmosMath WordsWolfram Alpha Questions and Answers Mathematics Stack ExchangeMathOverflow - for professional mathematicians Encyclopedia Encyclopedia of MathematicsPlanetmathProofWikiWolfram Mathworld Books Calculus: Basic Concepts for High Schools - L.
经验误差与泛化误差 通常我们把分类错误的样本数占样本总数的比例称为“错误率”(error rate),即如果在m个样本中有a个样本分类错误,则错误率E=a/m;相应的,1-a/m称为“精度”,即“精度=1-错误率”。更一般地,我们把学习器的实际预测输出与样本的真实输出之间的差异称为“误差”(error),学习器在训练集上的误差称为“训练误差”(training error)或“经验误差”(empirical error),在新样本上的误差称为“泛化误差”(generalization error)。显然,我们希望得到泛化误差小的学习器。然而,我们事先并不知道新样本是什么样,实际能做的是努力使经验误差最小化。在很多情况下,我们可以学得一个经验误差很小,在训练集上表现很好的学习器,例如甚至对所有训练样本都分类正确,即分类错误率为零,分类精度为100%,但这是不是我们想要的学习器呢?遗憾的是,这样的学习器在多数情况下都不好。
我们实际希望的,是在新样本上能表现得很好的学习器。为了达到这个目的,应该从训练样本中尽可能学出适用于所有潜在样本的“普遍规律”,这样才能在遇到新样本时做出正确的判别。然而,当学习器把训练样本学得“太好”了的时候,很可能已经把训练样本自身的一些特点当做了所有潜在样本都会具有的一般性质,这样就会导致泛化性能下降。这种现象在机器学习中称为“过拟合”,与“过拟合”相对的是“欠拟合”,关于“过拟合”和“欠拟合”现象,可以参考:https://blog.csdn.net/qq_41080850/article/details/86253123
在现实任务中,我们往往有多种学习算法可供选择,甚至对于同一个学习算法,当使用不同的参数配置时,也会产生不同的模型。那么,我们应该选用哪一个学习算法、使用哪一种参数配置呢?这就是机器学习中的“模型选择”(model selection)问题。理想的解决方案当然是对候选模型的泛化误差进行评估,然后选择泛化误差最小的那个模型。然而如上面所讨论的,我们无法直接获得泛化误差,而训练误差又由于过拟合现象的存在而不适合作为标准,那么,在现实中如何进行模型的评估与选择呢?
模型评估方法 通常,我们可通过实验测试来对学习器的泛化误差进行评估并进而做出选择(在现实任务中往往还会考虑时间开销、存储开销、可解释性等方面的因素,这里暂且只考虑泛化误差)。为此,需使用一个“测试集”(testing set)来测试学习器对新样本的判别能力,然后以“测试集”上的测试误差(testing error)作为泛化误差的近似。通常我们假设测试样本也是从样本真实分布中独立同分布采样而得。但需注意的是,测试集应该尽可能与训练集互斥,即测试样本尽量不在训练集中出现、未在训练过程中使用过。
可是,我们只有一个包含m个样例的数据集D={(x1,y1),(x2,y2),···,(xm,ym)},既要训练,又要测试,怎样才能做到呢?答案是:通过对D进行适当的处理,从中产生出训练集S和测试集T。下面介绍几种常见的做法:
留出法
交叉验证法
自助法
给定包含m个样本的数据集D,在模型评估与选择过程中由于需要留出一部分数据进行评估测试,事实上我们只使用了一部分数据训练模型。因此,在模型选择完成后,学习算法和参数配置已选定,此时应该用数据集D重新训练模型。这个模型在训练过程中使用了m个样本,这才是我们最终提交给用户的模型。 另外,需要注意的是,我们通常把学得模型在实际使用中遇到的数据称为测试数据,为了加以区分,模型评估与选择中用于评估测试的数据集常称为“验证集”(validation set)。例如,在研究对比不同算法的泛化性能时,我们用测试集上的判别效果来估计模型在实际使用时的泛化能力,而把训练数据另外划分为训练集和验证集,基于验证集上的性能来进行模型选择和调参。
模型性能度量 对学习器的泛化性能进行评估,不仅需要有效可行的实验估计方法,还需要有衡量模型泛化能力的评价标准,这就是性能度量(performance measure)。
注意此处的“均方误差”与统计学中的均方误差稍有不同,统计学中规定
的均方误差(MSE)是残差平方和(SSE)除以它自己的自由度。
下面再介绍几种分类任务中常用的性能度量:
错误率与精度
查准率、查全率与F1
查准率又称为准确率,查全率又称为召回率。
以西瓜问题说明查准率与查全率:查准率可以理解为挑出的好瓜中,
真正的好瓜占据的比例;查全率可以理解为挑出的真正好瓜在所有
真正的好瓜中占据的比例。
F1是基于查准率和查全率的调和平均定义的,则是加权调和平均。
ROC与AUC
关于ROC曲线与P-R曲线,还可以参考:https://www.plob.org/article/12476.html
代价敏感错误率与代价曲线
PS:以上内容绝大部分均摘自周志华老师的《机器学习》,本文权作记录以便于后续查阅复习。
l=f.readline().decode('utf-8').encode('GBK')
←←←←←←←←←←←← 快!点关注
背景 最近工作上有个类似需求是: 现有约3亿条数据词典存在于一个csv文件A中,作为数据源。对于 用户输入的任意单词M,需要快速的在A中匹配M单词是否存在。(A文件约3G大小左右,总行数三亿)
拿到这个需求,你的第一想法怎么做呢?
正常思路可能是:
将csv文件A导入某关系型数据库。sql查询按M匹配。 上面的方式有个明显的缺点是:慢!
3亿多行的数据,即便是建好索引进行检索,匹配到也得话不少时间(笔者没亲自试过,感兴趣的朋友可以自行测试测试,理论上快不起来的)。
目前能 在时间复杂度和空间复杂度上达到最佳的方案,恐怕就是Bloom Filter了, 维基地址:Bloom Filter
此处给不太了解Bloom Filter的读者看,熟悉的朋友直接看下一节。
本文场景Bloom Filter 使用思路解释: 假设申请了一段bit位大数组(即数组中的元素只能是一个bit位,1或0,默认元素值都为0) 将csv文件A中的每个单词,经过多个hash函数进行hash运算之后得到在大数组中对应的多个下标位置 将步骤2中得到的多个下标位置的bit位都置为1. 对于用户输入的任意单词M,按照2的步骤得到多个下标位置,其对应大数组中的值全部为1则存在,否则不存在。
方案选型 实现Bloom Filter的方法很多,有各种语言版本的,这里为了真切感受一下算法的魅力,笔者这里决定用java 代码徒手撸了!
另一方面,考虑到分布式应用的需要,显然在单机内存上构建Bloom Filter存储是不太合适的。 这里选择redis。
redis有以下为操作,可以用于实现bloomfilter:
redis> SETBIT bit 10086 1 (integer) 0 redis> GETBIT bit 10086 (integer) 1 redis> GETBIT bit 100 # bit 默认被初始化为 0 (integer) 0 复制代码 实现细节 实现bloom filter的关键是hash函数,一般为了降低误报率、减少hash碰撞的影响,会选择多个hash函数。
那么,怎么写一个hash函数呢?
不要方,我们要的hash是 input: String --> output: int , jdk里面的String类不是恰好也有一个hashCode 方法吗? 翻出来看一看!
3.5 算术和逻辑操作 下图列出了一些双字整数操作,分为四类。二元操作有两个操作数,而一元操作只有一个操作数。描述这些操作数的符号与3.4节中使用的符号完全相同,除了leal以外,每条指令都有对应的对字和对字节操作的指令。把后缀l换成w就是对字的操作,换成b就是对字节的操作。例如,addl对应有addw和addb。
这里面比较特别的指令就是leal(取地址指令),其余的指令都是比较常规的算术和逻辑运算,相比之下还比较好理解,因此LZ这里重点介绍leal指令,对于其余的指令LZ不会一一介绍,接下来我们就认识一下这个特别的leal指令吧。
leal指令 leal指令是非常神奇的一个指令,它可以取一个存储器操作数的地址,并且将其赋给目的操作数。如果用C语言当中来对应的话,它就相当于&运算。
比如对于leal 4(%edx,%edx,4),%eax这条指令来讲,我们假设%edx寄存器的值为x的话,那么这条指令的作用就是将 4 + x + 4x = 5x + 4赋给%eax寄存器。它和mov指令的区别就在于,假设是movl 4(%edx,%edx,4),%eax这个指令,它的作用是将内存地址为5x+4的内存区域的值赋给%eax寄存器,而leal指令只是将5x+4这个地址赋给目的操作数%eax而已,它并不对存储器进行引用的值的计算。
为了更好的表示这条指令的效果,LZ这里简单的画个图来表示这一过程。我们假设下图是执行指令之前,寄存器和存储器的状态。
可以看到,此时在存储器中,地址为5x+4的区域的值为1000。那么此时若是进行movl 4(%edx,%edx,4),%eax操作,很显然,%eax的值应该为1000,也就是下图。
但是如果进行leal 4(%edx,%edx,4),%eax操作的话,%eax的值就不是1000了,因为leal指令不会去取存储器当中的值,因此寄存器%eax的值应该是5x+4。
试想一下,倘若在地址为5x+4的位置存储的是变量i,那么其实这条指令就相当于&i操作,这也就是C语言当中的&取地址操作的汇编级做法。
一个示例 int arith(int x, int y , int z){ int t1 = x+y; int t2 = z*48; int t3 = t1&0xFFFF; int t4 = t2*t3; return t4; } 这里面包含了加、乘、与运算,我们使用-O1和-S参数编译sum.c这个文件,使用cat sum.s查看它,会得到如下的汇编代码。
.file "sum.c" .text .globl arith .type arith, @function arith: pushl %ebp movl %esp, %ebp //以上为栈帧建立 movl 16(%ebp), %eax leal (%eax,%eax,2), %edx sall $4, %edx movl 12(%ebp), %eax addl 8(%ebp), %eax andl $65535, %eax imull %edx, %eax //以下为栈帧完成 popl %ebp ret .
openjdk:8-jre镜像是基于debian系统的。默认时区是UTC。 下面两个方法都可以把时区改为Asia/Shanghai - 启动java应用时设置jvm参数 jvm参数 -Duser.timezone=Asia/ShangHai - 创建容器时设置debian的时区文件 debian有两个文件需要修改,一个是/etc/localtime,一个是/etc/timezone。 ``` cat > /home/foo/timezone <
参考博客: AES加密的四种模式详解
ECB模式Java实现(1)
ECB模式Java实现(2)
CBC模式Java实现(1)
CBC模式Java实现(2)
ECB模式 加密 import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Encoder; public class Base64AesEncrypt { /** * BASE64加密 * @param base64Content 被加密的字符串 * @return */ public static String encryptBASE64(String base64Content) { byte[] bt = base64Content.getBytes(); String aesContent = (new BASE64Encoder()).encodeBuffer(bt); return aesContent; } /** * AES加密 * @param aesContent 被加密的字符串 * @param aesKey 秘钥 * @return */ public static String encryptAES(String aesContent, String aesKey) { try { KeyGenerator kgen = KeyGenerator.
Kinetics 数据库处理 下载mp4 --> jpg比较3D conv与non-local的设置差异 本文仅为自己研究过程的一个随手记录,部分细节可能没有严格考证
kinetics数据库是当前较大规模的行为识别数据库,400类,training set 246k video, validation set 20k. 由于此前没有接触过视频数据库,而这个库又非常大,处理起来比较麻烦,记录一下。
下载mp4 -> jpg 下载 kinetics数据库的页面 , 里面没有现成的video,要根据提供的链接自己一个一个爬…好像看到有人说一个月也没爬多少。。不知真假。。。不过更严重的是里面部分链接已经被视频发布者删除或者转为私密模式了。non-local的作者Xiaolong Wang对kinetics短边按比例缩放到256保存了一个副本,github 链接 ,大约占132G, (原数据集400G+)云盘的下载链接要向他发邮件获取,由于图像大小有所损失,对data augmentation有影响,并且这个数据当时下载的时候大约有5%的video已经不存在了,所以性能会略有损失,(Xiaolong Wang:损失<0.5%)。132G的压缩包,下载速度10M/s,大约用了3.5h。
mp4 --> jpg kinetics的视频都是mp4格式,non-local 貌似就直接用mp4格式输入网络(作者自述 我没有考证),但是non-local用的是caffe2,我不是很6,所以借助的是CVPR2018上的一篇3D conv的pytorch实现。这篇工作里将mp4处理成jpg进行训练,所以也按帧提取了一下。使用上述project中 utils/video_jpg_kinetics.py 实现。
该过程耗时近24h,读写均在ssd上,拆解成frame的文件所占空间为400G+
比较3D conv与non-local的设置差异 worktrain methodbackboneinputframes/clipdata formatnon-localfine-tuneResNet50 + I3D224x22432mp43D ResNettrain from scratchResNet50 + 3D112 x 11216jpg 其中3D ResNet所用GPU为8*titanx。
springboot外置Tomcat启动时出现的中文乱码的处理 springboot外置tomcat启动时经常会遇到中文乱码的问题,通常是由于以下5种原因:
IDEA设置的字符编码不对:File->settings->Editor->file encoding将字符编码都修改为UTF-8。
IDEA配置文件中对字符编码的配置不对:在IDEA的安装目录bin文件夹下找到idea64.exe.vmoptions(32位的选择idea.exe.vmoptions)文件,编辑此文件,插入:-Dfile.encoding=UTF-8。Tomcat配置文件中的字符编码配置不对:在Tomcat安装目录下找到catalina.bat文件,在配置中加入set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS% -Dfile.encoding=UTF-8"或者在IDEA的tomcat启动配置中加入-Dfile.encoding。到tomcat/conf/目录下,修改logging.properties 找到java.util.logging.ConsoleHandler.encoding = utf-8 更改为 java.util.logging.ConsoleHandler.encoding = GBK。如果出现下面这种情况,多为Windows系统命令提示符字符编码配置不匹配:
解决方法:win+R输入regedit打开注册表编辑器,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor,鼠标右键-新建,选择“字符串值”,命名为“autorun”,数值数据“65001”点击确定。
完成后重新运行startup,中文正常显示。
Mosquitto动态链接库的交叉编译与移植
前段时间对Mosquitto进行了ARM移植,找了大量的资料,没有一个可以一次性成功的,于是借鉴了很多文章,并自己摸索最后得出了这篇移植结论,按照这种方法应该可以一次性交叉编译成功。如果有什么问题,请在下面给我留言,谢谢。
Ubuntu版本:14.04LTS
交叉编译链:友善之臂提供的4.4.3版本工具链
(/opt/FriendlyARM/toolchain/4.4.3/bin/arm-linux-gcc)
移植目录为/home/mosquito
安装目录为/home/mosquitto/arm
可以使用两种方式进行交叉编译
第一种方法:使用./configure配置后进行make && make install (这种方法需要两个依赖库,但是在make的时候需要大量修改Makefile中的依赖包目录,容易出错)
参考网址:https://blog.csdn.net/gaoyadianta/article/details/72831665
https://blog.csdn.net/L982817732/article/details/78926061
第二种方法:使用cmake配置后进行make && make install (这种方法需要三个依赖库,在配置时不需要修改太多地方,操作起来比较容易,因此在这里选择了第二种方法)
参考网址:https://blog.csdn.net/sqshining/article/details/69660650
https://blog.csdn.net/sqshining/article/details/69664310#commentsedit
开始交叉编译前的一些准备: cmake-3.7.2
wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz autoconf 用来生成configure文件
wget https://alpha.gnu.org/gnu/autoconf/autoconf-2.68b.tar.gz libtool
wget https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz 新建一个文件夹,在这个文件夹中进行所有的移植操作。
拉取上面三个压缩包,然后解压缩进行本地编译,命令如下
./configure make make install 交叉编译openssl wget https://www.openssl.org/source/old/1.0.0/openssl-1.0.0.tar.gz tar –zxvf openssl-1.0.0.tar.gz cd openssl-1.0.0/ ./config no-asm shared --prefix=/home/mosquitto/arm/ssl 注意:--prefix后面跟着是make install的安装目录,可以自行定义
export cross=arm-linux- make CC="${cross}gcc" AR="${cross}ar r" RANLIB="${cross}ranlib" 报错
原因是Makefile里面有-m64这句话。
解决方法:vim Makefile,找到-m64,删除,我这里一共发现了两处地方
再次
make CC="${cross}gcc" AR="${cross}ar r" RANLIB="
圣杯布局的出现是来自由 Matthew Levine 在 2006 年写的一篇文章 《In Search of the Holy Grail》,在国内最早是淘宝UED的工程师(玉伯大大)对圣杯布局改进并传播开来,在中国的叫法是双飞翼布局 。 圣杯布局和双飞翼布局达到的效果基本相同,都是侧边两栏宽度固定,中间栏宽度自适应。 主要的不同之处就是在解决中间部分被挡住的问题时,采取的解决办法不一样,圣杯布局是在父元素上设置了padding-left和padding-right,在给左右两边的内容设置position为relative,通过左移和右移来使得左右两边的内容得以很好的展现,而双飞翼则是在center这个div中再加了一个div来放置内容,在给这个新的div设置margin-left和margin-right 。
效果图 原本录制了一个小视频,奈何不能上传到博客中,视频中通过缩放页面可以发现随着页面的宽度的变化,这三栏布局是中间盒子优先渲染,两边的盒子框子宽度固定不变,即使页面宽度变小,也不影响我们的浏览。注意:为了安全起见,最好还是给body加一个最小宽度!
双飞翼布局要求 header和footer各自占领屏幕所有宽度,高度固定。中间的container是一个三栏布局。三栏布局两侧宽度固定不变,中间部分自动填充整个区域。中间部分的高度是三栏中最高的区域的高度。 双飞翼布局的实现 left、center、right三种都设置左浮动设置center宽度为100%设置负边距,left设置负边距为100%,right设置负边距为自身宽度设置content的margin值为左右两个侧栏留出空间,margin值大小为left和right宽度 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script> </head> <style> body { min-width: 550px; font-weight: bold; font-size: 20px; } #header, #footer { background: rgba(29, 27, 27, 0.726); text-align: center; height: 60px; line-height: 60px; } #container { overflow: hidden; } .column { text-align: center; height: 300px; line-height: 300px; } #left, #right, #center { float: left; } #center { width: 100%; background: rgb(206, 201, 201); } #left { width: 200px; margin-left: -100%; background: rgba(95, 179, 235, 0.
计算机网络作业(一) 一.安装并配置SSH服务器 1.登录https://www.mls-software.com/opensshd.html,下载setupssh-7.4p1-1.exe。 2.下载完成后,点击安装程序开始安装。 输入命令:ssh -v和ssh -V 4.调用系统用户并加权限 (1)生成一个组 输入命令:mkgroup -l >> ..\etc\group (2)生成一个用户名 输入命令 : mkpasswd -l >> ..\etc\passwd (3)设置用户权限 输入命令:chown chefe * 和chmod 600 * 5.启动服务器 输入命令:net start opensshd 二.安装并配置FTP服务器 1.开通服务 控制面板–>程序–>启动或关闭Windows功能–>勾选下图标记的选项 2.打开IIS管理器,建立站点 计算机管理–>点击Internet Information Services(IIS)管理–>点击该计算机名左侧的展开按钮–>右键单击网站,选择添加FTP站点–>输入站点名和共享文件夹所在的路径–>绑定IP地址并在绑定SSl选项中选择无SSl–>设置身份认证和授权信息–>FTP站点已经创建成功并正常运行 3.设置防火墙 Windows防火墙–>点击允许应用或功能通过Windows防火墙–>勾选列表中FTP服务器前的复选框,勾选后点击确定以完成设置 4.打开浏览器,在地址栏输入(ftp://192.168.1.44),回车以访问 三.安装并配置web服务器 1.控制面板–>程序–>启动或关闭Windows功能–>勾选下图所示的选项 2.计算机管理–>点击Internet Information Services(IIS)管理–>点击该计算机名左侧的展开按钮–>右击网站,选择添加网站 3.填写网站名称,物理地址和IP地址–>在刚填写的物理地址里存放自己编写的页面–>打开浏览器,在地址栏输入(ftp://192.168.1.44),回车以访问。 四.安装并配置E-mial服务器 1.下载hmailserver https://www.hmailserver.org/app.php/page/download?sid=05dfd5adebf86104d9ca199bd50d6d00 2.安装hmailserver 选择同意用户许可协定–>选择安装路径–>选择要安装的组件–>选择默认的数据库系统(内置数据库系统)–>创建一个开始菜单文件夹,用来放置hmailserver图标或选择一个已经存在的文件夹–>点击“install”按钮,进行安装 3.设置HMailServer管理控制台的密码 4.打开hmailserver–>选中要connect的host,点击右侧的“edit”按钮,选择“Save password”,接着输入之前设置的控制台管理密码,点击“save”按钮 5.添加域–>添加账号 6.登录www.foxmail.com.cn,下载并安装foxmail 7.打开foxmail的客户端,输入我们刚刚创建的电子邮箱账号和密码,点击“下一步”,点击“测试账户设置” 8.所有测试项通过,点击“关闭” --------------------- 作者:leonard_fmvp 来源:CSDN 原文:https://blog.csdn.net/leonard_fmvp/article/details/77985918 版权声明:本文为博主原创文章,转载请附上博文链接!
Java导出数据行写入到Excel表格:基于Apache POI import java.io.File; import java.io.FileOutputStream; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; public class ExcelUtil { public static void main(String[] args) throws Exception { HSSFWorkbook mWorkbook = new HSSFWorkbook(); HSSFSheet mSheet = mWorkbook.createSheet("Student"); // 创建Excel标题行,第一行。 HSSFRow headRow = mSheet.createRow(0); headRow.createCell(0).setCellValue("id"); headRow.createCell(1).setCellValue("name"); headRow.createCell(2).setCellValue("gender"); headRow.createCell(3).setCellValue("age"); // 往Excel表中写入3行测试数据。 createCell(1, "zhang", "男", 18, mSheet); createCell(2, "phil", "男", 19, mSheet); createCell(3, "fly", "男", 20, mSheet); File xlsFile = new File("f.xls"); mWorkbook.write(xlsFile);// 或者以流的形式写入文件 mWorkbook.write(new FileOutputStream(xlsFile)); mWorkbook.
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 方法一:
最直观的反映就是嵌套for循环:遍历两遍数组,将数组中的值两两相加,找到和为指定值 target 的两个数字,返回它们在数组中的下标即可。
var twoSum = function(nums,target) { //首先判断nums是否是数组、taget的值是否是数值 if(!Array.isArray(nums) || Object.prototype.toString.call(target) !== "[object Number]"){ return; }; //再判断两数之和 var i,j,len = nums.length; for(i=0;i<len;i++){ for(j=i+1;j<len;j++){ if(nums[i]+nums[j]===target){ return[i,j]; }else{ return false; } } } }; twoSum([2, 7, 11, 15],9);//[0,1] Object.
今天进行scikit-learn的特征选择实验时,一段非常短的代码不知为何总是报错,代码如下:
#Filename:FeatureV1.py
from sklearn.feature_selection import VarianceThreshold
X=[[0,0,1],[0,1,0],[1,0,0],[0,1,0],[0,1,1]]
sel=VarianceThreshold(threshold=(.8(1-.8)))
sel.fit_transform(X)
报错如下:
TypeError: 'float' object is not callable
我对着代码检查了好几遍,还是不明所以。
最后,总算在看代码提示<module> sel=VarianceThreshold(threshold=(.8(1-.8)))时发现错误,原因是乘法表示不规范,遂改之,如下:
#Filename:FeatureV1.py
from sklearn.feature_selection import VarianceThreshold
X=[[0,0,1],[0,1,0],[1,0,0],[0,1,0],[0,1,1]]
sel=VarianceThreshold(threshold=(.8*(1-.8)))
sel.fit_transform(X)
原因就是少了一个乘法符号,这是非常低级的错误,但是,对于水平不高的初学者来说要多练习编程,尽量的避免这种低水平的错误,不要让这种没有多少意义的错误打击我们学习编程的信心。
Android Studio 3.3 报如下错误
The given artifact contains a string literal with a package reference 'android.support.v4.content' that cannot be safely rewritten. Libraries using reflection such as annotation processors need to be updated manually to add support for androidx implementation 的 butterknife 版本号从 9.0.0-rc1 改成 10.0.0 即可
1. 将PNG图片用PS打开。 2. 图像-模式-8位/通道 (这样在后续存储时才有gif存储选项) 3. 将图片另存为GIF。 4. 选项中选择局部可感知或者全部可感知。 5. 强制选择“无”,勾选透明度。 6. 存储后的gif文件和原png文件对比,从20.6k变为了1.8k。 7. 最后,把文件后缀的gif命名为png。 这样,既保证了分辨率、大小,又保证透明部分依旧透明!
1、创建服务端 package server_scoket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_Socket {
public static void main(String[] args) throws IOException {
//创建服务端,绑定端口8081
ServerSocket server = new ServerSocket(8081) ;
System.out.println("Scoket 服务启动成功。。。。。。。。。。。。。");
//阻塞状态、监听服务端口8081
Socket client = server.accept() ; System.out.println("来访问客户端信息:" + " 客户端ip:"+client.getInetAddress()
+ "客户端端口:"+client.getInetAddress().getLocalHost() + "已连接服务器" );
BufferedReader bReader = new BufferedReader(new InputStreamReader(client.getInputStream())); //读取客户端发送来的消息
String msg = bReader.readLine(); System.out.println("客户端发来的消息:" + msg); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.
Error Info:
C:\Users\jalchu\WebstormProjects\vue-element-admin>npm install npm WARN deprecated bfj-node4@5.3.1: Switch to the `bfj` package for fixes and new features! npm WARN deprecated nomnom@1.8.1: Package no longer supported. Contact support@npmjs.com for more info. npm ERR! Error while executing: npm ERR! C:\Program Files\Git\cmd\git.EXE ls-remote -h -t git://github.com/adobe-webplatform/eve.git npm ERR! npm ERR! fatal: unable to connect to github.com: npm ERR! github.com[0: 192.30.255.112]: errno=No such file or directory npm ERR! github.com[1: 192.30.255.113]: errno=No such file or directory npm ERR!
转载自:https://blog.csdn.net/baidu_26646129/article/details/80464447
本文主要介绍百度地图POI数据获取:从百度地图得到POI数据,以json格式保存;
POI数据获取的原理部分还可以参照零基础掌握百度地图兴趣点获取POI爬虫(python语言爬取)(基础篇)。
POI数据获取
百度地图POI数据可以从百度地图提供的API——兴趣点坐标获取得到。得到的POI信息包括了名称、经纬度坐标、地址等等,具体的接口使用说明可以参考百度地图WEB服务api说明中的地点检索。
从说明文档我们可以发现,POI数据获取的关键在于构造出合适的url,访问该url便能请求到相应的POI数据。因此,我们先对百度地图WEB服务api中的url进行详细的说明。
http://api.map.baidu.com/place/v2/search?query=银行&bounds=39.915,116.404,39.975,116.414&output=json&ak={您的密钥} //GET请求
以上是百度地图说明文档提供的一个搜索url示例,我们可以将其划分为以下几个部分:
前缀部分:无论进行何种搜索,需要的数据格式如何,请求的url都需要这一部分 http://api.map.baidu.com/place/v2/search?
参数部分:对请求的数据进行定制,你可以指定特定的关键词、搜索区域、输出类型以及你的ak(access key) query=银行&bounds=39.915,116.404,39.975,116.414&output=json&ak={您的密钥}
前缀部分对所有请求都一致不需要过多的说明,而参数部分影响搜索的结果,需要详细说明。由于百度地图提供了三种POI搜索方式,即行政区划区域搜索、周边搜索、矩形区域搜索,但这几种搜索仅仅在一些参数上存在差异,大部分参数都是相同的,返回的结果也是相同的,本文仅以矩形区域搜索请求参数举例说明:
返回参数
需要特别注意的是:
百度地图为了保护数据,单次请求total最多为400,也就是只能搜出400个结果,如果搜索结果大于400个的时候只显示400条记录;
百度地图为非认证开发者提供的配额为2000次请求/每天,并发访问的限制为120。
第一个问题的解决可以通过划分子搜索区域,将需要搜索的矩形区域划分为多个面积更小的矩形区域,将他们的搜索结果进行合并即得到了需要的搜索结果。
第二个问题的解决通过申请多个ak,交替使用,同时减缓请求速度。
最后实现的代码如下:
# -*- coding: utf-8 -*- # 第一行必须有,否则报中文字符非ascii码错误 import urllib import json import time #ak需要在百度地图开放平台申请 ak = "XXX" #关键词 query=["社会福利院"] page_size=20 page_num=0 scope=1 #范围: #左下坐标 30.379,114.118 #右上坐标 30.703,114.665 #中间坐标 30.541,114.3915 bounds=[ [30.379,114.118,30.541,114.3915], [30.379,114.3915,30.541,114.665], [30.541,114.118,30.703,114.3915], [30.541,114.3915,30.703,114.665] ] new_bounds = [] # col_row 将bounds的每一小块继续细分为3行3列,可以防止区域内的搜索数量上限400 col_row = 3 for lst in bounds: distance_lat = (lst[2] - lst[0])/col_row distance_lon = (lst[3] - lst[1])/col_row for i in range(col_row): for j in range(col_row): lst_temp = [] lst_temp.
索引 一、日期时间日期时间截取格式化时间系统时间时间间隔insert日期日期运算 二、字符串字符串拼接字符集转换为char截取字符串字符串变数值正则模式查询 三、空值 null 相关判断是否为空空值 null 排序(Order by 语法) 四、其他条件判断取前几条自增加 一、日期时间 日期时间截取 //oracle TRUNC(date[,fmt])可截取日期和时间 trunc(sysdate, 'mm'); //mysql DATE(date) 只截取日期部分 DATE(datestring) 格式化时间 //oracle TO_CHAR,TO_DATE SELECT TO_CHAR(SYSDATE,'yyyy-MM-dd HH24:mi:ss') FROM dual SELECT TO_DATE('2005-01-01 13:14:20','yyyy-MM-dd HH24:mi:ss') FROM dual //mysql STR_TO_DATE,DATE_FORMAT,CAST //字段类型是varchar,用DATE_FORMAT;字段类型是时间,用STR_TO_DATE SELECT STR_TO_DATE( '2017-02-09 15:25:46.635','%Y-%m-%d %H:%i:%s') FROM DUAL;//字符串转时间类型 SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%S') FROM dual;//时间类型转字符串 SELECT CAST(NOW() AS DATETIME) FROM DUAL 系统时间 //oracle SYSDATE //mysql NOW() 时间间隔 //oracle 两日期间的月份数 MONTHS_BETWEEN //mysql 两日期间的天数 DATEDIFF insert日期 //oracle 需要把时间格式化 //mysql 可直接插入时间字符串 日期运算 //oracle 日期d加上n个月 ADD_MONTHS(d,n) //mysql 日期加上几天或几个小时 DATE_ADD(date,INTERVAL expr type) 二、字符串 字符串拼接 //oracle str1||str2||str3 //mysql concat(str1,str2,…) 字符集转换为char //oracle 参数一:要转换的字符串,参数二:字符串的字符集。 TO_CHAR( string-expression [, source-charset-name ] ) //mysql 如果oracle的TO_CHAR未指定参数二 CAST( string-expression AS CHAR ) 截取字符串 //oracle 截取位置从0开始 substr() //mysql 截取位置从1开始 substr() substring() //从开始位置st截取到最后 substr(str,st) //从位置st截取到位置en substr(str,st,en) 字符串变数值 //oracle TO_NUMBER('123'): //mysql cast( '123' as SIGNED INTEGER) 正则模式查询 //oracle regexp_like() select * from tb where regexp_like(name,’z’); //mysql regexp select * from tb where name regexp ’z’; 三、空值 null 相关 判断是否为空 第一个参数为空,就返回第二个参数
链路层 在链路层中,会讨论到两种截然不同类型的链路层信道。第一种类型是广播信道,这种信道用于连接有线局域网、卫星网和混合光纤同轴电缆( Hybrid Fiber Coaxialcable,HFC)接入网中的多台主机。因为许多主机与相同的广播信道连接,需要所谓的媒体访问协议来协调帧传输。在某些场合中,可以使用中心控制器来协调传输。第二种类型的链路层信道是点对点通信链路,这在诸如长距离链路连接的两台路由器之间,或用户办公室计算机与它们所连接的邻近以太网交换机之间等场合经常能够发现。点到点协议( Point-toPoint Protocol,PPP),该协议的适用范围从经电话线的拨号服务到经光纤链路的高速点到点帧传输。
链路层概述 将运行链路层协议(即第2层)协议的任何设备均称为 结点(node)。结点包括主机、路由器、交换机和WiFi接入点。我们也把沿着通信路径连接相邻结点的通信信道称为 链路(link)。为了将一个数据报从源主机传输到目的主机,数据报必须通过沿端到端路径上的各段链路传输。
链路层提供的服务 尽管任一链路层的基本服务都是将数据报通过单一通信链路从一个结点移动到相邻结点,但所提供的服务细节能够随着链路层协议的不同而变化。链路层协议能够提供的可能服务包括:
成帧( framing)。在每个网络层数据报经链路传送之前,几乎所有的链路层协议都要将其用链路层帧封装起来。一个帧由一个数据字段和若干首部字段组成,其中网络层数据报就插在数据字段中。帧的结构由链路层协议规定。链路接入。媒体访问控制( Medium Access Control,MAC)协议规定了帧在链路上传输的规则。对于在链路的一端仅有一个发送方、链路的另一端仅有一个接收方的点对点链路,MAC协议比较简单(或者不存在),即无论何时链路空闲,发送方都能够发送帧。更有趣的情况是当多个结点共享单个广播链路时,即所谓多路访问问题。这里,MAC协议用于协调多个结点的帧传输。可靠交付。当链路层协议提供可靠交付服务时,它保证无差错地经链路层移动每个网络层数据报。前面讲过,某些运输层协议(例如TCP)也提供可靠交付服务。与运输层可靠交付服务类似,链路层的可靠交付服务通常是通过确认和重传取得的链路层可靠交付服务通常用于易于产生高差错率的链路,其目的是本地(也就是在差错发生的链路上)纠正一个差错,而不是通过运输层或应用层协议迫使进行端到端的数据重传。然而,对于低比特差错的链路,包括光纤、同轴电缆和许多双绞铜线链路,链路层可靠交付可能会被认为是一种不必要的开销。由于这个原因,许多有线的链路层协议不提供可靠交付服务。差错检测和纠正。当帧中的一个比特作为1传输时,接收方结点中的链路层硬件可能不正确地将其判断为0,反之亦然。这种比特差错是由信号衰减和电磁噪声导致的。因为没有必要转发一个有差错的数据报,所以许多链路层协议提供一种机制来检测这样的比特差错。通过让发送结点在帧中包括差错检測比特,让接收结点进行差错检查,以此来完成这项工作。运输层和网络层也提供了有限形式的差错检测,即因特网检验和。链路层的差错检测通常更复杂,并且用硬件实现。差错纠正类似于差错检测,区别在于接收方不仅能检测帧中出现的比特差错,而且能够准确地确定帧中的差错出现的位置(并因此纠正这些差错)。 链路层在何处实现 链路层的主体部分是在网络适配器( network adapter)中实现的,网络适配器有时也称为网络接口卡( Network Interface Card,NC)。位于网络适配器核心的是链路层控制器,该控制器通常是一个实现了许多链路层服务(成帧、链路接入、差错检测等)的专用芯片。因此,链路层控制器的许多功能是用硬件实现的。例如, Intel I的8254x控制器[ Intel2012]实现了以太网协议。
在发送端,控制器取得了由协议较高层生成并存储在主机内存中的数据报,在链路层帧中封装该数据报(填写该帧的各个字段),然后遵循链路接入协议将该帧传进通信链路中。在接收端,控制器接收了整个帧,抽取出网络层数据报。如果链路层执行差错检测,则需要发送控制器在该帧的首部设置差错检测比特,由接收控制器执行差错检测。
尽管大部分链路层是在硬件中实现的,但部分链路层是在运行于主机CPU上的软件中实现的。链路层的软件组件实现了高层链路层功能,如组装链路层寻址信息和激活控制器硬件。在接收端,链路层软件响应控制器中断(例如,由于一个或多个帧的到达),处理差错条件和将数据报向上传递给网络层。所以,链路层是硬件和软件的结合体,即此处是协议钱中软件与硬件交接的地方。
差错检测和纠正技术 比特级差错检测和纠正(bit- level error detection and correotion),即对从一个结点发送到另一个物理上连接的邻近结点的链路层帧中的比特损伤进行检测和纠正,它们通常是链路层提供的两种服务。
在发送结点,为了保护比特免受差错,使用差错检测和纠正比特(Eror- Detection and- Correction,EDC)来增强数据D。通常,要保护的数据不仅包括从网络层传递下来需要通过链路传输的数据报,而且包括链路首部中的链路级的寻址信息、序号和其他字段。
差错检测和纠正技术使接收方有时但并总是检测出已经出现的比特差错。即使采用差错检测比特,也还是可能有未检出比特差错( undetected bit error);这就是说,接收方可能无法知道接收的信息中包含着比特差错。因此,接收方可能向网路层交付一个损伤的数据报,或者不知道该帧首部的某个其他字段的内容已经损伤。因此要选择一个差错检测方案,使得这种事件发生的概率很小。一般而言,差错检测和纠错技术越复杂(即那些具有未检测出比特差错概率较小的技术),导致的开销就越大,这就是意味着需要更多的计算量及更多的差错检测和纠错比特。
在传输数据中检测差错的3种技术:奇偶校验(它用来描述差错检测和纠正背后隐含的基本思想)、检验和方法(它通常更多地应用于运输层)和循环冗余检测(它通常更多地应用在适配器中的链路层)。
奇偶校验 奇偶校验(Parity Check)是一种校验代码传输正确性的方法。根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验。采用奇数的称为奇校验,反之,称为偶校验。采用何种校验是事先规定好的。通常专门设置一个奇偶校验位,用它使这组代码中“1”的个数为奇数或偶数。若用奇校验,则当接收端收到这组代码时,校验“1”的个数是否为奇数,从而确定传输代码的正确性。
采用单个奇偶校验位方式,接收方的操作也很简单。接收方只需要数一数接收的d+1比特中1的数目即可。如果在采用偶校验方案中发现了奇数个值为1的比特,接收方知道至少出现了一个比特差错。更精确的说法是,出现了 奇数个比特差错。其他多维奇偶校验维基百科:Multidimensional parity-check code
工作方式
为了能检测和纠正内存软错误,首先出现的是内存“奇偶校验”。内存中最小的单位是比特,也称为“位”,位只有两种状态分别以1和0来标示,每8个连续的比特叫做一个字节(byte)。不带奇偶校验的内存每个字节只有8位,如果其某一位存储了错误的值,就会导致其存储的相应数据发生变化,进而导致应用程序发生错误。而奇偶校验就是在每一字节(8位)之外又增加了一位作为错误检测位。在某字节中存储数据之后,在其8个位上存储的数据是固定的,因为位只能有两种状态1或0,假设存储的数据用位标示为1、1、1、0、0、1、0、1,那么把每个位相加(1+1+1+0+0+1+0+1=5),结果是奇数。对于偶校验,校验位就定义为1,反之则为0;对于奇校验,则相反。当CPU读取存储的数据时,它会再次把前8位中存储的数据相加,计算结果是否与校验位相一致。从而一定程度上能检测出内存错误,奇偶校验只能检测出错误而无法对其进行修正,同时虽然双位同时发生错误的概率相当低,但奇偶校验却无法检测出双位错误。优缺点
奇偶校验有两种类型:奇校验和偶校验。奇偶校验位是一个表示给定位数的二进制数中1的个数是奇数或者偶数的二进制数,奇偶校验位是最简单的错误检测码。如果传输过程中包括校验位在内的奇数个数据位发生改变,那么奇偶校验位将出错表示传输过程有错误发生。因此,奇偶校验位是一种错误检测码,但是由于没有办法确定哪一位出错,所以它不能进行错误校正。发生错误时必须扔掉全部的数据,然后从头开始传输数据。在噪声很多的媒介上成功传输数据可能要花费很长的时间,甚至根本无法实现。但是奇偶校验位也有它的优点,它是使用一位数据能够达到的最好的校验码,并且它仅仅需要一些异或门就能够生成。奇偶校验被广泛应用。 检验和方法 检验和(checksum),在数据处理和数据通信领域中,用于校验目的地一组数据项的和。它通常是以十六进制为数制表示的形式。如果校验和的数值超过十六进制的FF,也就是255. 就要求其补码作为校验和。通常用来在通信中,尤其是远距离通信中保证数据的完整性和准确性。
步骤
发送方生成检验和
将发送的进行检验和运算的数据分成若干个16位的位串,每个位串看成一个二进制数,这里并不管字符串代表什么,是整数、浮点数还是位图都无所谓。将IP、UDP或TCP的PDU首部中的检验和字段置为0,该字段也参与检验和运算。对这些16位的二进制数进行1的补码和(one’s complement sum)运算,累加的结果再取反码即生成了检验码。将检验码放入检验和字段中。其中1的补码和运算,即带循环进位(end round carry)的加法,最高位有进位应循环进到最低位。反码即二进制各位取反,如0111的反码为1000。 接收方校验检验和
接收方将接收的数据(包括检验和字段)按发送方的同样的方法进行1的补码和运算,累加的结果再取反码。校验,如果上步的结果为0,表示传输正确;否则,说明传输有差错。 检验和算法示例
生成器和promise总结
1.生成器是一种不会在同事输出所有值序列的函数,而是基于每次的请求生成值。
2.不同于标准函数,生成器可以挂起和恢复它们的执行状态。当生成器生成一个值后,它将会在不阻塞主线程的基础上挂起执行,随后静静地等待下次请求。
3.生成器通过在function 后面加一个星号(*)来定义。在生成器函数体内,我们可以使用新的关键字yield来生成一个值并挂起生成器的执行。如果我们想让渡到另一个生成器中,可以使用yield操作符。
4.在我们控制生成器的执行过程中,通过使用迭代器的next方法调用一个生成器,它能够创建一个迭代器对象。除此以外,我们还能够通过next函数向生成器中传入值。
5.promise是计算结果值的一个占位符,它是对我们最终会得到异步结果的一个保证。promise既可以成功也可以失败,一旦设定好了,就不能有更多改变。
6.promise显著地简化了我们处理异步代码的过程。通过使用then方法来生成promise链,我们就能轻易处理异步时序依赖。并行多个异步任务也同样简单:仅使用Promise.all方法即可。
7.通过将生成器和promise相结合能够使用同步代码来简化异步任务。
参考《JavaScript忍者秘籍》