前言部分 大家可以关注我的公众号,公众号里的排版更好,阅读更舒适。
正文部分 行项目达到了999最大编号
sap提供了note解决方案
欢迎到群里下载note
也可以关注我的公众号了解
点击进入:FICO凭证错误:BKPFF$PRDCLN800在FI中达到的项目最大编号
问题来源 在业务系统中,有时候想要知道用户最后一次活动距离现在的时间。记得mysql是有这样的字段的,可以直接在一条记录更新时,自动更新时间。上网查了查,找到了,是timestamp类型。
用法 在表中定义一个timestamp类型的字段,如下所示:
create table test( id integer primary key auto_increment, name varchar(256) not null, createdAt timestamp default current_timestamp on update current_timestamp ); createdAt字段被定义为timestamp类型,而且默认值是当前时间戳,当记录发生更新时,该字段同时会更新为当前时间戳。timestamp等于是提供了对一条对数据自身修改时间的记录。 依据不同的场景,一般timestamp会有几类用法:
在记录创建和修改时都刷新 参见上面的例子,在sql语句上,要同时注明default字段和on update字段。
createdAt timestamp default current_timestamp on update current_timestamp 只在记录创建时刷新时间,以后修改时不再刷新 如下所示,在定义字段时删去on update语句。
createdAt timestamp default current_timestamp 在创建时将字段设置为0,以后修改时刷新 只有on update语句。
createdAt timestamp on update current_timestamp 在创建时给一个定值,修改时刷新 只有on update语句。
createdAt timestamp DEFAULT ‘yyyy-mm-dd hh:mm:ss' on update current_timestamp 这样,在记录发生变化时,可以根据需要记录时间戳。
字段更新值和原值一样的情况 假定我们更新了表的某个字段,例如name属性,createdAt也可以相应刷新。但是有一种情况例外,就是如果更新值和原值一样,mysql出于优化考虑,并不会执行任何操作。此时,为了记录时间,可以强制刷新时间戳。
update table test set name = '<new name>', createdAt = current_timestamp where id = 1; 读取时间戳 如果要读出时间戳,又该怎么使用呢?
前言: 网络视频直播存在已有很长一段时间,随着移动上下行带宽提升及资费的下调, 视频直播被赋予了更多娱乐和社交的属性,人们享受随时随地进行直播和观看, 直播的打开时间和延迟变成了影响产品功能发展重要指标。 注:本文是以原文为主体,加上我自己的一些总结和补充写的 那么,问题来了: 如何实现低延迟、秒开的直播? 先来看看视频直播的5个关键的流程: 录制->编码->网络传输->解码->播放, 每个环节对于直播的延迟都会产生不同程度的影响。 这里重点分析移动设备的情况。 受限于技术的成熟度、硬件环境等,我们针对移动场景简单总结出直播延迟优化的4个点: 网络、协议、编解码、移动终端, 并将分四大块来一一解密UCloud直播云实现低延迟、秒开的技术细节。 一、UCloud直播云实现接入网络优化的技术细节: 1)全局负载均衡-就近接入 实现就近接入的技术比较广为人知,就是CDN即Content Delivery Network (内容分发网络)。 CDN包含两大核心技术: 负载均衡和分发网络。 随着10多年的演进,对负载均衡和分发的实现方式已多种多样, 分发网络的构建策略通常是经过日积月累的总结出一套最合适的分发路由, 并且也不是一成不变,需时刻关注调整,动态运营。 这里重点介绍下CDN的负载均衡技术。 负载均衡是如何实现让用户就近访问的呢? 比较普遍的实现方式:通过用户使用的DNS服务器来判断客户端所在的网络位置, 从而返回对应的服务IP。 如下图示例: Fig-2 广东电信用户IP:1.1.1.1 需要看一个直播http://www.ucloud.cn/helloworld.flv , 实现就近访问的过程是: S1. 用户向配置的DNS服务器1.1.1.0 (通常是运营商指定,也称local DNS,后面简称Ldns)发起www.ucloud.cn 的查询; S2. Ldns 上没有该域名的记录,则往顶级即Root NS上发起查询; S3. Root NS返回告知Ldns该域名的权威解析记录在UCloud NS上; S4. Ldns 向UCloud NS发起查询; S5. UCloud NS 向UCloud GSLB服务发起查询,GSLB发现 Ldns1.1.1.0是属于广东电信; S6. 返回广东电信的就近节节点IP1.1.1.2; S7. 返回1.1.1.2给Ldns; S8. 返回给用户1.1.1.2,用户到1.1.1.2上去获取直播内容。 链路很长, 但是每个Ldns上都会对查询过的域名做合理的缓存, 下一个广东电信的用户再来查询的时候就可以直接返回1.1.1.2。 架构并不复杂,关键点是如何知道Ldns是位于广东电信,这就涉及一个IP地址库。 有开源地址库,也有商业地址库,可以按需求采购即可,一般一年1万左右。 例如,淘宝的IP地址库 淘宝官方ip地址库 http://ip.
刚写完京东爬虫,趁着记忆还深刻,写点总结吧。
一、前提
默认已用scrapy爬取过网站,有爬虫基础,有爬虫环境
二、以爬取电子烟为例
1、任务一:爬取商品信息
在搜索框里面直接搜索电子烟,搜出来的界面,你会发现它是动态加载的。即一开始源代码里面只能看到30条商品的信息,随着你的下拉,另外30条才会加载出来。因此爬取起来比较麻烦。后来发现,从京东左边的商品分类中找到电子烟这一分类
此时的搜索到的电子烟分类的展示网页是一开始就已加载了全部60条商品信息的。商品信息准备从这一页入手。
有爬虫基础的很快就能知道下一步要怎么做了,首先我们需要获得每个商品的信息和链接,称搜索出来的展示页面为搜索页面,进入到商品的详情页面为详情页面。
(1)我们先从搜索页的处理开始
通过抽取<li class="gl-item"> 标签,很快能得到商品的信息。
从搜索页面能抓取到商品的ID,详情页链接,商品名字,店铺名字这些信息。而价钱是动态加载的,注意千万不要被检查(就是chrome通过右键点击检查看到的代码)误解。爬虫爬到的是源代码,检查看到的代码和源代码的代码是不一样的。以源代码为主。
这是检查看到的代码
这是源代码看到的代码
不信可以用爬虫爬取网页试试。所以确定价钱通过网页爬取不到,需要另想办法,先放下。
商品的评论数,你会发现你在搜索页看到的评论数和进入商品详情页看到的评论数不一样,详情页的评论数多一些。因此准备以商品详情页为主,先放下。
搜索页暂时只能爬取到这些信息了。下面进入详情页。
这部分代码如下:
def parse(self, response): # 解析搜索页 sel = Selector(response) # Xpath选择器 goods = sel.xpath('//li[@class="gl-item"]') # print 'goods' # print len(goods) # 总共60条商品信息 for good in goods: item1 = goodsItem() item1['ID'] = good.xpath('./div/@data-sku').extract() item1['name'] = good.xpath('./div/div[@class="p-name"]/a/em/text()').extract() item1['shop_name'] = good.xpath('./div/div[@class="p-shop"]/@data-shop_name').extract() item1['link'] = good.xpath('./div/div[@class="p-img"]/a/@href').extract() url = "http:" + item1['link'][0] + "#comments-list" # print detail yield scrapy.
求字符串操作在shell脚本中很常用,下面归纳、汇总了求字符串的几种可能方法:
【方法一】:利用${#str}来获取字符串的长度
【方法二】:利用awk的length方法
备注:
1) 最好用{}来放置变量
2) 也可以用length($0)来统计文件中每行的长度
【方法三】:利用awk的NF项来获取字符串长度
备注: -F为分隔符,NF为域的个数,即单行字符串的长度
【方法四】:利用wc的-L参数来获取字符串的长度
备注: -L参数
1) 对多行文件来说,表示打印最长行的长度! 82,表示/etc/passwd文件最长行的长度为82
2) 对单行字符串而言,表示当前行字符串的长度!
【方法五】:利用wc的-c参数,结合echo -n参数
备注: 1) -c参数: 统计字符的个数
2) -n参数: 去除"\n"换行符,不去除的话,默认带换行符,字符个数就成了7
【方法六】:利用expr的length方法
【方法七】:利用expr的$str : ".*"技巧
备注: .*代表任意字符,即用任意字符来匹配字符串,结果是匹配到6个,即字符串的长度为6
一、问题原因
1、1NFS客户端某个目录虽然挂载成功NFS服务端的目录,但是NFS客户端挂载目录里并不显示NFS服务端目录下的内容。
1、2NFS客户端某个目录虽然卸载成功NFS服务端的目录,但是NFS客户端挂载目录里依然显示NFS服务端目录下的内容。
二、问题结论
在NFS客户端挂载/卸载NFS服务端目录的时候一定要事先退出挂载目录!挂载/卸载目录之后,再进入挂载目录查看结果!
三、问题展现
3、1测试服务器基本配置
#提供一台NFS客户端,一台NFS服务端。下述不提供NFS安装教程。
#两台机器共同配置为:
[root@web01 ~]# cat /etc/redhat-release CentOS release 6.7 (Final)
[root@web01 ~]# uname -r
2.6.32-573.el6.x86_64
[root@web01 ~]# uname -m
x86_64
#NFS客户端基本配置为:
[root@web01 ~]# ifconfig eth0|awk -F '[ :]+' 'NR==2{print $4}'
10.0.0.8
[root@web01 uploads]# /etc/init.d/iptables status
iptables: Firewall is not running.
[root@web01 uploads]# /etc/init.d/nfs status #注意NFS客户端不开NFS服务 rpc.svcgssd is stopped
rpc.mountd is stopped
nfsd is stopped
rpc.rquotad is stopped
[root@web01 uploads]# /etc/init.d/rpcbind status
rpcbind (pid 22918) is running.
1、DIVCSS5初始化模板
为了兼容各大浏览器,开发案例或项目建议下载使用。使用前先修改预先设置的样式(DIVCSS5初始化模板)。
2、图片素材
主要是使用PS切出所需内容图片素材。(已经放入images文件夹)
三、案例详细代码与效果截图 - TOP 1、CSS代码
ul.imglist{ margin:0 auto; width:536px; overflow:hidden} ul.imglist li{ float:left; padding:4px 8px; width:160px} ul.imglist li img{ display:block; width:160px; height:90px} ul.imglist li span{ display:block; width:100%; height:30px; line-height:30px; background:#F6F6F6} 2、主要HTML代码
<ul class="imglist"> <li> <a href="#" target="_blank"> <img src="images/i160x90.jpg" /> <span>自制快手糟黄瓜 吃完整个</span> </a> </li> <li> <a href="#" target="_blank"> <img src="images/i160x90-2.jpg" /> <span>标题内容 吃完整个</span> </a> </li> <li> <a href="#" target="_blank"> <img src="images/i160x90-3.jpg" /> <span>自制快手糟黄瓜 吃完整个</span> </a> </li> <li> <a href="
网上有传言 微软的深度残差学习是抄袭 Highway Networks,只是Highway Networks的一个特例。Highway Networks 的确是先发表的。
http://people.idsia.ch/~rupesh/very_deep_learning/
有开源代码
reference: http://blog.csdn.net/cv_family_z/article/details/50349436
http://blog.csdn.net/l494926429/article/details/51737883
Our Highway Networks take inspiration from Long Short Term Memory (LSTM) and allow training of deep, efficient networks (even with hundreds of layers) with conventional gradient-based methods. Even when large depths are not required, highway layers can be used instead of traditional neural layers to allow the network to adaptively copy or transform representations
我们这个高速CNN网络受 LSTM启发,可以使用传统基于梯度的方法快速训练深度网络(几百层的)。即使不需要大的深度,高速网络也可以自适应表示合适的特征变换。
随着神经网络的发展,网络的深度逐渐加深(更深的层数以及更小的感受野,能够提高网络分类的准确性(Szegedy et al.
## MarkDown本地编辑器的选择 最近更新,两个月前使用小书匠的时候打开一直处于加载界面进不去,就放弃了该软件转而使用有道笔记,目前有道笔记支持MarkDown另存本地,所以在此推荐有道笔记。 csdn支持在线markdown,但是有时候可能在本地写好后再上传,于是就去找合适的编辑器。 首先是很多人推荐的MarkDownPad2,官网地址:MarkDownPad2官网地址。下载安装后报错,尝试了几次都有问题,然后放弃了。你可以试一试看能不能用。 然后找到了一款很不错的,这篇blog就是用这个编辑器的处女作。点击–小书匠 附上其他供测试: 列表:
1. List item - 二级目录
我们都是好孩子 文字斜体正常字 文字粗体正常字
苹果
:一种水果 水平线 注意: 使用list后连续两次空格后可以退出list模式。
1.首先按windows+R键进入运行程序,或者通过开始菜单进入运行,输入cmd命令,回车 2.输入netstat -ano回车,查找你要找的端口号:如我要找的是8080端口,因为我在配置java开发环境tomcat时,登录http://localhost:8080总是打不开这个地址,提示404错误,而我将tomcat配置成端口为8088时,就没问题,这就说明我的8080端口被占用了。 在结果中找到8080端口对应的PID号是4936,再打开windows任务管理器,找到4936进行对应的进程,把它杀掉就OK了。
图像矩阵的shape属性表示图像的大小,shape会返回tuple元组,第一个元素表示矩阵行数,第二个元组表示矩阵列数,第三个元素是3,表示像素值由光的三原色组成。
import cv2 import numpy as np fn="baboon.jpg" if __name__ == '__main__': print 'load %s as ...' % fn img = cv2.imread(fn) sp = img.shape print sp sz1 = sp[0]#height(rows) of image sz2 = sp[1]#width(colums) of image sz3 = sp[2]#the pixels value is made up of three primary colors print 'width: %d \nheight: %d \nnumber: %d' %(sz1,sz2,sz3) 运行结果: load baboon.jpg as … (512, 512, 3) width: 512 height: 512 number: 3
1、getMethods返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口的公共 member 方法。 2、getDeclaredMethods返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
也就是说getDeclaredMethods能拿到所有(不包括继承的方法),而getMethods只能拿到public方法(包括继承的类或接口的方法)
还有只得注意的是这两个方法返回的数组中的元素的顺序是无序的,它和你在类中定义方法的顺序无关
一、为何使用内部类 内部类提供了更好的封装,只有外部类能访问内部类 内部类可以独立继承一个接口,不受外部类是否继承接口影响内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private 利于回调函数的编写 一个内部类的例子:
public class OuterClass { private String outerName; private int outerAge; public class InnerClass{ private String innerName; private int innerAge; } } 二、内部类与外部类的联系 2.1 内部类是一个相对独立的实体,与外部类不是is-a关系 内部类是一个编译时概念,编译后外部类及其内部类会生成两个独立的class文件: OuterClass.class和OuterClass$InnerClass.class,我用javac编译器对上面的OuterClass进行编译:
D:\>javac OuterClass.class 编译后的结果:
2.2 内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素 public class OuterClass { private String outerName; private int outerAge; public class InnerClass{ private int innerName; InnerClass(){ //内部类可以访问外部类的元素 outerName="I am outer class"; outerAge=23; } public void display(){ System.out.println(outerName+" and my age is "+outerAge); } } public static void main(String[] args) { OuterClass outerClass = new OuterClass(); OuterClass.
点击打开链接
由于网友的需求,我把本站【领悟书生教程网】的文章分页代码分享给各位,代码比较简单,在使用的过程中如果有什么不明白可以找我,同时希望各位提出诚恳的意见 分页效果
首先来看看分页工具类PageUtil.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 package com.
本文参考了: https://github.com/BVLC/caffe/wiki/Ubuntu-16.04-or-15.10-Installation-Guide https://gist.github.com/wangruohui/679b05fcd1466bb0937f#file-caffe-ubuntu-15-10-md http://blog.csdn.net/g0m3e/article/details/51420565
前言: 本文是基于已经成功安装了python各种常用包、opencv、cuda
安装过程 1、首先安装各种更新包 sudo apt-get update sudo apt-get upgrade sudo apt-get install -y build-essential cmake git pkg-config sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler sudo apt-get install -y libatlas-base-dev sudo apt-get install -y --no-install-recommends libboost-all-dev sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev sudo apt-get install -y python-pip sudo apt-get install -y python-dev sudo apt-get install -y python-numpy python-scipy sudo apt-get install -y libopencv-dev 2、下载caffe cd ~ mkdir git //在home下新建一个git文件夹,用来存放那些从github上git下来的文zong件 git clone https://github.
<a href="#" id="imgId"><img width="50" height="50" src="xxx.gif" id="test"></a> <script> var imgId=document.getElementById("imgId"); var $img=imgId.getElementsByTagName("img")[0]; $img.onload = function(){ imgSize.call($img); }; function imgSize(){ var imgObj = new Image(); imgObj.src = this.src; alert(imgObj.width + "\n" + imgObj.height); } </script>
最近不断有朋友向我咨询AndroidStudio多渠道的打包方法,今天整理一下之前积累的打包套路,写一篇文章,手把手的教给大家。 说到多渠道,这里不得不提一下友盟统计,友盟统计是大家日常开发中常用的渠道统计工具,而我们的打包方法就是基于友盟统计实施的。按照友盟官方文档说明,渠道信息通常需要在AndroidManifest.xml中配置如下值:
<meta-data android:value="Channel ID" android:name="UMENG_CHANNEL"/> 上面的value值Channel_ID就是渠道标识。我们的期望的就是在编译时候这个值能够自动变化以满足区分多渠道的需求。
(一)在AndroidManifest.xml里设置动态渠道变量 <meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" /> (二)在build.gradle设置productFlavors 这里假定我们需要打包的渠道为酷安市场、360、小米、百度、豌豆荚 android { productFlavors { kuan { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "kuan"] } xiaomi { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"] } qh360 { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qh360"] } baidu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] } wandoujia { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"] } } } 或者批量修改
android { productFlavors { kuan {} xiaomi {} qh360 {} baidu {} wandoujia {} } productFlavors.
相关框架
JUnit4、Mockit、PowerMock
相关maven依赖
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.6.5</version> <scope>test</scope> </dependency> 代码base 后面的测试代码均是针对下面class的
import org.springframework.beans.factory.annotation.Autowired; public class UserController { @Autowired private UserService userService; public boolean addUser(UserDto userDto) { int added = userService.addUser(userDto); if (added <= 0) { return false; } else { return true; } } public boolean delUser(int id) { try { userService.delUser(id); return true; } catch (Exception e) { return false; } } public void saveUser(UserDto userDto) { userService.
echo 'main(){}'|arm-xilinx-linux-gnueabi-gcc -E -v -
看到如下输出内容
Using built-in specs.
COLLECT_GCC=arm-xilinx-linux-gnueabi-gcc
COLLECT_LTO_WRAPPER=/home/ding/xilinx/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/../libexec/gcc/arm-xilinx-linux-gnueabi/4.6.1/lto-wrapper
Target: arm-xilinx-linux-gnueabi
Configured with: /scratch/janisjo/2011.09-xilinx-linux/src/gcc-4.6-2011.09/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-xilinx-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --enable-extra-sgxxlite-multilibs --with-arch=armv5te --with-cpu=cortex-a9 --with-float=softfp --with-fpu=neon-fp16 --disable-multilib --with-gnu-as --with-gnu-ld --with-specs='%{save-temps: -fverbose-asm} %{funwind-tables|fno-unwind-tables|mabi=*|ffreestanding|nostdlib:;:-funwind-tables} -D__CS_SOURCERYGXX_MAJ__=2011 -D__CS_SOURCERYGXX_MIN__=9 -D__CS_SOURCERYGXX_REV__=50 %{O2:%{!fno-remove-local-statics: -fremove-local-statics}} %{O*:%{O|O0|O1|O2|Os:;:%{!fno-remove-local-statics: -fremove-local-statics}}}' --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --with-pkgversion='Sourcery CodeBench Lite 2011.09-50' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-xilinx-linux-gnueabi/libc --with-build-sysroot=/scratch/janisjo/2011.09-xilinx-linux/install/arm-xilinx-linux-gnueabi/libc --with-gmp=/scratch/janisjo/2011.09-xilinx-linux/obj/host-libs-2011.09-50-arm-xilinx-linux-gnueabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/janisjo/2011.09-xilinx-linux/obj/host-libs-2011.09-50-arm-xilinx-linux-gnueabi-i686-pc-linux-gnu/usr --with-mpc=/scratch/janisjo/2011.09-xilinx-linux/obj/host-libs-2011.09-50-arm-xilinx-linux-gnueabi-i686-pc-linux-gnu/usr --with-ppl=/scratch/janisjo/2011.09-xilinx-linux/obj/host-libs-2011.09-50-arm-xilinx-linux-gnueabi-i686-pc-linux-gnu/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-cloog=/scratch/janisjo/2011.09-xilinx-linux/obj/host-libs-2011.09-50-arm-xilinx-linux-gnueabi-i686-pc-linux-gnu/usr --with-libelf=/scratch/janisjo/2011.09-xilinx-linux/obj/host-libs-2011.09-50-arm-xilinx-linux-gnueabi-i686-pc-linux-gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/janisjo/2011.09-xilinx-linux/install/arm-xilinx-linux-gnueabi/bin --with-build-time-tools=/scratch/janisjo/2011.09-xilinx-linux/install/arm-xilinx-linux-gnueabi/bin
Thread model: posix
在Linux环境下编一个工程,无论怎么编译总是出现错误,提示如下: bmeta_info.cpp:4280: undefined reference to `crypt’ collect2: ld returned 1 exit status
网上查的资料表示:
Undefined reference to 错误:这类错误是在连接过程中出现的,可能有两种原因∶一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这 需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有 给定相应的函数库的名称,或者是该档案库的目录名称有问题
使用 man crypt命令后从中找到如下信息:
GNU EXTENSION The glibc2 version of this function has the following additional features. If salt is a character string starting with the three characters "$1$" followed by at most eight characters, and optionally terminated by "$", then instead of using the DES machine, the glibc crypt function uses an MD5-based algorithm, and outputs up to 34 bytes, namely "
String的split()的两种方法 public String[] split(String regex) 该方法就是给定的表达式和限制参数0来调用两参数split方法。 public String[] split(String regex,int limit) 规定:使用regex进行字符串切割称为模式匹配 参数regex: 1.如果表达式不匹配输入的任何内容,返回的数组只具有一个元素,即此字符串。(尤其注意空字符串这种情况,他也是一个字符串) 2.可以匹配的情况下,每一个字符串都由另一个匹配给定表达式的子字符串终止,或者由此字符串末尾终止(数组中的字符串按照他们在此字符串出现的顺序排列) 参数:limit: 该参数用于控制模式匹配使用的次数,可以影响到数组的长度 1.limit>0: 模式匹配将被最多应用n-1次,数组的长度将不会大于n,数组的最后一项将包含所有超出最后匹配的定界符的输入。 2.limit<0: 模式匹配将应用尽可能多的次数,而且数组的长度是任何长度。 3.lilmit=0: 模式匹配将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。 对 “boo:and:foo”进行分割(注意空字符串的使用) regexlimitresult:2{“boo”,”and:foo”}:5{“boo”,”and”,”foo”}:-2{“boo”,”and”,”foo”}o5{“b”,”“,”:and:f”,”“,”“}o-2{“b”,”“,”:and:f”,”“,”“}o0{“b”,”“,”:and:f”}
点击打开链接
问题描述 在用springmvc开发应用程序的时候。对于像我一样的初学者,而且还是自学的人,有一个很头疼的问题。那就是数据都已经查出来了,但是页面的样式仍然十分简陋,加载不了css.js,图片等资源文件,如果你输入某个css的文件在浏览器中得到的直接是404错误(例如http://localhost:8080/iMax_view/css/classify.css),表示路径肯定没有错,这是因为你在web.xml中配置的springservlet
<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- springmvc前端控制器,rest配置 --></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">servlet</span>></span> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">servlet-name</span>></span>springmvc_rest<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"
/** * Implement this method to handle generic motion events. * 实现该方法来处理一般的MotionEvent; * 一般的motion events 描述,操纵杆的动作,鼠标honver、滚轮等 * * @param event The generic motion event being processed. * @return True if the event was handled, false otherwise. */ @Override public boolean onGenericMotionEvent(MotionEvent event) { //The input source is a pointing device associated with a display. //输入源为可显示的指针设备,如:mouse pointing device(鼠标指针),stylus pointing device(尖笔设备) if (0 != (event.getSource() & InputDevice.SOURCE_CLASS_POINTER)) { switch (event.getAction()) { // process the scroll wheel movement…处理滚轮事件 case MotionEvent.
用一个简单的实例带大家走进遗传算法的神奇世界。
问题描述:
求下面二元函数的最大值:
遗传算法主要核心包括:编码,初始种群的产生,适应度计算,选择算子,交叉算子,变异算子。
这个示例中采用二进制编码,x1,x2的范围在[1-7]直接,可以选择3位二进制进行编码,3为二进制编码刚好和每个数字对应。适应度计算,可以采取目标函数f(x1.x2),算法具体实现如下:
import java.util.ArrayList; import java.util.Collections; import java.util.Random; /** * Created by yaobo on 2016/6/20. */ public class GAMAX { public static int MaxGen=1000;//最大遗传代数 public static int generate;//全局变量,控制循环的代数 double Pc=0.7;//交叉概率 double Pm=0.05;//变异概率 int Chromlenth=6;//染色体长度 int scale=10;// 种群规模 int everchromlength=3;//变量的编码长度 int bestIndex;//当前代最好个体的索引 int worstIndex;//当前代最坏个体的索引 Individual bestIndividual;//当前代最好的个体 Individual worstIndividual;//当前代最坏的个体 Individual currentBest=new Individual(); static double Rs=00.;//保存出现最好结果值 static int Rsindex=-1;//保存出现最好结果的代数 Individual[] population=new Individual[scale];//定义数组保存种群 Random random=new Random();//随机函数 public static void main(String[] args) { GAMAX gamax=new GAMAX(); generate=0;//从0代开始 gamax.
http://www.cnblogs.com/zziss/archive/2012/02/13/2350032.html
API级别是什么
当你开发你的Android应用程序时,了解该平台API变更管理的基本方法和概念是很有帮助的。同样的,知道API级别标识以及该标识如何保障你的应用与实际硬件设备相兼容对于开发及后续的发布、维护都是有益的。API级别是一个整数值,它唯一标识了一个具体版本的Android平台,及其框架的API的版本。
Android平台提供了一套框架API,使得应用程序可以与系统底层进行交互。该框架API由以下模块组成:
一组核心的包和类 清单(manifest)文件的XML元素和属性声明 资源文件的XML元素和属性声明及访问形式 各类意图(Intents) 应用程序可以请求的各类授权,以及系统中包含的授权执行 每个Android平台的后续版本会包括它提供的更新的Android应用程序框架的API。
该框架的API的更新设计,使高版本的API与早期版本兼容。也就是说,在新版本API中大多数都是新增功能,和引进新的或替代的功能。作为API的部分升级,老的替换的部分已过时,但不会从新版本中删除,使得已有的应用程序仍然可以使用它们。在极少数情况下,旧版本API的部分可能被修改或删除,通常这种变化是为了保障API的稳定性及应用程序或系统的安全。所有其他早期版本的API将不做修改的保留。
一个Android平台提供的框架API,被指定一个整数标识符,称为“API级别”。每一个版本的Android平台只支持有一个API级别,虽然该支持是隐含地包括了所有早期的API级别(一直到API级别1级)。 Android平台的最初版本提供的框架API级别是1级,随后的版本依次递增。
下表说明了具体平台版本和支持的API级别的对应关系。
平台版本
API级别
Android 3.0
11
Android 2.3.3
10
Android 2.3
9
Android 2.2
8
Android 2.1
7
Android 2.0.1
6
Android 2.0
5
Android 1.6
4
Android 1.5
3
Android 1.1
2
Android 1.0
1
在Android中使用API级别
API级别标识为保证用户和应用程序开发者的最佳体验,起了关键作用:
它让Android平台可以描述它支持的框架API的最高版本 它让应用程序可以描述它需要的框架API版本 它使得系统可以在硬件设备上安装应用程序时能够检查版本是否匹配,使得版本不兼容的应用程序不会被错误安装在设备之上. 每个版本的Android平台都在其内部存储了自己的API级别标识。
应用程序可以用框架API提供的清单文件元素 — 来描述该应用程序可以运行的最小和最大API级别,以及应用程序开发者设计期望运行的平台版本。三种属性分别描述如下:
android:minSdkVersion — 指明该应用程序可以运行的API最低版本。默认是“1”。 android:targetSdkVersion — 指明该应用程序设计时期望运行的目标API版本。这允许应用程序使用目标API级别下定义的清单元素或行为,而不是只限于使用最低API级别定义的内容。 android:maxSdkVersion — 指明该应用程序可以运行的最高API级别。 用户尝试安装一个应用程序,或者在系统升级后重验证应用程序的时候,Android系统首先会检查应用程序的清单文件中的属性,将其与系统内部API级别对比。系统只有在满足下列情况时才允许进行应用程序安装:
如果声明了android:minSdkVersion属性,其属性值必须小于或等于该系统的API级别对应的整数值。如果未声明,系统会默认该应用程序运行需要的最低API级别是1。 如果声明了android:maxSdkVersion属性,其属性值必须等于或大于该系统的API级对应的整数值。如果未声明,系统会默认该应用程序没有最高API级别限制。 应用程序清单文件中声明该属性后, 元素看起来应类似于下面的例子:
源文件 /* * hello.c */ #include <linux/init.h> #include <linux/module.h> static int hello_init(void) { printk(KERN_ALERT "hello, world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("Dual BSD/GPL"); Makefile文件 ifneq ($(KERNELRELEASE),) obj-m := hello.o else KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif
var now = new Date();
var date = now.getFullYear() + "-" + ((now.getMonth() + 1) < 10 ? "0" : "") + (now.getMonth() + 1) + "-" + (now.getDate() < 10 ? "0" : "") + now.getDate();
一、位置参数 调用函数时根据函数定义的参数位置来传递参数。
#!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_dict = {1: u'先生', 2: u'女士'} print 'hello %s %s, welcome to python world!' %(name, sex_dict.get(sex, u'先生')) # 两个参数的顺序必须一一对应,且少一个参数都不可以 # print_hello('tanggu', 1) 二、关键字参数 用于函数调用,通过“键-值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
# 以下是用关键字参数正确调用函数的实例 # print_hello('tanggu', sex=1) # print_hello(name='tanggu', sex=1) # print_hello(sex=1, name='tanggu') # 以下是错误的调用方式 # print_hello(1, name='tanggu') # print_hello(name='tanggu', 1) # print_hello(sex=1, 'tanggu') 通过上面的代码,我们可以发现:有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序的
三、默认参数 用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
# 正确的默认参数定义方式--> 位置参数在前,默认参数在后 def print_hello(name, sex=1): .... # 错误的定义方式 def print_hello(sex=1, name): .
最近和几个朋友交流Android开发中的网络下载问题时,谈到了用Thread开启下载线程时会产生的Bug,其实直接用子线程开启下载任务的确是很Low的做法,那么原因究竟如何,而比较高大上的做法是怎样?于是用这篇博文详细分析记录一下。
一、概念介绍
Thread是指在CPU运行的一个程序中,可以有多个执行路径。运行的程序称作进程,而这个执行路径,就被称为线程(如果对这两个名词不太理解的同学可以参考一下操作系统方面的书籍)。Java中的多线程是指多个Thread可以在一段内同步执行,这样可以提高代码的运行效率,Java中允许一个进程有多个线程,可以无限多,但是必须要有一个线程,也就是当前进程的主线程。
必须要明白的一点是,Thread是Java语言下的一个底层类,而Android是使用并封装了Java语言的系统,所以Android中的AsyncTask只是使用了Java的多线程概念并优化封装之后的一个抽象类。所以Thread和AsyncTask完全是两个不同层次的概念,而不是简单的替换。
再说说AsyncTask异步任务,这个类是在Android中使用的,在编写该类时就已经明确说明,“AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs”,后边的不重要就不用粘贴了,可以看出异步任务进行长时间操作时使用的。因为Android中对每一个App的运行都看做一个进程,而这个进程中的主线程,就是UI线程,也就是我们打开一个App时可以看到界面的这个线程。而像下载这种耗时操作,如果放到UI线程执行,则会使得UI线程负荷过大产生ANR应用无响应异常,所以创建了AsyncTask类,用来专门进行一些耗时的非UI更新操作。
通过上面的介绍,很容易想到AsyncTask是使用了Java中的多线程技术的,但是他不是单纯的Thread,具体是怎么实现异步任务的,我们可以看源码比较。
Thread类是在java.lang包下的,所以他的使用不需要另外导包,而且Thread是实现Runnable接口的类,也就是说他可以实例化;由于Thread是底层代码,具体源码就不再分析了,所以主要说一下AsyncTask怎么用Thread实现的异步任务。
AsyncTask类是在android.os包下的抽象类,在使用之前必须导包。AsyncTask是使用线程工厂创建新的线程在后台执行异步任务的,之前我们说个Android中有一个UI线程作为主线程,那么再创建的线程都是子线程了,至于新创建的这些子线程做了什么事情,就要看我们的意愿了。
二、下载分析:
介绍了半天两个类的对比,感觉还是直接上Demo来的快一点。下边我分别用开启子线程和开启异步两种方式实现下载,同时简单分析一下这两种方式下的CPU执行顺序。
1. 在当前Activity中开启子Thread执行下载
(1)创建下载子线程:
问题来源 想在买的VPS上搭点博客服务,偏爱于动态博客之类的,选用了nodejs,范围一下就减小了,一开始看中了N-blog。需要安装bower,如果在安装的时候,一直提示npm版本问题:
npm WARN deprecated This version of npm lacks support for important features, npm WARN deprecated such as scoped packages, offered by the primary npm npm WARN deprecated registry. Consider upgrading to at least npm@2, if not the npm WARN deprecated latest stable version. To upgrade to npm@2, run: npm WARN deprecated npm WARN deprecated npm -g install npm@latest-2 npm WARN deprecated npm WARN deprecated To upgrade to the latest stable version, run: npm WARN deprecated npm WARN deprecated npm -g install npm@latest npm WARN deprecated npm WARN deprecated (Depending on how Node.
1.原理
Nginx解析location/后面的字符串,配置不同的字符串匹配不同的URL进行反向代理。
2.nginx.conf配置文件
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 2016; server_name localhost; location / { root html; index index.html index.htm; } location /yyxtManager { proxy_pass http://10.56.6.13:6667/yyxtManager; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /jrtxManager { proxy_pass http://10.56.6.13:6666/jrtxManager; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /hytpay { proxy_pass http://10.
Android 开发中经常遇到各种hdpi,xhdpi,xxhdpi....很多尺寸大小的png图片要求.
网上也有不少工具,今天我又发现一款在线转换大小的网站,用了一下,一个png 114X114 转换成 16X16和512X512效果还可以;
连接在这里,希望需要的mark一下,么么
png工具类网站:http://images.my-addr.com/resize_png_online_tool-free_png_resizer_for_web.php
项目地址 : https://github.com/zhonggaorong/QQLoginDemo/tree/master
最新版本的qq登录实现步骤实现:
1. 首先,你需要去向腾讯申请账号。 地址:点击打开链接 2. 下载最新的SDK 地址: SDK下载 SDK内容如下:
1. doc: 为说明文档, 方法参数说明。
2.sample 这个是简单的demo
3. TencentOpenApi_IOS_Bundle.bundle 资源文件包
4. TencentOpenApi.framework 核心开发框架
接下来就进入正题:
1. 项目配置,手把手教学: 1. 新建一个工程。 2. 把TencentOpenApi.framework 和 TencentOpenApi_IOS_Bundle.bundle 拖入工程。 3. 配置项目。 3.1 添加依赖库: 3.2 在工程配置中的“Build Settings”一栏中找到“Linking”配置区,给“Other Linker Flags”配置项添加属性值“-fobjc-arc” 3.3 URLScheme 配置: 3.4 针对ios9以后,需要添加白名单。 在info.plist文件中加入 LSApplicationQueriesSchemes 对应的info.plist 的source code 为
<key>LSApplicationQueriesSchemes</key> <array> <string>mqqapi</string> <string>mqq</string> <string>mqqOpensdkSSoLogin</string> <string>mqqconnect</string> <string>mqqopensdkdataline</string> <string>mqqopensdkgrouptribeshare</string> <string>mqqopensdkfriend</string> <string>mqqopensdkapi</string> <string>mqqopensdkapiV2</string> <string>mqqopensdkapiV3</string> <string>mqzoneopensdk</string> <string>wtloginmqq</string> <string>wtloginmqq2</string> <string>mqqwpa</string> <string>mqzone</string> <string>mqzonev2</string> <string>mqzoneshare</string> <string>wtloginqzone</string> <string>mqzonewx</string> <string>mqzoneopensdkapiV2</string> <string>mqzoneopensdkapi19</string> <string>mqzoneopensdkapi</string> <string>mqzoneopensdk</string> </array> 3.
最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜索了很多相关介绍性的文档,发现国内百度上却很少有相关类文档,觉得有必要来梳理一下:
ld-linux.so.2 是linux下的动态库加载器/链接器,这篇文章主要来讲一下 ld-linux.so.2 是如何和Linux 以及相关应用打交道的。
1. 什么是 ld.linux.so ? 很多现代应用都是通过动态编译链接的,当一个 需要动态链接 的应用被操作系统加载时,系统必须要 定位 然后 加载它所需要的所有动态库文件。 在Linux环境下,这项工作是由ld-linux.so.2来负责完成的,我们可以通过 ldd 命令来查看一个 应用需要哪些依赖的动态库:
$ ldd `which ls` linux-gate.so.1 => (0xb7fff000) librt.so.1 => /lib/librt.so.1 (0x00b98000) libacl.so.1 => /lib/libacl.so.1 (0x00769000) libselinux.so.1 => /lib/libselinux.so.1 (0x00642000) libc.so.6 => /lib/libc.so.6 (0x007b2000) libpthread.so.0 => /lib/libpthread.so.0 (0x00920000) /lib/ld-linux.so.2 (0x00795000) libattr.so.1 => /lib/libattr.so.1 (0x00762000) libdl.so.2 => /lib/libdl.so.2 (0x0091a000) libsepol.so.1 => /lib/libsepol.so.1 (0x0065b000) 当最常见的ls小程序加载时,操作系统会将 控制权 交给 ld-linux.
一、什么是指代消解? 1、指代的基本概念 指代作为一种常见的语言现象,广泛存在于自然语言的各种表达中。
eg:***俄罗斯总统*** 在德国发表讲话时表示:“我们不排除中油集团参 与已拍卖的尤甘斯克的生产。”***他*** 表示,中油集团没有参加这次拍卖 中文的指代主要有以下三种典型的形式【1】: 1.人称代词(Pronoun) 【李明】怕高妈妈一人呆在家里寂寞,【他】便将家里的电视搬了过来。 2.指示代词(Demonstrative) 【很多人都想创造一个美好的世界留给孩子】,【这】可以理解,但不完全正确 3.有定描述(Definite Description) 【贸易制裁】似乎成了【美国政府在对华关系中惯用的大棒】。然而,这【大棒】果真如美国政府所希望的那样灵验吗?
一般代词消解和早期的指代消解(Anaphora Resolution)指的是对显性代词消解算法的研究,再后来指代消解包含并开始侧重于共指(Coreference,也称同指)消解的研究,之后指代消解又添加了零代词的内容。我的研究重点可能是问答系统中的指代消解,所以侧重于显性代词和零代词消解,对共指划分只做简单介绍,后文不强调是零代词的内容均指显性代词消解。
显性代词消解 是指当前的照应语与上下文出现的词、短语或句子(句群)存在密切的语义关联性,指代依存于上下文语义中,在不同的语言环境中可能指代不同的实体,具有非对称性和非传递性 零代词消解 是恢复零代词指代前文语言学单位的过程,有时也被称为省略恢复 共指消解 主要是指两个名词(包括代名词、名词短语)指向真实世界中的同一参照体,这种指代脱离上下文仍然成立
1.1 显性代词消解 所谓显性代词消解,就是指在篇章中确定显性代词指向哪个名词短语的问题,代词称为指示语或照应语(Anaphor),其所指向的名词短语一般被称为先行语(Antecedent),根据二者之间的先后位置,可分为回指(Anaphora)与预指(Cataphora),其中:如果先行语出现在指示语之前,则称为回指,反之则称为预指。
1.2 零代词消解 所谓零代词消解,是代词消解中针对零指代(Zero Anaphora)现象的一类特殊的消解。在篇章中,用户能够根据上下文关系推断出的部分经常会省略,而省略的部分(用零代词(Zero Pronoun)表示)在句子中承担着相应的句法成分,并且回指前文中的某个语言学单位。零指代现象在中文中更加常见,(中华语言博大精深。。)近几年随着各大评测任务的兴起开始受到学者们的广泛关注。
1.3 共指消解 所谓共指消解,是将篇章中指向同一现实世界客观实体(Entity)的词语划分到同一个等价集的过程,其中被划分的词语称为表述或指称语(Mention),形成的等价集称为共指链(Coreference Chain)。在共指消解中,指称语包含:普通名词、专有名词和代词,因此可以将显性代词消解看作是共指消解针对代词的子问题。 共指消解与显性代词消解不同,它更关注在指称语集合上进行的等价划分,评测方法与显性代词消解也不近相同,通常使用MUC、B-CUBED、CEAF和BLANC评价方法。
指代消解的研究方法大致可以分为基于启发式规则的、基于统计的和基于深度学习的方法,目前看来,基于有监督统计机器学习的消解算法仍然是主流算法。
Reference 【1】.王厚峰.指代消解的基本方法和实现技术【J】.中文信息学报,2002,16(6):9—17
服务稳定性的实现方案: 依赖管理&服务分级&优雅降级&开关&应急预案
ubuntu和windows一样,可以任意创建或者删除新的用户,windows下比较简单,ubuntu下需要使用命令,不过操作起来不是很繁琐,所以我尽量写的详细一些。
如何创建ubuntu新用户?
首先打开终端,输入:sudo adduser username,系统会提示以下信息:
正在添加用户“username”...
正在添加新组“username”(1001)...
正在添加新用户“username”(1001)到组“username”...
创建主目录“/home/username”...
正在从“/etc、skel”复制文件...
输入新的 UNIX 口令:(此处大家注意,不是输入你当前用户的密码,而是输入你要创建新用户的密码)
重新输入新的 UNIX 口令:(再输一次即可)
passwd:已成功更新密码
Changing the user information for username
Enter the new value, or press ENTER for the default
Full Name []: yangyang (输入新用户的名称)
Room Number []:
Work Phone []:
Home Phone []:
Other []:
这个信息是否正确? [Y/n] y
到了这一步,新用户已经添加成功了,此时我们可以打 ls /home查看一下,如果显示 username yangming,侧代表用户创建成功。如图1所示。
图1
到此,用户添加成功。如果需要让此用户有root权限,执行命令: root@ubuntu:~# sudo vim /etc/sudoers 修改文件如下: # User privilege specification root ALL=(ALL) ALL db ALL=(ALL) ALL 保存退出,db用户就拥有了root权限。
使用 Linux 工具进行计算机取证
本文通过介绍 Linux 系统工具(Ftkimage、xmount、Volatility、dd、netcat)来介绍使用计算机取证的方法和步骤。 硬盘数据的取证是指为了证据保全,确保取证工作造成数据丢失,在获取到证据介质后,首先要做的就是对介质数据进行全盘镜像备份。内存取证主要通过对内存数据及其缓存硬盘数据进行分析,提取那些对案件侦破可能有重要意义的易失性数据,这些易失性数据的特点是存在于正在运行的计算机或网络设备的内存中,关机或重启后这些数据将不再存在。
0x00前言
计算机取证过程中要用到很多工具 , 根据取证工具的用途, 主要可以将取证工具分为三大类:第一类是磁盘文件取证复制工具, 第二类是内存文件取证工具,第三类是取证分析工具。尽管很多商业工具都是在 Windows 环境中开发的,但是 Linux 平台还是获得了自己的一席之地,因为 Linux 包含了非常强大的工具,这些工具对取证调查是非常有帮助的,L本文主要介绍 Linux 环境下的磁盘和内存取证工具包括 Ftkimage、xmount、Volatility、dd、netcat 等。
0x01磁盘取证简介
一般来说取证就是收集并分析证据,并为司法行动中的展示构建事实的一个过程。但在计算机技术中,或在计算机取证技术中,取证就是通过专门的技术来发现证据的过程,这些证据可被用于确认计算机、计算机网络、相关设备、数据存储媒体是否被用于实施犯罪或未授权的活动。在计算机的取证领域中,取证人员在取证调查的整个过程中证明证据媒体没有在任何方面被篡改是至关重要的。其中一种方法是对原始的证据媒体作一个映象复制,并对映象复制品展开调查,以防止对原始证据的任何更改。本文介绍磁盘取证工具的平台是 Fedora 21 x64 系统。
1镜像工具 dd
计算机取证时需要为计算机生成一个位镜像, 这个操作要在系统还在运行的时候或在系统关闭之前进行。最常使用的就是两个工具: dd 和 netcat(两者都是开源软件安装非常简单这里从略)。dd 为我们生成磁盘的位镜像文件,而 netcat 将拷贝通过网络传送出去。你需要一台联网的电脑来接收该镜像文件,而且该电脑需要有足够的空间来存放镜像文件。
复制/dev/sdc 到文件 cyqdrive.dd 中。将文件分割成多个 1GB 大小的文件。读取错误时,忽略该错误而不停止拷贝行为。这个例子命令如下:
#dd if=/dev/sdc split=1G of=cyqdrive.dd
刚才已经展示如何创建一个磁盘镜像,但只是创建镜像到系统的本地文件。但是当当前的物理空间不足时就要使用 netcat 来将 dd 命令的的输出通过网络连接进行重定向。首先在目标服务器上,启动 netcat 作为一个监听,并将输出重定向到一个远程服务器上的文件。我会用 netcat 监听 TCP 的 3452 端口,并将镜像写入一个远程的文件 cyqimage.dd。
#nc -l -p 3452 > myimage.dd
转自:http://blog.csdn.net/shuzfan/article/details/51338178
“Xavier”初始化方法是一种很有效的神经网络初始化方法,方法来源于2010年的一篇论文
《Understanding the difficulty of training deep feedforward neural networks》
可惜直到近两年,这个方法才逐渐得到更多人的应用和认可。
为了使得网络中信息更好的流动,每一层输出的方差应该尽量相等。 基于这个目标,现在我们就去推导一下:每一层的权重应该满足哪种条件。 文章先假设的是线性激活函数,而且满足0点处导数为1,即 现在我们先来分析一层卷积: 其中ni表示输入个数。
根据概率统计知识我们有下面的方差公式: 特别的,当我们假设输入和权重都是0均值时(目前有了BN之后,这一点也较容易满足),上式可以简化为: 进一步假设输入x和权重w独立同分布,则有: 于是,为了保证输入与输出方差一致,则应该有: 对于一个多层的网络,某一层的方差可以用累积的形式表达: 特别的,反向传播计算梯度时同样具有类似的形式: 综上,为了保证前向传播和反向传播时每一层的方差一致,应满足: 但是,实际当中输入与输出的个数往往不相等,于是为了均衡考量,最终我们的权重方差应满足:
——————————————————————————————————————— ———————————————————————————————————————
学过概率统计的都知道 [a,b] 间的均匀分布的方差为: 因此,Xavier初始化的实现就是下面的均匀分布: —————————————————————————————————————————— ———————————————————————————————————————————
下面,我们来看一下caffe中具体是怎样实现的,代码位于include/caffe/filler.hpp文件中。
<code class="language-C++ hljs haskell has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-title" style="box-sizing: border-box;">template</span> <typename <span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);"
Intent简介 Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。在SDK中给出了Intent作用的表现形式为:
通过Context.startActivity() orActivity.startActivityForResult() 启动一个Activity;通过 Context.startService() 启动一个服务,或者通过Context.bindService() 和后台服务交互;通过广播方法(比如 Context.sendBroadcast(),Context.sendOrderedBroadcast(), Context.sendStickyBroadcast()) 发给broadcast receivers。
Intent可分为隐式(implicitly)和显式(explicitly)两种:
(1)显式 Intent 即在构造Intent对象时就指定接收者,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的,如下:
Intent intent = new Intent(MainActivit.this, NewActivity.class); startActivity(intent ); 上面那个intent中,直接指明了接收者:NewActivity
(2)隐式 Intent 即Intent的发送者在构造Intent对象时,并不知道也不关心接收者是谁,有利于降低发送者和接收者之间的耦合,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间,如下:
Intent intent = new Intent(); intent.setAction("com.wooyun.test"); startActivity(intent); 上面那个intent,没有指明接收者,只是给了一个action作为接收者的过滤条件。 对于显式Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些隐式Intent,通过解析,将Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。 Intent Filter匹配规则 Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行匹配判断的。一个过滤列表中的action、type、category可以有多个,所有的action、type、category分别构成不同类别,同一类别信息共同约束当前类别的匹配过程。只有一个Intent同时匹配action、type、category这三个类别才算完全匹配,只有完全匹配才能启动Activity。另外一个组件若声明了多个Intent Filter,只需要匹配任意一个即可启动该组件。 例如:
<action android:name="com.wooyun.project.SHOW_CURRENT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="video/mpeg" android:scheme="http" . . . /> <data android:mimeType="image/*" /> <data android:scheme="http" android:type="video/*" /> (1)action的匹配规则 action是一个字符串,如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配。一个Intent Filter中可声明多个action,Intent中的action与其中的任一个action在字符串形式上完全相同(注意,区分大小写,大小写不同但字符串内容相同也会造成匹配失败),action方面就匹配成功。可通过setAction方法为Intent设置action,也可在构造Intent时传入action。需要注意的是,隐式Intent必须指定action。比如我们在Manifest文件中为MyActivity定义了如下Intent Filter:
<intent-filter> <action android:name="
参考: 1.http://tomcat.apache.org/tomcat-8.0-doc/ssl-howto.html 2.http://www.eclipse.org/jetty/documentation/current/configuring-ssl.html 3.http://www.eclipse.org/jetty/documentation/9.3.0.v20150612/jetty-maven-plugin.html#maven-config-https
个人经验:keytool生成的JKS格式的密钥对是导不入到windows个人证书列表的,而PKCS12格式是可以的 使用keytool生成必要文件 1.生成服务端密钥对(keytool -genkeypair创建的keystore含有证书). d:\jdk8\bin\keytool -genkeypair -alias server -keystore server.p12 -storetype PKCS12 -keyalg RSA -storepass changeit -keypass changeit -validity 365 -dname "CN=server, OU=test, O=test, L=TH, ST=GZ, C=CN"
2.生成客户端密钥对.两个作用:a.导入到个人证书列表;b.为导出客户端证书做铺垫,进而导入到服务端的信任库 d:\jdk8\bin\keytool -genkeypair -alias client -keystore client.p12 -storetype PKCS12 -keyalg RSA -storepass changeit -keypass changeit -validity 365 -dname "CN=client, OU=test, O=test, L=TH, ST=GZ, C=CN"
3.从客户端密钥对导出客户端证书.作用:接着上面的第2小步,为导入到服务端的信任库做铺垫 d:\jdk8\bin\keytool -exportcert -alias client -file client.cer -keystore client.p12 -storetype PKCS12 -storepass changeit
4.将客户端证书导入到服务端的信任库.接着上面的第3小步,目前没有truststore,所以会生成一个 d:\jdk8\bin\keytool -importcert -alias client -file client.
Mac开机后默认进入系统Mac OS X的方法有两个: 方法一 - 开机时设置的方法: 1. 开机后按住"Option"直到出现系统选择界面时松开; 2. 移动光标到Macintosh HD,按下"Ctrl"; 3. 按下回车,此时进入Mac OS X系统,也就是系统设置为以后默认进入Mac OS X了。 方法二 - 已经进入Mac OS X系统的设置方法: 1. 在"系统偏好设置"里找到"启动磁盘",选择"Macintosh HD"; 2. 点击“重新启动”按钮,电脑重启后,默认以后直接Mac OS X系统了。
路由器的接口相对于交换机来说最大的特点就是接口类型和配置更为复杂,一般吧路由器上的接口分为三大类:一类用于局域网的LAN接口,一类用于广域网接入/互联的WAN接口,最后一类可以应用于LAN组网,或者WAN接入/互联网中的逻辑接口。最为复杂的就是各种WAN接口。
各种WAN接口有:Serial接口、Async接口(Async:异步)、CE1/PRT接口、E1-F接口、CT1/PRI接口、T1-F接口、3G Cellular接口(Cellular:蜂窝状)、POS接口、CPOS接口、PON接口、ADSL接口、VDSL接口和G.SHDSL接口等。
一、路由器接口基础及基本参数配置与管理
接口分类
接口是设备与网络中的其他设备交换数据并相互作用的部件。AR G3系列路由器中,所有接口共分为管理接口、物理接口和逻辑接口三大类。
1、管理接口
主要为用户提供配置管理支持,也就是通过此类接口可以登录到设备,并进行配置和管理操作,但管理接口不承担业务传输。
AR G3系列路由器支持Console和Mini-USB两种管理接口。
2、物理接口
物理接口是真实存在、有器件支持的接口,需要承担业务传输。物理接口有时也被称为端口。物理接口分为两种:
1)LAN接口:路由器可以通过它们与局域网中的网络设备交换数据。
2)WAN接口:路由器可以通过它们与局域网外的网络设备交换数据。
关于同步、异步传输概念:
异步传输
通常,异步传输是以字符为传输单位,每个字符都要附加 1 位起始位和 1 位停止位,以标记一个字符的开始和结束,并以此实现数据传输同步。所谓异步传输是指字符与字符(一个字符结束到下一个字符开始)之间的时间间隔是可变的,并不需要严格地限制它们的时间关系。起始位对应于二进制值 0,以低电平表示,占用 1 位宽度。停止位对应于二进制值 1,以高电平表示,占用 1~2 位宽度。一个字符占用 5~8位,具体取决于数据所采用的字符集。例如,电报码字符为 5 位、ASCII码字符为 7 位、汉字码则为8 位。此外,还要附加 1 位奇偶校验位,可以选择奇校验或偶校验方式对该字符实施简单的差错控制。发送端与接收端除了采用相同的数据格式(字符的位数、停止位的位数、有无校验位及校验方式等)外,还应当采用相同的传输速率。典型的速率有:9 600 b/s、19.2kb/s、56kb/s等。
异步传输又称为起止式异步通信方式,其优点是简单、可靠,适用于面向字符的、低速的异步通信场合。例如,计算机与Modem之间的通信就是采用这种方式。它的缺点是通信开销大,每传输一个字符都要额外附加2~3位,通信效率比较低。例如,在使用Modem上网时,普遍感觉速度很慢,除了传输速率低之外,与通信开销大、通信效率低也密切相关。
同步传输
通常,同步传输是以数据块为传输单位。每个数据块的头部和尾部都要附加一个特殊的字符或比特序列,标记一个数据块的开始和结束,一般还要附加一个校验序列 (如16位或32位CRC校验码),以便对数据块进行差错控制。所谓同步传输是指数据块与数据块之间的时间间隔是固定的,必须严格地规定它们的时间关系。
3、逻辑接口
是指能够实现数据交换功能,承担业务传输,但物理上不存在,需要通过配置建立的虚拟接口。
物理接口编号规则
物理接口是实际存在的接口,这就需要为每个接口配置一个编号,以标识每个接口。AR G3系列路由器采用“槽位号/子卡号/接口序号”的格式来定义接口编号。
1)槽位号:表示接口所在的路由器单板所在的槽位号。
首先要明白两个概念:一是什么是“单板”,二是什么是“主控板”。
“单板”可以理解为单一功能板,是插在主控板上面,用于实现某种功能的电路板(也称为接口卡,或者模块),如我们插入一个功能模块(如各种类型以太网接口卡),则这个模块电路板就是一个单板。“主控板”是路由器系统控制和管理的核心,提供整个系统的控制平面,管理平面和业务交换平面,通常还包括电源和风扇模块。
(个人理解,主控板相当于PC机的主板,单板相当于其上的各种接口卡,如网卡、显卡等)。
一般来说,一台路由器设备只有一个主控板,但高端路由器可能有多个主控板,如NE40E。
AR系列路由器支持SIC/WSIC/XSIC/SRU类型的单板,SIC/WSIC/XSIC/SRU类型单板的结构相同,下面以WSIC类型单板举例说明。
SRU主控板是系统控制和管理核心,提供整个系统的控制平面,管理平面和业务交换平面。
-- 控制平面:完成系统的协议处理、业务处理、路由运算、转发控制、业务调度、流量统计、系统安全等功能。
-- 管理平面:完成系统的运行状态监控、环境监控、日志和告警信息处理、系统加载、系统升级等功能。
-- 业务交换平面:提供高速无阻塞数据通道,实现各个业务模块之间的业务交换功能。
SRU主控板包含10块不同型号的主控板
因为AR150/150-S/160/200/200-S系列、AR1200/AR1200-S系列、AR2201-48FE、AR2202-48FE、AR2204、AR2220L、AR2201-48FE-S、AR2204-S和AR2220-S和AR2220S的主控板是一体化的(没有单板),且只有一个主控板,所以其主控板物理槽位号统一取值为0。
其他系列的各单板槽位号参见说明,遇到槽位号合并时,物理槽位号取较大槽位编号,如槽位1和槽位2合并后,取新槽位号2。
2)子卡号:表示各单板上所插入的子卡编号。但因为AR G3系列路由器各单板都不支持子卡,因此统一取值为0。所以各接口编号中的第二位均为0。
3)接口序号:表示各主控板和单板上各接口的编排序号。
-- 接口板面板上只有一排接口
对于AR120&AR160系列、AR1200系列、AR2200系列、AR3200和AR3600系列,最左侧接口从0起始编号,其他接口从左到右依次递增编号。
根据师兄师姐各方 面试总结问题如下:
Java基础
1. 九种基本数据类型的大小,以及他们的封装类。
2. String,StringBuffer, StringBuilder 的区别?
3. Switch能否用string做参数?
4. Java的四种引用,强弱软虚,用到的场景。
5. Tomcat,apache,jboss的区别
6. Hashcode的作用。
7. ArrayList、LinkedList、Vector的区别。
8. GET POST区别 、SESSION, COOKIE区别、redirect, foward区别
9. Map、Set、List、Queue、Stack的特点与用法。
10. Servlet的生命周期、HTTP 报文包含内容 11. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
12. TreeMap、HashMap、LindedHashMap的区别。
13. Collection包结构,与Collections的区别。
14. Statement与PreparedStatement的区别,什么是SQL注入,如何防止SQL注入
15. Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。
16.JAVA内存模型,一个对象(两个属性,四个方法)实例化100次,现在内存中的存储状态, 几个对象,几个属性,几个方法。
17. Static class 与non static class的区别。
18. java多态的实现原理。
19. 实现多线程的两种方法:Thread与Runable。
20. 线程同步的方法:sychronized、lock、reentrantLock等,线程同步,并发操作怎么控制 21. 锁的等级:方法锁、对象锁、类锁。
22. 写出生产者消费者模式。
23. ThreadLocal的设计理念与作用。
24. ThreadPool用法与优势。
25. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。
26. foreach与正常for循环效率对比。
27. 反射的作用于原理,主要是概念,都在哪需要反射机制,反射的性能,如何优化
28. 泛型常用特点,List<String>能否转为List<Object>。
我使用的工具室WebStorm,项目以前使用的nodejs版本是4.4.x,我用的是Nodejs6.2,但是一启动项目就报:v8debug is not defined
搜索了一下解决方案:解决方案的地址
http://blog.csdn.net/qq415734794/article/details/7852063
如果出现oracle提示ERROR - ORA-12541: TNS:无监听程序,那么就依照下列步骤做,这是因为你的分配的地址不对。 我本机是64位的系统,首先找到C:\Program Files (x86)\Oracle\odac_client\tnsnames.ora文件,用记事本打开,显示oracle值: [html] view plain copy ORACLE = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST =自动分配的IP地址)(PORT =1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) ) 修改如下:
[html] view plain copy 10.1.10.183/orcl = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.1.10.183)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl) ) ) 主机名输入localhost或127.0.0.1都会提示无监听程序。由于自动分配的IP地址会有变动,所以将oracle值中的host改成本机的计算机名,保存修改后的tnsnames.ora。再次连接(10.1.10.183/orcl)数据库,出错问题解决。
连接远程数据库,更改配置文件,或者通过 NET Manager 配置。
http://jingyan.baidu.com/article/6c67b1d68edabc2787bb1e8d.html
http://jingyan.baidu.com/article/fdbd4277142cbbb89e3f4823.html
下面的thread dump是在CPU使用高的情况下采集的jstack的数据。
"pool-19-thread-50" prio=10 tid=0x00007fd1b8001000 nid=0x11bb2 runnable [0x00007fd41f018000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
- locked <0x0000000790724f88> (a sun.nio.ch.Util$2)
- locked <0x0000000790724f98> (a java.util.Collections$UnmodifiableSet)
- locked <0x0000000790724f40> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
at weblogic.socket.NIOSocketMuxer$NIOInputStream.readInternal(NIOSocketMuxer.java:815)
at weblogic.socket.NIOSocketMuxer$NIOInputStream.read(NIOSocketMuxer.java:759)
at weblogic.socket.NIOSocketMuxer$NIOInputStream.read(NIOSocketMuxer.java:742)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
- locked <0x00000007aac27988> (a java.io.BufferedInputStream)
at weblogic.net.http.MessageHeader.isHTTP(MessageHeader.java:227)
at weblogic.net.http.MessageHeader.parseHeader(MessageHeader.java:149)
at weblogic.net.http.HttpClient.parseHTTP(HttpClient.java:514)
at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:434)
- locked <0x00000007aac23230> (a weblogic.net.http.SOAPHttpURLConnection)
at weblogic.net.http.SOAPHttpURLConnection.getInputStream(SOAPHttpURLConnection.java:37)
at weblogic.
使用python工具读写MS Word文件(docx与doc文件),主要利用了python-docx包。本文给出一些常用的操作,并完成一个样例,帮助大家快速入手。
安装 pyhton处理docx文件需要使用python-docx 包,可以利用pip工具很方便的安装,pip工具在python安装路径下的Scripts文件夹中
pip install python-docx 当然你也可以选择使用easy_install或者手动方式进行安装
写入文件内容 此处我们直接给出一个样例,根据自己的需要摘取有用的内容
#coding=utf-8 from docx import Document from docx.shared import Pt from docx.shared import Inches from docx.oxml.ns import qn #打开文档 document = Document() #加入不同等级的标题 document.add_heading(u'MS WORD写入测试',0) document.add_heading(u'一级标题',1) document.add_heading(u'二级标题',2) #添加文本 paragraph = document.add_paragraph(u'我们在做文本测试!') #设置字号 run = paragraph.add_run(u'设置字号、') run.font.size = Pt(24) #设置字体 run = paragraph.add_run('Set Font,') run.font.name = 'Consolas' #设置中文字体 run = paragraph.add_run(u'设置中文字体、') run.font.name=u'宋体' r = run._element r.rPr.rFonts.set(qn('w:eastAsia'), u'宋体') #设置斜体 run = paragraph.
关于JSONObject的封装,或者说使用,现在市面上很多。这里不做过多的描述,但是有种情况却不得不说明下,在
这次的授课中,我让学生用JSONObject进行对对象进行JSON格式转换,但是在转换过程中,很多都遇到了
java.sql.Date类型的属性无法完成转换,并且抛出异常:net.sf.json.JSONException: java.lang.reflect.InvocationTargetException
很多人遇到这个问题后,应该会查询百度等搜索引擎,那么可能得到一种类型转换的说法,我们也得到这样的说法,
后来多方测试,也确实是这个问题。如何解决?
或许很多人会说,那既然时间格式无法转换,我们可以转换设计类型嘛,数据库中我们不用date或datetime,直接用
varchar,而java中直接用String好了。确实这不失一个解决问题的办法,但是如果我们不改呢?
下面是我给出的设计图:
在这个设计图中,我给出了一个接口JsonValueProcessor ,这个接口可以自定义一些JSON类型转换器,正好,我就
分别定义了3种不同类型的类型转换器。
分析上图,我定义了3种角色:
1、类型转换器抽象接口:分别定义了2个接口方法,一个用于处理数组,一个用于处理属性类型;
2、类型转换器具体实现类:实现了上述抽象接口类的接口方法;
3、调用者:用户通过调用“调用者”的方法,完成由对象向JSONObject转换。
类型转换器抽象接口,由json-lib.jar提供,我们不必定义。
处理java.sql.Date类型属性的类型转换器:
package com.lovo.util; import java.text.SimpleDateFormat; import java.util.Date; import net.sf.json.JsonConfig; import net.sf.json.processors.JsonValueProcessor; /** * 定义一个自己的时间适配处理器 * @author Administrator * */ public class SQLDateProcessor implements JsonValueProcessor{ private String format = "yyyy-MM-dd hh:mm:ss";//自定义时间格式化的样式 public SQLDateProcessor() { super(); // TODO Auto-generated constructor stub } public SQLDateProcessor(String format) { this.format = format; } public Object processArrayValue(Object arg0, JsonConfig arg1) { // TODO Auto-generated method stub return arg0; } /** * 处理对象的值 * str 这个参数是当前需要处理的属性名 */ public Object processObjectValue(String str, Object obj, JsonConfig arg2) { // TODO Auto-generated method stub String ret = "
将头文件引入的时机尽量延后,减少类的使用者所需引入头文件的数量(向前声明),同时避免互相引用,减少编译时间和编译错误如下截图说明了向前引用的示例,在头文件中用@class向前引用,在.m实现文件中引入需要使用到的头文件,降低类的耦合。
无法使用向前声明的时候,比如说带有某个协议的类,尽量把该类遵循此协议写到class-continuation分类中,不行的话就单独把这个协议放到一个头文件中,然后将其引入。