NSNumber:处理包括int,float, char等在内的多种数据 NSNumber *a = @1; NSNumber *b = @2.0f; NSNumber *c = @3.1415926; NSNumber *d = @'a' //char NSNumber *e = @(x * y); //expressionNumber *** 当然, int x = 1; 等价于 NSNumber *a = @1; float y = 2.0f 等价于 NSNumber *b = @2.0f; 字面量数组:2种方式 NSArray *animal = [NSArray arrayWithObjects:@"cat", @"dog",nil];NSArray *animal = @[@"cat", @"dog"]; 但是需要注意的是如果数组中出现一个nil的话,第一种会创建成功,但是到这个nil变量的时候就会停止,而第二种方式会抛出异常(推荐) 字面量字典
用awk的printf就可以补位
# 仅适用于数字 printf "%04d\n" 86 echo 86|awk '{printf("%04d\n",$0)}' 下面是我实际应用中使用的一个脚本,目的是批量修改hdfs上的文件名,输入两个参数即可,就是开始时间和结束时间,然后用whil去循环。 #example------nohup sh hdfs_rename.sh 20160522 20160530 >>logrename 2>&1 & datebeg=$1 dateend=$2 beg_s=`date -d "$datebeg" +%Y%m%d` end_s=`date -d "$dateend" +%Y%m%d` while [ "$beg_s" -le "$end_s" ] do date=${beg_s} for i in `seq 99` do num1=`echo ${i}|awk '{printf("%06d\n",$0)}'` num2=`echo ${i}|awk '{printf("%02d\n",$0)}'` echo ${date} echo ${num1} echo ${num2} hadoop fs -mv /xtrader/${date}/${num1}_* /xtrader/${date}/xtrader_UserInfo_${date}_${num2}.gz done echo ${date} beg_s=`date -d"${beg_s}+1 day" +%Y%m%d` done
TrueCrypt加密之后的文件,目前没有好的办法破解,因此在调查取证的时候,可以考虑以下方法: 4.1 分析和检查是否有TrueCrypt加密之后的文件存在。 (a) TrueCrypt加密之后的文件没有固定的特征,如果加密者把这样的文件保存为常见格式的文件时,利用Encase、Winhex、取证大师等软件分析文件特征,对于不匹配的文件重点分析,进行排查是否为加密文件; (b) 搜索系统所安装软件,包括历史安装记录,检查是否有安装TrueCrypt软件的 痕迹; (c) 搜索大文件,作为加密容器,一般都存放着多个文件,因此,较大的文件可能性会比较大,不过也不排除特别重要的文件单独加密的可能。 4.2 TrueCrypt能设置双层加密,即在一个加密卷中再隐藏另一个加密卷,隐藏卷形象的来说就是“嵌套”在普通加密卷里边的。当用户被胁迫解密加密卷时,用户可以把隐藏加密卷的“外套”普通加密卷解密,透露一些无关紧要的信息,而真正的受保护的信息则隐藏在隐藏卷中,数据得以保护。加密卷的加载流程如下图所示: 2012-12-17 02:15 上传下载附件 (33.35 KB) 对于此类情况,首先要考虑是否能得到隐藏卷的密码,如果不能,应该把数据备份之后,用无用数据填充的方式覆盖普通卷空余的空间,可以把伪装在普通卷里面的数据破坏,让加密者自己也无法再恢复这些隐藏的数据。 4.3 TrueCrypt对数据的操作都是在内存(RAM)中进行,因此软件不确定是否在计算机的内存中保存有密码、主密钥和一些未加密的数据。而最新的研究成果显示,即使计算机关机后,内存保存的资料,包括加密程序的安全锁和口令仍未消失,最长可能达数分钟之久,透过冷冻计算机记忆芯片,还可延长内存暂存资料的时间,普林斯顿大学一班计算机保安专家组成的研究小组组长-计算机科学家费尔滕解释:只要以液态氮(摄氏-196度)冷冻计算机芯片,即使电源已中断,内存仍可保持状态至少数小时。然后将芯片安装回计算机,就可读取里面的资料。 4.4 在使用者机器上安装使用间谍或者监控程序,开机自动运行,利用键盘记录钩子记录TrueCrypt加载卷的密码。此外,还可以利用政策,社会工程学方法(如通过其他途径获得其他帐号密码或者其他方面的信息来分析加密文件的密码)等方式来获取密码,并注意是否可以获取隐藏卷的密码。 5 总结 TrueCrypt是全球著名的开源加密软件,有着安全、易用、功能强大等优点,也适用于可移动存储设备的加密。随着在国内应用的推广,对使用该软件加密之后的计算机数据的取证也变得越来越困难,因此有必要对这方面加强研究,总结规律,以提高取证的效率。
制作隐形操作系统的步骤太多所以对截图采用数字标号; 某些操作对主线任务起一个监视作用或者这些操作是对TrueCrypt程序的辅助操作,在这些步骤的数字后加了字母。 温馨提示:制作隐形操作系统时务必:1)登陆Windows管理员账号;2)用管理员权限运行TrueCrypt!3)隐藏操作系统分区必须比原始操作系统分区大5%(不然就要提示步骤5中的错误);4)请注意这些重要步骤(及下文中所有标红的文字):第16、21、45、48、49步骤! 开始上图: 对硬盘重新分配空间后继续: 如果系统没有激活,对整个隐形系统的制作没有什么影响(虚拟机测试结果)! 外层加密卷支持密钥文件! 哦!NO! 强烈建议:任何情况下都不要用快速格式化! 第18步骤的分步骤b-d:打开了外层加密卷并往里面拷贝了一些迷惑文件;分步骤e是点击18a中“下一步”后外层加密卷被自动卸载的截图! 从第19步骤开始做隐藏加密卷: 第21步骤是重要步骤:一定要记住本步骤所选择的加密算法!这个算法在第48步骤会用到! 第24步骤的密码要跟第13步骤的密码完全不同! 第34步骤的分步骤a-d:隐形系统启动后的截图。 在接下来的步骤中先擦除一次原始系统,然后再安 装 迷惑系统到原始系统所在分区 -- 就是隐形操作系统分区接挨着的上一个分区 ! 步骤42的分步骤a-e:安装迷惑系统到原始系统所在分区! 第43步骤是迷惑操作系统安装后的界面: 第45步骤是重要步骤:一定要选常规! 第46步往后,有很多操作跟以前操作的相像。 第48步骤是重要步骤:一定要用跟21步相同的算法! 第49步骤是重要步骤:本步骤所设置密码必须完全不同于第24和第13所设置的两个密码! 重新用管理员权限启动TrueCrypt后继续操作: 第55步的分步骤a-d:用虚拟光驱加载应急盘。 结束第66步,万事大吉!大功告成! 下面是一些测试性的截图,仅供读者参考: 下面的两个截图可以看出: 隐形操作系统和迷惑操作系统大小也完全一样: 下面的截图是进不同操作系统对盘操作时有不同的情况: The End! 致谢:感谢热心网友“五星”对本文截图后期处理所做的贡献!
1)TrueCrypt随机数产生RandomNuderGenerator(RNG)
Random Number Generator(RNG)是一个内存中的随机数产生器。它在TrueCrypt中发挥着重要作用。RNG将产生各种密钥,其中最主要的是加密卷首部分的卷首密钥和以后实时加解密过程中的主次密钥。RNG还将产生卷首前512字节的 “盐”和密钥文件.用于基于PBKDF2的用户 口令的实现中。同时为了隐藏卷文件中重要内容的大小.卷文件通常在创建的过程中填充临时加密过的随机数.而这些随机数也是RNG产生的。在Win—dows平台下RNG产生的随机数是RNG实时收集 Windows操作系统的各种数据并通过一定方式的运算得到的。
2)TrueCrypt中实时加解密密钥
对加密卷内的文件进行读写操作时都需要加解密,而密钥存放的位置和受保护的程度决定了加密文件的安全性。True—Crypt把主次密钥(实时加解密时的密钥)存放在加密卷的卷首(512字节)的第 256至511字节。而卷首的512字节由不同于主次密钥的卷首密钥加密的。卷首密钥得到的理论基础是PKCS#5(基于I=1令的密码系统规范2.o)中的密钥导出函数PBKDF2.得出的密钥可以有效的防范字典攻击。PBKDF2主要公式是:DK=PBKDF2(P,S,C,dkLen),其中DK是最终导出的密钥,参数P是口令(一个字节串)参数s是“盐”(一个字节串)参数c是迭代的次数.参数dkLen是导出密钥的任意长度。一般来说P就是用户输入的口令,而TrueCrypt为保证用户口令的安全对参数P做了修改。用“用户口令+口令密钥文件”方式得到新的用户口令。口令密钥文件是TrueCrypt的一大亮点.它即可以由Tme—Crypt自己随机生成。又可以是用户提供的任意格式任意大小的文件,如图片文件、Mp3文件等。并不是文件的所有数据都起作用,只有文件的前 1048576字节f1MB1的数据才作为有用数据进行运算。TrueCrypt对 口令密钥文件的数量也没有限制。
PBKDF2中对分组的操作是基于基本 的伪随机 函数的,True—Crypt中提供 了三种这 样的函数 HMAC—SHA-512、HMAC—RIPEMD-160、HMAC—Whirlpool。
3)TrueCrypt隐藏卷
隐藏卷形象的来说就是 “嵌套”在普通加密卷里边的。这样设计考虑了用户的安全需求。当用户被胁迫解密加密卷时用户可以把隐藏加密卷的 “外套”普通加密卷解密,透露一些无关紧要的信息,而真正的受保护的信息则隐藏在隐藏卷中,得以保护。由此可见隐藏卷的创建过程必须是:首先创建一个普通卷然后在普通卷里创建一个隐藏卷。需要注意的是普通卷和普通卷里的隐藏卷的用户口令必须是不同的。在加载卷时TrueCrypt根据用户 口令来判断是加载普通卷还是普通卷里的隐藏卷。所以用户在胁迫的情况下可以告诉普通卷的口令。来保护信息。
4)TrueCrypt加密卷的创建和加载
加密卷的创建过程如下:用户选择创建参数,包括加密算法 、哈希函数、文件系统、加密卷大小等;按照卷首格式在内存中创建卷首:根据用户选择的文件系统格式化加密卷,并向卷内填充随机数:创建备份卷首。
加密卷的加载就是把加密卷虚拟成一个虚拟磁盘。用户通过向磁盘内读写文件.实现加解密.
首先,很抱歉。今天着实忙的不行,现在才闲下来,今天只能写一个这个了,十分抱歉!如果有错,尽请纠正!谢谢支持!
链接命令:ln 命令格式:ln -s [源文件] [目标文件] 英文含义:link
功能描述:为某一个文件在另外一个位置建立一个不同的链接文件
选项:-s 创建软连接,不加选项则为硬链接
-s 是代号(symbolic)的意思。
硬链接的特征: 1、拥有相同的 i 节点和存储block块,可以看做同一个文件。
解释:之前我们说过每个文件都有属于自己的 i 节点,类似于ID号。硬盘分区会有一个文件索引列表以及一个数据分区。用户查找文件以后,会先进入到文件索引(文件索引至少包含 i 节点、时间、存储位置)内获取到存储位置,再根据位置去数据分区找到对应的block块,组合成数据返回。硬链接的话,链接文件和原文件都会对应同一个 i 节点和一样的存储数据块。这个概念和PHP里面的引用变量类似。也就是说,原文件和硬链接二者其中任何一个改变了另外一个也会改变,但是,如果其中一个被删除了另一个并不会被删除。这就相当于一个房间有二个门,我们关了一个门这个房间还是可以进入,房间里面什么东西变了不管你从哪个门,哪怕是从窗子进去那房间里面的东西都是一样的。 2、可通过 i 节点识别
解释:上面第一条说了是有一样的 i 节点的。所以如果两个文件 i 节点一样,那二者肯定有一个是原文件,一个是硬链接。
3、不能跨分区
解释:二个文件只能在同一个分区,这个应该是很好理解的吧?
4、不能针对目录
解释:硬链接只能给单个文件做链接,对目录无效。也可以理解成一个文件的二个入口。
软链接的特征: 1、类似于Windows的快捷方式。
解释:总的来说,链接的作用其实就是为了方便用户去进入某个目录或者是打开某个文件。
2、软链接拥有自己的 i 节点和block块,但是对应的数据块中只保存了原文件的 i 节点和文件名等,并没有原文件的数据。
解释:刚才说过硬链接是和原文件共用同一个文件索引的。而软链接则不是,软链接有自己的文件索引,自己的 i 节点和数据块。当用户去搜索文件的时候,先是获取到软链接的文件索引,再根据存储目录去数据块中取得数据,这个数据包含原文件的信息。再根据信息中的存储位置去获取到原文件的数据从而再返回给用户。这就相当于一个传送门,每个软链接都是帮你快捷的传送到某个很远的地方去。
3、软链接的权限都为lrwxrwxrwx。
解释:软链接各类用户都可以去读写。但是要注意的是,软链接的权限和原文件的权限是二码事儿。这就相当于把你传送过去了,但是面前还有一道门,然而你可能并没有带钥匙或者是带了钥匙。
4、修改其中一个另外一个也会改变
解释:软链接这块是和硬链接一样的。这时候软链接就像一个快递员,你给他,他帮你送到你家。没有权限他就送不进去,有权限他就直接帮你放进去了。
5、删除原文件以后软链接不能使用
解释:原文件都没有了传送门给你送哪去?宇宙?还是海底?
注:[] 代表可选项
Linux系列教程 Thans 一、常见目录的作用
/ 根目录
/bin 命令保存目录,普通用户就可以读取的命令
/boot 启动目录,启动所需的相关文件。一般单独分区,不能占满,没有空间后系统无法启动,一般留200M即可
/dev 设备文件保存目录,在这个目录中包含了所有Linux系统中使用的外部设备
/etc 配置文件保存目录
/home 普通用户的家目录(家目录即为初始目录用户登录以后所在的目录)比如有用户thans,则有对应目录/home/thans
/lib 系统库保存目录
/lib64 64位系统库保存目录
/mnt 系统挂载目录
/media 挂载目录
/sbin 命令保存目录,超级用户可以读取的命令
/root 超级用户的家目录 /tmp 临时目录
/proc 直接写入内存的。这个目录是一个虚拟目录,它是系统内存映射,我们可以直接通过访问这个目录来获取系统信息。也就是说,这个目录的内容不在硬盘上而是在内存中。
/sys 同上
/usr 系统软件资源目录
/usr/bin 系统命令(普通用户) /usr/sbin 系统命令(超级用户) /var 系统相关文档内容
linux是个严谨的系统,大家以后在练习的时候,尽量在tmp目录和家目录下练习。并且要养成该放哪放哪的好习惯!
二、命令的基本格式
命令 [选项] [参数]
注意:
个别命令不遵循这个格式
当有多个选项时,可以写在一起
简化选项与完整选项 例如:-a 等于 --all
这个结构中,root代表当前用户,localhost代表主机名。 ~ 代表当前所在目录 # 是用户提示符,#代表的是超级用户,$代表的是普通用户。
三、文件、目录处理命令
1查询目录中的内容:ls 格式:ls [选项] [文件或目录]
选项:
-a 显示所有有文件,包括隐藏文件
-l 显示详细信息
今天阴差阳错查了一下application中allowbackup属性的作用,看了大吃一惊,allowbackup是一个是否允许备份系统和用户数据的属性,应因此而引发Android的安全性问题。
漏洞案例
先来看一个情景案例,某IT男一直暗恋部门某女神,一天女神手机太卡了找IT男帮助清理手机空间,IT 男高兴地答应女神两分钟搞定,屁颠屁颠的跑到自己电脑旁边连上手机,女神在一边呆呆的看着IT男敲了几行代码然后在手机上点了几下,最后果然两分钟不到就搞定了,在女神谢着离开后,IT男露出了 WS 的笑容。
漏洞背景
在谷歌 2010 年发布 Android 2.2 Froyo (冻酸奶)系统中,谷歌引入一个了系统备份的功能,允许用户备份系统应用和第三方应用的apk安装包和应用数据,以便在刷机或者数据丢失后恢复应用。 第三方应用开发者需要在应用的 AndroidManifest.xml 文件中配置 allowBackup 标志(默认为 true)来设置应用数据是否能能够被备份或恢复。当这个标志被设置为true时应用程序数据可以在手机未获取 ROOT 的情况下通过adb调试工具来备份和恢复,这就允许恶意攻击者在接触用户手机的情况下在短时间内启动手机 USB 调试功能来窃取那些能够受到 AllowBackup 漏洞影响的应用的数据,造成用户隐私泄露甚至财产损失。
android:allowBackup=“false” 手工检测以及在线检测方法 http://blog.csdn.net/forlong401/article/details/44241305
本章提供了PostgreSQL的SQL命令,这些命令的准确语法规则。这组命令是从psql的命令行工具。上一节我们已经安装Postgres,直接打开psql:
Program Files > PostgreSQL 9.2 > SQL Shell(psql).
使用psql的时候,可以生成完整的命令列表使用的\ help命令。对于一个特定的命令的语法使用下面的命令:
<span class="pln" style="padding: 0px; margin: 0px;"> postgres</span><span class="pun" style="padding: 0px; margin: 0px;">-#</span><span class="pln" style="padding: 0px; margin: 0px;"> \help </span><span class="str" style="padding: 0px; margin: 0px;"><command_name></span> SQL语句 一个SQL语句,包括令牌,每个令牌可以代表一个关键字,标识符,带引号的标识符,常量,或特殊的字符符号。以下表格使用简单的SELECT语句来说明一个基本的,完整的SQL语句及其组件。
SELECT id, name FROM states Token Type Keyword Identifiers Keyword Identifier Description Command Id and name columns Clause Table name PostgreSQL的SQL命令 ABORT 中止当前事务。
<span class="pln" style="padding: 0px; margin: 0px;">ABORT </span><span class="pun" style="padding: 0px; margin: 0px;"
引用地址:58沈剑:三种妙法搞定冗余表数据一致性!
在这次DBAplus社群的分享中给大家带来的主题是“冗余表数据一致性保证”,主要包括四个方面的内容:
为什么会有冗余表的需求如何实现冗余表正反冗余表谁先执行冗余表如何保证数据的一致性 一、为什么会有冗余表的需求 首先聊聊为什么会有冗余表的需求。互联网很多业务场景的数据量很大,此时数据库架构要进行水平切分,水平切分会有一个patition key,通过patition key的查询能够直接定位到库,但是非patition key上的查询可能就需要扫描多个库了。 例如订单表,业务上对用户和商家都有订单查询需求: Order(oid, info_detail) T(buyer_id, seller_id, oid)。 如果用buyer_id来分库,seller_id的查询就需要扫描多库。如果用seller_id来分库,buyer_id的查询就需要扫描多库。这类需求,为了做到高吞吐量低延时的查询,往往使用“数据冗余”的方式来实现,就是我们所说的的“冗余表”: T1(buyer_id, seller_id, oid) T2(seller_id, buyer_id, oid) 同一个数据,冗余两份,一份以buyer_id来分库,满足买家的查询需求;一份以seller_id来分库,满足卖家的查询需求。当然,元数据还是放在Order(oid, info_detail)里。冗余表的业务场景说清楚了,再来看下冗余表的实现方案。 二、如何实现冗余表 方法一:服务同步写 顾名思义,由服务层同步写冗余数据,如上图流程: 业务方调用服务,新增数据 服务先插入T1数据 服务再插入T2数据 服务返回业务方新增数据成功 优点: 不复杂,服务层由单次写,变两次写 数据一致性相对较高(因为双写成功才返回) 缺点: 请求的处理时间增加(要插入次,时间加倍) 数据仍可能不一致,例如第二步写入T1完成后服务重启,则数据不会写入T2 如果系统对处理时间比较敏感,引出常用的第二种方案。 方法二:服务异步写 数据的双写并不再由服务来完成,服务层异步发出一个消息,通过消息总线发送给一个专门的数据复制服务来写入冗余数据,如上图1-6流程:
业务方调用服务,新增数据
服务先插入T1数据
服务向消息总线发送一个异步消息(发出即可,不用等返回,通常很快就能完成)
服务返回业务方新增数据成功
消息总线将消息投递给数据同步中心
数据同步中心插入T2数据
优点: 请求处理时间短(只插入1次) 缺点: 系统的复杂性增加了,多引入了一个组件(消息总线)和一个服务(专用的数据复制服务) 因为返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的) 在消息总线丢失消息时,冗余表数据会不一致 如果想解除“数据冗余”对系统的耦合,引出常用的第三种方案。 方法三:线下异步写 数据的双写不再由服务层来完成,而是由线下的一个服务或者任务来完成,如上图1-6流程: 业务方调用服务,新增数据 服务先插入T1数据 服务返回业务方新增数据成功 数据会被写入到数据库的log中 线下服务或者任务读取数据库的log 线下服务或者任务插入T2数据 优点: 数据双写与业务完全解耦 请求处理时间短(只插入1次) 缺点: 返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的) 数据的一致性依赖于线下服务或者任务的可靠性 三、正反冗余表谁先执行 上述三种方案各有优缺点,但不管哪种方案,都会面临: “究竟先写T1还是先写T2”的问题 都可能不一致,应该怎么解决的问题 先看看第一个问题,先操作哪一个的问题:究竟先写正表还是反表? 对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:【如果出现不一致】,谁先做对业务的影响较小,就谁先执行。 以上文的订单生成业务为例,buyer和seller冗余表都需要插入数据: T1(buyer_id, seller_id, oid) T2(seller_id, buyer_id, oid) 用户下单时,如果“先插入buyer表T1,再插入seller冗余表T2”,当第一步成功、第二步失败时,出现的业务影响是“买家能看到自己的订单,卖家看不到推送的订单”。 相反,如果“先插入seller表T2,再插入buyer冗余表T1”,当第一步成功、第二步失败时,出现的业务影响是“卖家能看到推送的订单,买家看不到自己的订单”。 由于这个生成订单的动作是买家发起的,买家如果看不到订单,会觉得非常奇怪,并且无法支付以推动订单状态的流转,此时即使卖家看到有人下单也是没有意义的。 因此,在此例中,应该先插入buyer表T1,再插入seller表T2。however,记住结论:对于一个不能保证事务性的操作,【如果出现不一致】,谁先做对业务的影响较小,就谁先执行。 四、冗余表如何保证数据的一致性 最后是一致性的问题。不管是同步写入,异步写入,线下异步写入,都有可能出现数据不一致,怎么解决?常见的方案有这么几种: 方法一:线下扫描正反冗余表全部数据 如上图所示,线下启动一个离线的扫描工具,不停的比对正表T1和反表T2,如果发现数据不一致,就进行补偿修复。 优点: 比较简单,开发代价小 线上服务无需修改,修复工具与线上服务解耦 缺点: 扫描效率低,会扫描大量的“已经能够保证一致”的数据 由于扫描的数据量大,扫描一轮的时间比较长,即数据如果不一致,不一致的时间窗口比较长 很容易想到这个方案的优化方向。有没有可能只扫描“可能存在不一致可能性”的数据,而不是每次扫描全部数据,以提高效率呢?这就引出了第二种方案。 方法二:线下扫描增量数据 每次只扫描增量的日志数据,就能够极大提高效率,缩短数据不一致的时间窗口,如上图1-4流程所示: 写入正表T1 第一步成功后,写入日志log1 写入反表T2 第二步成功后,写入日志log2 当然,我们还是需要一个离线的扫描工具,不停的比对日志log1和日志log2,如果发现数据不一致,就进行补偿修复。互联网大部分业务是读多写少的场景。其实对于新增的数据量,是很小的,所有折中方案只需要扫描很少的数据,保证一致的数据也不会被重复扫描。 优点: 虽比方法一复杂,但仍然是比较简单的 数据扫描效率高,只扫描增量数据 缺点: 线上服务略有修改(代价不高,多写了2条日志) 虽然比方法一更实时,但时效性还是不高,不一致窗口取决于扫描的周期 我们之前的im好友表与反向好友表,修复周期是1天。当然这个周期也是由业务场景决定的。无论如何,修复还是不实时,有没有更为实时的修复方法呢?这就引出了方案三。 方法三:实时线上“消息对”检测 这次不是写日志了,而是向消息总线发送消息,如上图1-4流程所示: 写入正表T1 第一步成功后,发送消息msg1 写入反表T2 第二步成功后,发送消息msg2 这次不是需要一个周期扫描的离线工具了,而是一个实时订阅消息的服务不停的收消息。 假设正常情况下,msg1和msg2的接收时间应该在3s以内,如果检测服务在收到msg1后没有收到msg2,就尝试检测数据的一致性,不一致时进行补偿修复。 优点: 效率高,每个数据只扫一次 实时性高,消息的通知很实时 缺点: 方案相对比较复杂,引入了消息总线这个组件 线下多了一个订阅总线的检测服务 However,技术方案本身就是一个投入产出比的折衷,可以根据业务对一致性的需求程度决定使用哪一种方法。 五、总结 1、互联网很多业务场景的数据量很大,此时数据库架构要进行水平切分,切分后为了做到高吞吐量低延时的查询,往往使用“数据冗余”的方式来实现多个 字段上的高效查询(都不需要遍历库)。 2、冗余表有三种实现方式: 服务同步写 服务异步写 线下异步写 3、冗余表到底正表先操作还是反表先操作的解决方法论是:对于一个不能保证事务性的操作,【如果出现不一致】,谁先做对业务的影响较小,就谁先执行。 4、为了发现冗余表数据不一致,并进行数据修复的常见方案有3种: 线下扫描正反冗余表全部数据 线下扫描增量数据 实时线上“消息对”检测 六、Q & A Q1:方案3的消息总线都有哪些实现方式? A1:消息总线,msg-queue,开源的,自研的都行,像ActiveMQ,ZeroMQ,RabbitMQ都行。 Q2:买家、卖家的这种表数据量都比较大,应该都是分库分表,里面t1,t2应该是一个笼统的概念,t1,t2内部应该会映射更多的分库吧,这些分库间映射,数据一致性和冗余,能不能再简单说说? A2:没错,正向表和反向表都会进行水平切分,而且patition key是不一样的。数据冗余上文提到就是一条数据冗余了2份,一致性也如上文所说有3种常见的方法来保证(仅限冗余表的一致性保证)。 Q3:用触发器来插入另一个表怎么样? A3:触发器恐怕不通用,互联网场景数据量大,并发量大,分库了之后,数据都是分布在不同的实例,不同的机器上的。 Q4:实时线上“消息对”检测中,如果消息总线出现问题,数据完整性,数据修复处理方式,能否简单说一下? A4:出现数据不一致的概率很低(例如10w个请求一个不一致,1/10w),消息总线出现问题的概率更低(消息总线100w个请求出现一个不一致?1/100w),这种巧合的概率在1/(10w*100w)。当然,如果硬要细究,最差可以退化到扫全量、扫增量。
循环单链表和循环双链表是由对应的单链表和双链表改造而来,只需在终端节点和头结点间建立联系即可。循环单链表终端节点的next结点指针指向表头结点。循环双链表终端节点的next指针指向表头结点,头结点的prior指针指向表尾结点。如果p指针沿着循环链表行走,判断p走到表尾节点的条件是p->next==head。
1、单链表
在每个结点中除了包含数据域外,还包含了一个指针域,用以指向其后继结点。
2、头插法和尾插法建立链表
(1)算法代码
typedef struct SinglyLinkedLists { int data; struct SinglyLinkedLists *next; }SinglyLinkedLists; void createListByFront(SinglyLinkedLists *&list, int a[], int n)//头插法 { //newList指向新申请的结点 SinglyLinkedLists *newList; int i; //申请list的头结点 list = (SinglyLinkedLists *)malloc(sizeof(SinglyLinkedLists)); list->next = NULL; for (i = 0; i < n; ++i) { newList = (SinglyLinkedLists *)malloc(sizeof(SinglyLinkedLists)); newList->data = a[i]; newList->next = list->next; list->next = newList; } } void createListByRear(SinglyLinkedLists *&list, int a[], int n)//尾插法 { //newList指向新申请的结点,rearList始终指向list的终端结点 SinglyLinkedLists *newList, *rearList; int i; //申请list的头结点 list = (SinglyLinkedLists *)malloc(sizeof(SinglyLinkedLists)); list->next = NULL; rearList = list; for (i = 0; i < n; ++i) { newList = (SinglyLinkedLists *)malloc(sizeof(SinglyLinkedLists)); newList->data = a[i]; rearList->next = newList; rearList = rearList->next; } rearList->next = NULL; } void queryData(SinglyLinkedLists *list) { SinglyLinkedLists *p = list->next; while (p !
由于项目中有大量的回调,就使用EventBus.结果出现了一个BUG。
至于具体的用法我就不介绍了,下面主要介绍使用EventBus时遇到的Bug.
我在使用Activity + fragment 的时候,发现在页面多次返回之后,应用崩溃。
查看log日志,提示:
“IllegalStateException: Activity has been destroyed” in fragment trasaction 就去百度 “Activity has been destroyed”,搜索结果很多,但是都没有效果。 把问题说给同事听后,有人说可能内存泄漏,导致内存不足, Activity就被销毁了。 然后检查,发现 EventBus 忘了 unregister(); 在代码中加了 EventBus.getDefault().unregister(this) 之后,BUG消失;
1、顺序表
顺序表就是把线性表中的所有元素按照其逻辑顺序,依次存储到从指定的存储位置开始的一块连续的存储空间中。
2、算法代码
#define maxSize 100 typedef struct//typedef声明新的类型名来代替已有的类型名 { int data[maxSize]; int length; }SequenceList; int queryData(SequenceList sl, int value) { int i; for (i = 0; i < sl.length; ++i) if (value == sl.data[i]) return i; return -1; } int insertData(SequenceList &sl, int position, int vaule) { int i; if (position < 0 || position > sl.length - 1 || sl.length == maxSize) return -1; for (i = sl.length - 1; i >= position; --i) sl.
private Integer simId_1 = 0; private Integer simId_2 = 1; private String imsi_1 = ""; private String imsi_2 = ""; private String imei_1 = ""; private String imei_2 = ""; private Context mContext; public class IMSInfo { public String chipName; public String imsi_1; public String imei_1; public String imsi_2; public String imei_2; public String getChipName() { return chipName; } public void setChipName(String chipName) { this.chipName = chipName; } public String getImsi_1() { return imsi_1; } public void setImsi_1(String imsi_1) { this.
云风老大用汇编实现的一个高效memcpy,号称比传统memcpy快50%
FastMemcpy
https://github.com/skywind3000/FastMemcpy/blob/master/FastMemcpy.h#L580
不过VS2015编译器中已经做了类似的优化。
相关文章:
如何用蓝图实现Delegate Event:
http://aigo.iteye.com/blog/2269663
原文作者:@玄冬Wong
转载请注明出处:http://aigo.iteye.com/blog/2301010
虽然官方doc上说Event的Binding方式跟Multi-Cast用法完全一样,Multi-Cast论坛上也有很多例子,但是实际是不一样。。而且论坛上找不到相关例子。后来看了下runtime/core的源码,Event的binging方式如下(附上完整步骤):
1,先定义自定义Event,此例中我们定义在GameMode中,名字叫 MyInitEvent。例子中定义的是无参函数,如果需要带参数,官方doc讲的有
UCLASS() class MYPROJ_API AMyGameMode : public AGameMode { GENERATED_BODY() public: AHGameMode(); //定义Event DECLARE_EVENT(MyUObject, MyInitEvent) //用于获取Event引用的函数,方便在GameMode之外执行binding MyInitEvent& OnInitialize() { return InitEvent; } private: //Event实例化 MyInitEvent InitEvent; //Event的binding指针 FDelegateHandle DHandle; } 2,执行Binding。MyUObject::TestFun是需要被触发的函数,这里假设是一个普通的无参成员函数:
MyUObject* MyObj = NULL; //这里假设创建MyUObject if (MyObj) { DHandle = MyGameMode->OnInitialize().AddUObject(MyObj, &MyUObject::TestFun); } 注:任何UObject的普通函数都可以被设置为Event的回调函数,但如果函数是UFUNCTION,那么需要将AddUObject替换为AddUFunction。
3,触发Event,这里假设在BeginPlay中触发:
void AMyGameMode::BeginPlay() { InitEvent.Broadcast(); } 4,移除Event,比如之前bingding的event不想再触发了:
MyGameMode->OnInitialize().Remove(DHandle); Event 和 Delegate 区别
Delegate 只能绑定一个回调函数,Delegate执行Execute()函数时,只会触发事先绑定的一个函数;Event可以绑定任意个函数,一旦执行Event的Broadcast()函数,所有回调函数按Add顺序依次执行。
Dynamic Multicast Delegate也可以同时绑定多个回调函数,但是其运行效率要比 Event 慢。
[TUTORIAL] Fog Of War
https://forums.unrealengine.com/showthread.php?55650-TUTORIAL-Fog-Of-War
一些定义
sps: sample per second throughput rates: 吞吐量 积分型:转换效果不够好,转换过程中带来的误差比较大
逐次逼近型:转换效果较好但制作成本较高,尤其是高位数转换,转换位数越多,精度越高,制作成本就越高。
Σ-ΔADC:以相对逐次逼近型简单的电路结构,而得到低成本,高位数及高精度的转换效果,多为16bit或24bit转换精度
量化噪声:数模转换器(ADC)提供了许多系统中模拟信号到数字信号的重要转换。它们完成一个模拟输入信号到二元有限长度输出命令的振幅量化,范围通常在6到18b之间,是一个固有的非线性过程。该非线性特性表现为ADC二元输出中的宽带噪声,称作量化噪声,它限制了一个ADC的动态范围。
斩波(chop): 是一项用于消除失调电压和其它低频误差的技术。对输入信号分别进行正反相处理,然后再将两个结果求平均值以后消除内部电路带来的误差电压得到没有任何失调项的差分输入电压。
失调误差:在信号处理链路中的很多地方可能会有失调电压误差,例如,当两种不同金属连接时会产生与温度相关的热电偶电压。在集成电路例如ADC中,有许多内部失调误差源,例如,放大器输入器件之间的不匹配,采样开关关闭时采样电容上的电荷注入,或者EMI辐射的干扰等。如果这些不良失调随温度变化就会带来麻烦,因为一次校准不足以消除各种温度和电源条件下的失调误差。
AD7321:
类型:逐次逼近型ADC
输出方式: 1路SPI 500ksps;
转换精度/分辨率:12位带符号位
通道数:2通道
输入信号:AD7321可输入真双极性模拟信号,它有四种软件可选输入范围:±10 V、±5 V、±2.5 V和0至10 V。每个模拟输入通道支持独立编程,可设为四个输入范围之一。
AD7321中的模拟输入可通过编程设为单端、真差分或伪差分三种模式。
参考电压:内置一个2.5 V的参考电压,同时也可采用外部参考。如果在REFIN/OUT针脚上施加3V参考电压,AD7321则可接受±12V真双极性模拟输入。
功耗:17mW
电源:对于±12V输入范围,需采用最低±12V的VDD和VSS电源。
AD7708/7718: (用在测温--RTD,热电偶)
应用:是适合低频测量应用的完整模拟前端。
类型:含PGA的24位Σ-Δ ADC
Σ-Δ ADC原理:将模数转换过后的数字量再做一次窄带滤波处理。当模拟量进入转换器后,先在调制器中做求积处理,并将模拟量转为数字量,在这个过程中会产生一定的量化噪声,这种噪声将影响到输出结果,因此,采用将转换过的数字量以较低频率一位一位地传送到输出端,同时在这之间加一级低通滤波器的方法,就将量化噪声过滤掉,从而得到一组精确的数字量。
转换精度/分辨率:AD7708 16bit; AD7718 24bit
通道数:可配置为4/5个全差分输入通道或8/10个伪差分输入通道。
输入信号:该器件上的两个引脚可配置为模拟输入或基准电压输入。AD7708是AD7718的 16位版本。利用这些ADC,可以直接转换20mV至2.56V范围的输入信号,支持传感器信号直接输入,无需进行信号调理。
其他:
出厂校准 单转换周期设置 可编程增益前端 50 Hz、60 Hz同时抑制 VREF Select ™ 提供绝对测量和比率测量能力 AD7708的工作原理:同其它智能化器件一样,AD7708也可以用软件来调节其所具有的功能,即通过微控制器MCU编程向AD7708的相应寄存器填写适当的参数。AD7708芯片中共有11个寄存器,当模式寄存器(Mode Regis-ter)的最高位CHOP=0(CHOP被选中)后,其工作方框图如下图所示。
此时,输出率可变化范围为5.35 Hz至105.03Hz,可以从中选择一个频率从而得到最佳的滤波效果。断续频率fCHOP也随之而定,为输出率(fADC)的二分之一。在MUX方框中模拟输入与fCHOP混合,并将信号送入缓冲器BUF,在缓冲器中有一级RC低通滤波,过滤掉输入信号中的噪声信号,下一级PGA的功能是可编程调整信号增益,一个经过调整合适的输入信号才被送进Σ-△调制器(MOD0)中进行求积,并转换为数字量,在Σ-△MODO中,对输入信号的采样频率为外部晶振频率32.768 kHz,在对模拟信号进行量化处理的过程中会形成量化噪声,这个噪声会影响到输出的数字量,因此必须再次对转换过的数字量进行低通数字过滤,确保输出值准确无误,这里AD7708采用了Sinc3或(sinx/x)3滤波器,它的主要作用就是消除由调制器产生的量化噪声,其中SF参数可根据所要滤掉的噪声频率大小用软件设定,默认值为69(45H),该值对50~60Hz的噪声有较好的抑制作用。
当CHOP=1时,断续(斩波)功能中止,与fCHOP相关的功能块也相应取消,此时流程图[2]如图2所示。输出频率变化范围可从16.06 Hz到1365.33 Hz,环节减少输出速度可以加快,但在输入增益或温度改变 时,可能会出现漂移,此时需要做些校验。
计算电压值:=(读出的ADC值/65536)*2.56V.
其中16bit的采样精度,2^16=65536。设定单输入端,输入范围0~2.56V。
using LSALogger; using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Core; using System.Data.Entity.Core.Metadata.Edm; using System.Data.Entity.Core.Objects; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text;
namespace LSADataAccess { public class DataAccessorHelper { private readonly static string formatString = typeof(DataAccessorHelper).FullName;
#region Select Method /// <summary> /// Select Single /// </summary> /// <typeparam name="T"></typeparam> /// <param name="selector"></param> /// <returns></returns> public T SelectSingle<T>(Func<T, bool> selector = null) where T : class { T result = null; try { using (DataAccessorEntities context = new DataAccessorEntities()) { if (selector == null) { result = context.
【华为OJ】【算法总篇章】 【华为OJ】【098-矩阵乘法计算量估算】 【工程下载】 题目描述 矩阵乘法的运算量与矩阵乘法的顺序强相关。 例如: A是一个50×10的矩阵,B是10×20的矩阵,C是20×5的矩阵 计算A*B*C有两种顺序:((AB)C)或者(A(BC)),前者需要计算15000次乘法,后者只需要3500次。 编写程序计算不同的计算顺序需要进行的乘法次数 输入描述 输入多行,先输入要计算乘法的矩阵个数n,每个矩阵的行数,列数,总共2n的数,最后输入要计算的法则 输出描述 输出需要进行的乘法次数 输入例子 3 50 10 10 20 20 5 (A(BC)) 输出例子 3500 算法实现 import java.util.Deque; import java.util.LinkedList; import java.util.Scanner; /** * Author: 王俊超 * Time: 2016-05-04 19:00 * CSDN: http://blog.csdn.net/derrantcm * Github: https://github.com/Wang-Jun-Chao * Declaration: All Rights Reserved !!! */ public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // Scanner scanner = new Scanner(Main.
写在前面:Struts2主要包含前端控制器FC、Action、ValueStack容器、Result、Interceptor拦截器、Tags标签6个核心组件,本文主要介绍这几个组件的合作关系,由此构成Struts2的工作流程,以便更好地理解和使用Struts2。
背景知识 1、Struts2基础标签 1)用于输出的标签
--*<s:property value="name"/> value的值实际上是OGNL表达式
--特殊用法
<s:property /> 用于输出栈顶数据
2)用于调试的标签
<s:debug/>
--该标签仅仅是给程序员用的,用于调试,即用于观察ValueStack中的数据
--当代码提交给测试、客户时,要把该标签删除
--该标签具有互斥性(可以理解为BUG),如果页面上出现多次这个标签时,实际上只有第一个有效
3)用于循环的标签
a、用于循环集合
--比如Action中有集合属性List<User> users
<s:iterator value="users">
<s:property value="userName"/>
</s:iterator>
b、用于循环数字
<s:iterator begin="1" end="3" var="i">
<s:property value="#i"/>
</s:iterator>
2、OGNL表达式 1)类似于EL表达式,但是比EL功能强大
2)表达式允许我们通过一个字符串,来访问JAVA对象。从而避免了在JSP上嵌套着写JAVA代码。即,表达式可以通过字符串间接的帮助我们访问JAVA对象。
3)基本原理
--OGNL表达式将被OGNL引擎解析,这个过程是Struts2自行完成的
--OGNL引擎允许我们访问两种类型的对象,一种是JavaBean类型,称之为root对象;另一种为Map类型,称之为context对象。
--当OGNL表达式以#开头时,OGNL引擎会访问context对象,否则会访问root对象
4)root对象
--我们写OGNL表达式时(不以#开头的情况),首先要明确谁是root对象,其次从该对象的下级属性写起。
举例:
--比如以Action为root对象,Action中有String name, User user属性,那么要在页面显示这两个属性的话,写法如下:
<s:property value="name"/>
<s:property value="user.userName"/>
--比如以User为root对象,要在页面上显示它的名称,写法如下:
<s:property value="userName"/>
5)context对象
--OGNL表达式以#开头,则访问context对象
--#后面写的是context对象的key,context对象是Map类型
3、ValueStack 1)什么是ValueStack
Struts2中并不是直接将OGNL组件搬过来使用,而是使用一个对象容器ValueStack对这个组件进行了改造及封装,因此我们在Struts2中是通过ValueStack来使用OGNL表达式。并且ValueStack中封装了Action的数据,上下文等数据,这些数据我们都可以通过OGNL表达式来获得。
2)原理
--结构:ValueStack中封装了OGNL引擎、context对象、Stack对象。
--规则:当我们在标签中写一个OGNL表达式时,该表达式被Struts2自动的传递给ValueStack中的OGNL引擎,引擎会判断表达式是否以#开头,若是则直接从context对象中取值,否则向Stack中取值。
--如何向Stack取值:OGNL表达式从栈顶向下依次取值,它是以栈的每一级对象作为root对象从中取值的,若取到值则直接返回,否则继续向下取值,直到栈底为止。
3)*栈顶的变化
a、默认情况下,栈顶是Action
*b、在循环时,栈顶将发生变化,规则如下:
--在未循环时,栈顶依然是Action
--在第一次循环时,Struts2将循环变量(如user)压入到栈中,因此循环变量占据栈顶位置,而Action处于栈的第二位。
List 的Sort方法排序有三种结果 1,0,-1分别表示大于,等于,小于。
1.对于数值类型的List (List<int>),直接使用Sort进行排序。
List<int> scoreList=new List<int>(){89,100,78,23,67}; scoreList.Sort();//默认按升序排列,相当于:scoreList.Sort((x,y)=>x.CompareTo(y)) scoreList.Sort((x,y)=>-x.CompareTo(y));//降序排列 2.对于非数值类型或者自定义类型,可通过实现IComparable接口重写CompareTo方法来排序:
public class Person : IComparable<Person> { public string Name { get; set; } public int Age { get; set; } //ComparetTo:大于 1; 等于 0; 小于 -1; public int CompareTo(Person p) { int result; if (this.Name == p.Name && this.Age == p.Age) { result = 0; } else { //this.Name表示后面的 Mary p.Name表示前面的 Bob //Mary 跟Bob 由小到大比较,如果Mary 与 Bob 比较 大于0(说明Mary 大于Bob),则 result=1(说明是由小到大的顺序) if (this.
使用 datetimepicker 控件在进行开发时, 空间默认是选择到时分秒的. 如下图 : 在开发的时候. 有很多时候是不需要时分秒的. 在空间加载的时候设置属性即可.
$("#pickupTime").datetimepicker({ minView: "month",//设置只显示到月份 format : "yyyy-mm-dd",//日期格式 autoclose:true,//选中关闭 todayBtn: true//今日按钮 });
原文链接: http://blog.csdn.net/yidu_blog/article/details/51453496
1. 导入微信包
2.添加微信依赖的库
3.MRC的文件修改成ARC
方法:找到文件 -fno-objc-arc 添加这句话
要修改的有2个文件 一个是 pay..... 一个是 apiXml...
改好直接 command + B 编译一下。 成功往下进行
4.在appdelegate里面引入头文件,和协议
#import "payRequsestHandler.h"
#import <QuartzCore/QuartzCore.h>
还有这两个
5. // 向微信注册 [WXApiregisterApp:APP_IDwithDescription:@"demo 2.0"];
添加方法
6.回调方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
//weixin
NSUserDefaults *userDefaults = [[NSUserDefaultsalloc]init];
NSString *ispay = [userDefaultsobjectForKey:@"ispaying"];
if ([ispay isEqualToString:@"weixinpay"]) {
[userDefaults setObject:@""forKey:@"ispaying"];
return [WXApihandleOpenURL:url delegate:self];
}
return YES;
}
7.支付结果回调
//微信支付结果回调
-(void) onResp:(BaseResp *)resp{
[Err] 1093 - You can't specify target table 's' for update in FROM clause
执行SQL
DELETE from book WHERE id IN( SELECT id FROM ( SELECT id,name FROM book WHERE name IN( SELECT name FROM book GROUP BY name HAVING count(name) > 1 ) ) t WHERE id NOT IN ( SELECT id FROM book GROUP BY name HAVING count(name) > 1 ) ); 出现错误:
[Err] 1093 - You can't specify target table 's' for update in FROM clause 执行SQL语句时出现这个错误。原因是在更新这个表和数据时又查询了它,而查询的数据又做了更新的条件
数位dp,一般的题意是要求把某个区间的符合某种特征的数的个数求出来,一般的思路就是把最大数按位分解,然后dfs依次判断每一位相应的数是否满足要求。 把以前做过的几道简单数位dp的题总结一下,可以作为入门题做做。 1. hdu 2089 不要62 题意:给定一个区间[a,b],问在这个区间中的数字,不包含4和62的数有多少个?
分析:数据范围小于1e6,如果暴力的话,再加上分解因数,预处理的时间复杂度数量级最大1e7,查询O(1)。 用数位dp的做法:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int f[8][2],bit[8]; /* f[i][j]:i是位数 j==0,尾位不是6 j==1,尾位是6 */ int dfs(int pos,bool six,bool lim)//位数,尾位是否是6,是否是上限 { if(pos<=0)return 1; if(!lim&&f[pos][six]!=-1)return f[pos][six]; int num=lim?bit[pos]:9; //假设该位是2,下一位是3,如果现在算到该位为1,那么lim=0,表示下一位是能取到9的, //如果该位为2,那么lim=1,下一位只能取到3 int ans=0; for(int i=0;i<=num;i++){ if(i==4||six&&i==2)continue;//如果再加一位是4,或者尾位是6再加一位是2,那么都是不合法的状态,跳过。 ans+=dfs(pos-1,i==6,lim&&i==num); } if(!lim)f[pos][six]=ans; return ans; } int solve(int n) { int len=0; memset(f,-1,sizeof(f)); while(n){ bit[++len]=n%10; n/=10; } return dfs(len,0,1); } int main() { int a,b; while(~scanf("%d%d",&a,&b)&&(a+b)){ printf("%d\n",solve(b)-solve(a-1)); } return 0; } 2.
很多人搜索github,但是芸芸众生,要找到自己想要的项目犹如海底捞针一般,今天教大家几项神技,可以快速找到自己想要的内容。
1、按star数目搜索,比如JavaScript,要求星数,这样就能获取star数目最多的项目
2、follow一些github上面的大牛
请登录:https://github-ranking.com/
国内大牛:http://outofmemory.cn/github/
这里是搜索名人的网址:https://github.com/search
高级搜索:https://github.com/search/advanced
3、Awesome + 你的关键字:搜索一些优秀的框架、教程、项目等
4、看一些搜索技巧,设定条件进行搜索
地址:https://help.github.com/articles/searching-repositories/
5、通过readme看看人家是否发出pull request
看看这篇文章:http://blog.csdn.net/qianlong4526888/article/details/11529981
6、看explore推荐
https://github.com/explore
7、看看其他
http://blog.sina.com.cn/s/blog_4e60b09d0102vcso.html
8、直接github上搜fackbook或者其他,可以看到他们的最新作品
1.下载NppFTP
2.把压缩文档中的bin目录下的两个文件解压到notepad++的plugin目录下
3.重新启动notepad++即安装成功
插件使用:
1.notepad++的“插件”菜单,鼠标悬停在“NppFTP”项上,在出来的下级菜单中选中“ShowNppFTP Window”
2.在notepad++右侧会出现一个窗口,此时此窗口工具栏上按钮都是灰色的,点击工具栏上的”>>”按钮,鼠标悬停在弹出来菜单中的“settings”菜单项上,在弹出来的自己菜单中选择“Profile Setting”,出现“Profile Setting”对话框
3.在对话框最左下角点击“Add New”,在弹出对话框中输入这个ftp配置文件(profile)的名称,点击确定,建立好新配置文件的名称
4.然后在左侧点击刚才建立的配置文件,然后右侧框都由灰色变成可写入状态;在“hostname”中填入ftp主机(ip地址或者域名),“Username”和“Password”中填入ftp用户名和密码,然后直接点击对话框最下方的“close”即可完成配置
5.此时回到notepad++的主页面,看右侧NppFTP的工具栏第一按钮已经成为蓝色,点击之后选择刚才编辑的ftp配置文件,就开始连接到ftp服务器上了。
6.浏览ftp服务器文件操作和一般ftp文件无区别,遇到要编辑的文件直接双击打开,NppFTP会自动下载下来打开,编辑完毕之后按Ctrl+S保存即可自动上传到服务器上。
如果服务器上没有装vsftpd,很简单,sudo apt-get install vsftpfd 即可
需要配置下文件sudo vim /etc/vsftpd.conf,
write_enable = YES ascii_upload_enable = YES ascii_download_enable = YES
这里我使用的是不是匿名登录(直接使用其中一个帐号登录),所以没有使能相关选项
还要记得sudo service vsftpd restart 一下
/etc/vsftpd/vsftpd.conf文件详解,可以对应自己的需求进行修改 #################匿名权限控 制###############
anonymous_enable=YES #是否启用匿名用户 no_anon_password=YES #匿名用户login时不询问口令
下面这四个主要语句控制这文件和文件夹的上传、下载、创建、删除和重命名。 anon_upload_enable=(yes/no); #控制匿名用户对文件(非目录)上传权限。 anon_world_readable_only=(yes/no); #控制匿名用户对文件的下载权限 anon_mkdir_write_enable=(yes/no); #控制匿名用户对文件夹的创建权限 anon_other_write_enable=(yes/no); #控制匿名用户对文件和文件夹的删除和重命名
注:匿名用户下载是使用的是nobody这个用户,所以相应的O这个位置要有R权限才能被下载。若想让匿名用户能上传和删除权限,必需设置
write_enable=YES #全局设置,是否容许写入(无论是匿名用户还是本地用户,若要启用上传权限的话,就要开启他) anon_root=(none) #匿名用户主目录 anon_max_rate=(0) #匿名用户速度限制 anon_umask=(077) #匿名用户上传文件时有掩码(若想让匿名用户上传的文件能直接被匿名下载,就这设置这里为073) chown_uploads=YES #所有匿名上传的文件的所属用户将会被更改成chown_username chown_username=whoever #匿名上传文件所属用户名
#################本地用户权限控 制###############
write_enable=YES #可以上传(全局控制) 删除,重命名 local_umask=022 #本地用户上传文件的umask userlist_enable=YES #限制了这里的用户不能访问 local_root #设置一个本地用户登录后进入到的目录 user_config_dir #设置用户的单独配置文件,用哪个帐户登陆就用哪个帐户命名 download_enable #限制用户的下载权限
补零
PadLeft
this->Caption= this->Caption.StringOfChar('0',10-Caption.Length())+Caption; UnicodeString __fastcall StringOfChar(WideChar Ch, int Count);
str = str.StringOfChar('0', 10 - str.Length()) + str; 转载于:https://www.cnblogs.com/cb168/p/5502218.html
题意: 把一个包含m个正整数的序列划分成k个(1≤k≤m≤500)非空的连续子序列,使得每个正 整数恰好属于一个序列。设第i个序列的各数之和为S(i),你的任务是让所有S(i)的最大值尽 量小。例如,序列1 2 3 2 5 4划分成3个序列的最优方案为1 2 3 | 2 5 | 4,其中S(1)、S(2)、S(3) 分别为6、7、4,最大值为7;如果划分成1 2 | 3 2 | 5 4,则最大值为9,不如刚才的好。每个 整数不超过107。如果有多解,S(1)应尽量小。如果仍然有多解,S(2)应尽量小,依此类推。 分析: 二分最大值,用O(n)扫一遍判断,T=O(nlogn)。 打印最优解的时候比较麻烦,我WA了几次,扫后面尽可能取多的数,然后因为要有k个划分,也就是要k-1个’\’,所以处理到还剩下k个数的时候每隔一个放一个’\’。(注意下标从0开始)
#include<cstdio> #include<stack> #include<iostream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N=555; int a[N]; int n,k; bool ok(ll x) { int tot=k-1; ll t=0; for(int i=0;i<n;i++){ t+=a[i]; if(t>x){ i--; tot--; t=0; if(tot<0)return 0; } } return 1; } int main() { int T; scanf("
解决方法:以"http","https"开头的url在本页用webview进行加载,其他链接进行跳转
private class MyWebViewClient extends WebViewClient{ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(url.startsWith("http:") || url.startsWith("https:") ) { view.loadUrl(url); return false; }else{ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } } }
最近在研究XMPP即时通信,在从好友列表进入聊天页面的时候需要UITableView(消息列表)自动滚动到底部,如下所示: 刚开始试了两种方法,
第一种是在viewDidAppear中设置tableView(scrollView)的contentOffset, [chatTableView setContentOffset:CGPointMake(0, chatTableView.contentSize.height-chatTableView.frame.size.height) animated:NO]; 结果是虽然滚动到底部,但会闪动一下。
第二种方法就是在viewDidAppear中: NSIndexPath *indexpath = [NSIndexPath indexPathForRow:_dataArr.count-1 inSection:0]; [chatTableView scrollToRowAtIndexPath:indexpath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 结果和第一种方法是一样的。
然后突然想起UITableView其实在在调用numberOfRowsInSection时就确定了其contentSize,那么在这个方法里是不是可以通过改变其contentOffset来达到目的呢,试了一下,果不其然,tableView滚动到底部,且没有闪动。
Android底部导航栏的实现方式特别多,例如TabHost,TabLayout,或者TextView等,都可以实现底部导航栏的效果,但是却没有Google官方统一的导航栏样式,今天讲的就是Google最近添加到Material design中的底部导航栏BottomNavigationBar,也可以说是现今Android底部导航栏的一个标准与统一吧。
效果:
实现效果:
实现:
1.下载jar包 2.添加Maven
<dependency> <groupId>com.ashokvarma.android</groupId> <artifactId>bottom-navigation-bar</artifactId> <version>1.2.0</version> <type>pom</type> </dependency> 3.添加依赖。
compile 'com.ashokvarma.android:bottom-navigation-bar:1.2.0' 4.添加Ivy
<dependency org='com.ashokvarma.android' name='bottom-navigation-bar' rev='1.2.0'> <artifact name='$AID' ext='pom'></artifact> </dependency> 布局设置
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.wangchang.testbottomnavigationbar.MainActivity"> <FrameLayout android:id="@+id/layFrame" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <com.ashokvarma.bottomnavigation.BottomNavigationBar android:id="@+id/bottom_navigation_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" /> </LinearLayout> 这个很简单,不用详叙。
主页面实现:
package com.example.wangchang.testbottomnavigationbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.ashokvarma.bottomnavigation.BottomNavigationBar; import com.ashokvarma.bottomnavigation.BottomNavigationItem; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements BottomNavigationBar.
var v_yesterday = new Date(); v_yesterday.setDate(v_yesterday.getDate()-1); var v_tmp_endTime = v_yesterday.format("yyyy.MM.dd 23:59:59"); var v_tmp_startTime = v_yesterday.format("yyyy.MM.dd 00:00:00"); jq("#endTime").val(v_tmp_endTime); jq("#startTime").val(v_tmp_startTime); Date.prototype.Format = function(fmt) { var o = { "M+" : this.getMonth()+1, //月份 "d+" : this.getDate(), //日 "h+" : this.getHours(), //小时 "m+" : this.getMinutes(), //分 "s+" : this.getSeconds(), //秒 "q+" : Math.floor((this.getMonth()+3)/3), //季度 "S" : this.getMilliseconds() //毫秒 }; if(/(y+)/.test(fmt)) fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); for(var k in o) if(new RegExp("("+ k +")").test(fmt)) fmt = fmt.
Bootstrap预定义了一些样式,Bootstrap1.0使用的是以前的重置样式表,但是Bootstrap2.0使用Nicolas Gallagher写的Normalize.css,HTML5 Boilerplate使用的也是这个样式,这个样式表包含在bootstrap.css中
特别值得注意的是以下几种默认样式,它们专门针对排版和链接:
1)从body中去掉了margin,这样内容就会紧贴浏览器窗口边缘。
2)为body应用了background-color:white;
3)Bootstrap以@baseFontFamily、@baseFontSize和@baseLineHeight属性作为排版的基准,确保整个网站的标题以其他内容的行高一致;
4)Bootstrap通过@linkColor设置全局链接颜色,只在:hover状态下为链接加下划线。
Why use sentry? Sentry1 is a modern error logging and aggregation platform. The Sentry package fundamentally is just a simple server and web UI. It will handle authenticating clients (such as Raven) and all of the logic behind storage and aggregation.
Sentry2 is not limited to Python. The primary implementation is in Python, but it contains a full API for sending events from any language, in any application.
How to Setup Sentry Server?
问题:打印反序数。
背景:反序数即镜面数。例如:123456的反序数是654321。
思路: 1.更新输入数:将最右边的数,即个位数独立出来。 2.更新输出数:用*10的方法将整个输出数序列左移一位,再加上刚得到的个位数,即得到反序。 3.循环计算直到输入数一位都不剩。
#include "stdafx.h" #include <stdlib.h> #include <math.h> int reverseDigits(int number) { int reverseNumber = 0; int temp; while (number > 0) { temp = number % 10;//得到个位 number = number / 10;//number缩小一位 reverseNumber = reverseNumber * 10 + temp;//reverseNumber增加一位,增加的数为刚取得的个位temp } return reverseNumber; } void main() { int n; scanf_s("%d", &n); n = reverseDigits(n); printf("%d\n", n); system("pause"); }
数据链路层有三个目的:
(1)为IP模块发送和 接收IP数据报。 (2)为ARP模块发送ARP请求和接收ARP应答。 (3)为RARP发送RARP请 求和接收RARP应答。 ARP叫做地址解析协议,是用IP地址转MAC地址的一种协议。 RARP则叫做逆地址解析协议,是用MAC地址转IP地址的一种协议。
数据链路层属于计算机网络的底层,使用的信道主要有点对点信道和广播信道两种类型。
TCP/IP支持多种不同的链路层协议,这取决于网络所使用的硬件,如以太网,令牌环网,FDDI(光纤分布式数据接口)及RS-232串行线路等。
数据链路层的协议数据单元——帧:将IP层(网络层)的数据报添加首部和尾部封装成帧。 数据链路层协议有许多种,都会解决三个基本问题:封装成帧,透明传输,差错检测。
最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。 如果在IP层要传输一个数据报比链路层的MTU还大,那么IP层就会对这个数据报进行分片。一个数据报会被分为若干片,每个分片的大小都小于或者等于链路层的MTU值。当同一网络上的主机互相进行通信时,该网络的MTU对通信双方非常重要。但当主机间要通过很多网络才能通信时,对通信双方最重要的是通信路径中最小的MTU,因为在通信路径上不同网络的链路层MTU不同。通信路径中最小的MTU被称为路径MTU。
CSMA/CD(Carrier Sense Multiple Access/Collision Detect)即载波监听多路访问/冲突检测机制。作用是防止连接在总线上的各站点之间发生冲突,协调总线上各计算机工作的协议。 (1)多点接入:说明这是总线型网络,许多计算机以多点接入的方式连接到总线上。 (2)载波监听:是指每一个站在发送数据之前要检测一下总线上是否有其他的计算机在发送数据,如果有,则暂时不发送数据,以免发生碰撞 (3)碰撞检测:边发送数据边检测信道上的信号电压大小。当信号电压摆动值超过一定的门限值,表明发生了碰撞。立即停止发送,等待一段时间后再次发送。
对于环回接口,需要注意的地方:
(1)传给环回地址(一般是127.0.0.1)的任何数据均作为I P输入。 (2)传给广播地址或多播地址的数据报复制一份传给环回接口,然后送到以太网上。这是 因为广播传送和多播传送的定义包含主机本身。 (3)任何传给该主机IP地址的数据均送到环回接口。
2019独角兽企业重金招聘Python工程师标准>>> 接着上一次的工程,这次把读取音频包跟解码音频包放到不同的线程里面去。而且找到了播放卡顿的原因,按照网上大神的说法,就是输出缓冲区out_size的大小要跟随swr_convert的返回值,具体取值为
out_size = swr_convert返回值 X 输出通道数 X 输出样本数;
这里的输出样本数count是这样计算的:
switch(audio_out.sample_fmt) { case AV_SAMPLE_FMT_F32:count = 4;break; case AV_SAMPLE_FMT_S16:count = 2;break; case AV_SAMPLE_FMT_U8: count = 1;break; } 按照如上设置好以后,会发现音频很完整地输出了。
但还存在一个问题,就是延时还是没有设置好,导致部分音乐播放过快,而部分音乐播放缓慢,严重还会出现数堆栈下溢。
下面直接上源码,配置过程参照上次发表的配置,亲测在windows 还有ubuntu里面都能正常播放,另外我用的是Qt5.5 ++
//qtplayer.h #ifndef QTPLAYER_H #define QTPLAYER_H #include <QtMultimedia/QAudio> #include <QtMultimedia/QAudioFormat> #include <QtMultimedia/QAudioOutput> #include <QMutex> #include <QWaitCondition> #include <QTest> #include <QThread> #ifdef __cplusplus extern "C"{ #endif #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswresample/swresample.h> #include <libavutil/opt.h> #ifdef __cplusplus } #endif #define OK 1 #define ERROR -1 #define MAX_QUEUE_SIZE 100 #define MAX_AUDIO_FRAME_SIZE 192000 #define MAX_AUDIO_FRAME_SIZE_HIGH 320000 //封装好的音频参数 struct AudioParam{ int64_t channel_layout; int nb_samples; int channels; int sample_rate; AVSampleFormat sample_fmt; }; //数据包节点,其实FFmpeg自带了AVPacketList class PacketNode{ public: AVPacket pkt; PacketNode* next; public: PacketNode(); }; //包队列 class PacketQueue{ private: PacketNode* first; //队列头,指向第一个数据包 PacketNode* rear; //队列尾,指向最后一个数据包 int len; //队列长度,即多少个数据包 QMutex mutex; //读写锁 QWaitCondition cond; //读写条件 public: PacketQueue(); int destroyQueue(); int putPacket(AVPacket* pkt ); int getPacket(AVPacket* pkt ); int initQueue(); int getSize(); }; //音频参数 struct AudioState{ char url[512]; //文件名 AVFormatContext* pFmtCtx; // AVCodecContext* iAcc; int audioStream; //音频流索引 SwrContext* pSwrCtx; //音频参数转换上下文 AVFrame* pDecoded; //存放解码后的音频帧 PacketQueue pktList; // }; //播放线程类 class QtPlayer:public QThread { private: volatile bool stopped; AudioState* as; char errStr[128]; public: QtPlayer(); void getAudioState(AudioState* ); void run(); void stop(); char* getErrStr(); }; //读取数据包线程类 class ReadPacket:public QThread { private: volatile bool stopped; AudioState* as; char errStr[128]; public: ReadPacket(); void getAudioState(AudioState* ); void run(); void stop(); char* getErrStr(); }; AudioState *createAudioState(char* url); #endif // QTPLAYER_H 源文件:
我们如果想要一个属于自己的网站,都需要买域名和服务器,然而,这些都需要人民币。下面我来和大家分享一个小技巧,来免费创建自己的网站。 在github上搭建起来自己的主页下面我们一起来看一下如何搭建。
在github上放自己的网页 (一) 首先自己要有一个github账号,那么去注册一个:https://github.com/join?source=login ,注册好了之后,我们进入github 。比如以前我注册的名称是 johnnynode 。
(二) 然后点击右上角的 “+”号 ,我们再次点击 “New repository”,好的,进入页面,我们填写Repository name ,填写的格式是 : 你注册的用户名.github.io, 比如我填写的是johnnynode.github.io 然后点击绿色的“Create repository” 按钮。我们就创建了一个自己的仓库了。不过里面啥都没有 ^_^…
(三) 然后我们就要把我们自己的主页放到github上了。首先我们需要有git工具 如果是windows,需要在环境变量里配置git,以确保我们可以使用git这个命令,我们可以用 git bash 或者 windows的 cmd 命令来完成 。
(四) 我们可以按照页面上的提示去操作,我经常习惯的就是先把那个刚创建的空仓库克隆下来,如果使用cmd,那么找个目录,按住键盘的shift键,鼠标右键,选择“在此处打开命令窗口”。
(五) 首先我们很有必要的配置一下全局参数 git config --global user.name '此处输入自已的名字' git config --global user.email '此处输入自已的邮箱地址' (六) 配置完成后,我们从仓库上把我们仓库的地址克隆到本地
格式为:git clone '我的仓库地址' '我本地文件夹的名称' 示例为: git clone git@github.johnnynode/johnnynode.github.io.git johnnynode 说明:此处之前,在github上我选择的是SSH的加密方式,所以我克隆的地址是这个: git@github.johnnynode/johnnynode.github.io.git ,在命令的最后是我要克隆后生成仓库文件夹的名称 : johnnynode,当然,你需要自己弄属于你自己的文件夹,克隆好后,我们就可以把我们的页面文件拷贝到这个文件夹下了,在这个文件夹下我们来建一个index.html文件。 (七) 我们通过cd命令进入这个文件夹。然后我们需要add和commit
用命令 git add -A 或者 git add --all 然后我们提交改动的文件 git commit -m 'init commit' 此处不对git命令进行深究, 这个意思是把暂存区中的内容提交到仓库中,然后我们就可以往github上push了。 (八)往github上提交 我们使用命令 git push -u origin master 我们默认在master分支上操作,这个我们也不深究。等待提交完成后,我们刷新仓库的页面,发现我们的文件已经放到github上了。(如果在这个过程中遇到了问题,比如访问权限的问题,那么我们需要提供用户名和密码,如果想省略这步骤,需要自己去设置SSH and GPG keys 官网上有介绍,不做深究)
http://acm.cqu.edu.cn/oj/problem_show.php?pid=21464
本题不是很难,仔细观察就可以得知x+n-i是恒定的(x是每个人的金钱,n是队列的长度,i是在当前位置。如果那么很显然的一点是如果出现相同的xi+n-i,那么一定是无限交换队列。 下面附上AC代码。
#include<iostream> #include<algorithm> #include<cstdio> #include<queue> #include<cstring> #include<cstring> using namespace std; const int maxn=2e6+10; bool vis[maxn]; int main() { int t; scanf("%d",&t); int ca=1; while(t--) { int n; scanf("%d",&n); bool flag=false; memset(vis,false,sizeof(vis)); for(int i=0;i<n;i++) { int a; scanf("%d",&a); int b=a+n-i; if(vis[b]) flag=true;//如果出现相同的 vis[b]=true; } if(flag) { printf("Case %d: No\n",ca++); }else{ printf("Case %d: Yes\n",ca++); } } }
name是input标签的属性值,jQuery提供了attr() 方法用于设置/改变属性值
$("input:text").attr("name");
$("input:text").prop("name"); // 也可以使用prop()方法获取属性
$("*[name='name']").val(); //获取vlaue值 $("*[name='name']").attr('id','name'); //添加id名称 $("*[name='name']").after('<div>hello world</div>'); //在当前外添加元素 jquery通过name属性取值的方法 alert($("input[name='inputTest']").val());
alert($("input[type='text']").attr("id")); //这个是取id的值,方便记就写在这儿了
$("input[name='inputTest']").each(
function(){
alert($(this).val());
}
) alert($("input[name='inputTest']")[0].value);
alert($("input[name='inputTest']")[1].value);
alert($("input[name='inputTest']").get(0).value); //此处也可以得到值,等同于上面两行
alert($("input[name='inputTest']").get(1).value);
根据name取值: $("input[name='mobile']").val() 根据id取值: $("#mobile_reg_form").html() 根据name取值了遍历: $("input[name='mobile']").each( function(){ alert($(this).val()); } ) 取出form中的input: <script type="text/javascript" language="JavaScript" charset="UTF-8"> $(document).ready(function(){ var a=$("form input"); $.each( a, function(name,object){ alert(name+":"+$(object).val()); } ); }); </script> 得到值(多个的情况): $("input[name='mobile']")[0].value $("input[name='mobile']").get(1).value -----jquery添加删除样式-------- 给一个标签添加样式: $("#id").addClass("style"); 删除一个标签的样式: $("#id").removeClass("style"); 注:"#id" id是对应标签的id,style是对应css样式的名称 转载于:https://www.cnblogs.com/zhangliang88/p/5468840.html
内存区域可以分为栈,堆,静态存储区和常量存储区。局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。
C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h
1. malloc函数
malloc函数可以从堆上获得指定字节的内存空间,其函数声明如下:
void * malloc(int n);
其中,形参n为要求分配的字节数。如果函数执行成功,malloc返回获得内存空间的首地址;如果函数执行失败,那么返回值为NULL。由于malloc函数值的类型为void型指针,因此,可以将其值类型转换后赋给任意类型指针,这样就可以通过操作该类型指针来操作从堆上获得的内存空间。
需要注意的是,malloc函数分配得到的内存空间是未初始化的。因此,一般在使用该内存空间时,要调用另一个函数memset来将其初始化为全0。memset函数的声明如下:
void * memset (void * p,int c,int n) ;
该函数可以将指定的内存空间按字节单位置为指定的字符c。其中,p为要清零的内存空间的首地址,c为要设定的值,n为被操作的内存空间的字节长度。如果要用memset清0,变量c实参要为0。malloc函数和memset函数的操作语句一般如下:
int * p=NULL;
p=(int *)malloc(sizeof(int));
if(p==NULL)
printf(“Can’t get memory!\n”);
memset(p,0,siezeof(int));
注意:通过malloc函数得到的堆内存必须使用memset函数来初始化。
demo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int * p=NULL;
p=(int *)malloc(sizeof(int));
if(NULL==p){
printf("Can't get memory!\n");
return -1;
}
printf("%d\n",*p); //输出分配的空间上的值
memset(p,0,sizeof(int)); //将p指向的空间清0
printf("%d\n",*p); //输出调用memset函数后的结果
*p=2;
printf("%d\n",*p);
return 0;
}
2. free函数
从堆上获得的内存空间在程序结束以后,系统不会将其自动释放,需要程序员来自己管理。一个程序结束时,必须保证所有从堆上获得的内存空间已被安全释放,否则,会导致内存泄露。例如上面的demo就会发生内存泄露。
前言:
好几天没动手了,感觉有点手懒了,干我们这行真的一点不能懈怠啊!
回来写了个仿扣扣聊天界面的实现,动态添加聊天内容等!
分析:
主体:RecylerView+LinearLayout
效果:
简单的模仿一下扣扣。
下面介绍一下怎么实现的
demo结构:
看起来没那么复杂哈。
主页面布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#EEEEEE" android:orientation="vertical" tools:context=".activity.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recylerView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="48dp" android:background="#EEEEEE" android:orientation="horizontal" android:padding="4dp"> <EditText android:id="@+id/et" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="4dp" android:layout_weight="5" android:paddingLeft="4dp" android:textSize="14sp" android:background="@drawable/bg_et" /> <TextView android:id="@+id/tvSend" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="4dp" android:layout_weight="1" android:background="@drawable/bg_send" android:gravity="center" android:padding="6dp" android:text="发送" android:textColor="#FFFFFF" android:textSize="10sp" /> </LinearLayout> </LinearLayout> 就是一个RecylerView+LinearLayout 适配器主要实现
@Override public ChatAdapter.BaseAdapter onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case ItemModel.
两种方法证明积分中值定理
1、执行流程
原始序列:49、38、65、97、76、13、27
(1)将原始序列看成是7个只含有一个元素的子序列,显然这些子序列都是有序的。
子序列1:49
子序列2:38
子序列3:65
子序列4:97
子序列5:76
子序列6:13
子序列7:27
(2)两两归并,形成若干有序二元组。第一趟二路归并排序结束,结果如下:
{38、49,},{65、97},{13、76},{27}
(3)再将这个序列看成若干二元组子序列。
子序列1:38、49
子序列2:65、97
子序列3:13、76
子序列4:27
(4)继续两两归并,形成若干有序四元组。。第二趟二路归并排序结束,结果如下:
{38、49、65、97},{13、27、76}
(5)最后只有两个子序列了,在进行一次归并,就可完成整个二路归并排序,结果如下:
13、27、38、49、65、76、97
最近在做各类小应用,用到了MYSQL,有时候会用到一些比较复杂的嵌套查询,在研究怎么通过SQL实现这些。 假设下面这张表(stu)描述学生的基本信息:
idnamegrade1Jim72Tom83Cake9……… 另外一张表(sco)描述学生的成绩信息:
stu_idsubjectscore1math782math833physics90……… 现在想查询七年级学生的数学成绩,那么sql语句应该这么写:
select * from stu left join sco on stu.id = sco.stu_id where stu.grade = 7 and sco.subject = "math"; 两个表都有过滤条件,博主在实际应用场景下,两个表要复杂得多,而且过滤条件也多,于是在想有没有办法先select出两张表,然后再join。从性能上说,先过滤也有利于后续join的过程。当然,数据库对这些肯定有相应优化。我们还是回归到一个基本问题, 两个子查询怎么样进行join呢?
select * from (select * from stu where grade = 7) s left join (select * from sco where subject = "math") t on s.id = t.stu_id; 注意在上面的例子当中,两个子查询的写法,查询语句括起来,紧跟一个表的临时命名。 再写个复杂的例子,我们知道mysql不支持全外连接,如果要对上面的表进行全外连接,怎么办呢? 思路也简单,先左外连接,再右外连接,最后求并。
select * from (select * from stu where grade = 7) s left join (select * from sco where subject = "
一个电子产品,它的质量究竟什么起主导?
答案应该是通过工程师的设计与研发,产线的生产、制造出来的,这是主导,在研发过程中,检验、检测非常重要,因为这个环节更是注重细节的一个关键点。
在整个电子产品的流程中,这个产品过程细节决定一切,细节中一个关键的因素就是创新,而不是一味的模仿。创新一个很重要的点就是质量,简单解释就是,质量是创新的前提。
我更加觉得,苹果手机的诞生,是一种注重细节的精神。 所以说,作为产品决策者和研发者,如果我们在设计、研发、生产中能关注到每一个细节,我们就可以实现生产出高质量的产品来。
接下来就需要好好研究市场规律了,这个学问很大 ……
为了兑现“做最懂技术的产品经理”的诺言,我上周开始捣腾PHP了。虽然早在大学读书的时候,我也曾经玩过一小段时间的PHP,不过到如今,也忘得一干二净了。所以,偶和一个PHP菜鸟无异。既然是菜鸟,自然先从搭建PHP开发环境开始了。
首先,从PHP的官方网站下载了PHP 5.2.14 For Windows的压缩包,解压至D盘的PHP目录;随后下载了Apache HTTP Server的最新版本——2.2.17,是MSI格式的,安装也非常简单。接着就是将PHP与HTTP Server关联起来——让HTTP Server能够处理php请求,其实也就是修改httpd.conf文件了。有关这一点,网上的资料已经非常详细,官方的介绍在这里。环境搭建好了之后,为了让PHP能够更强大,接下来就是通过修改PHP.ini文件来装载所需的PHP Extention(PHP扩展)了,而这些扩展在Windows平台下就是一个个动态链接库(DLL文件)。这下老大难的问题来了——无法装载某些动态链接库(PHP startup: Unable to load dynamic library)。对于这个问题,我们通过Google能够找到如下的解决方案:
切记修改Windows的环境变量,在PATH环境变量当中增加PHP所在的路径以及PHP扩展所在的路径;如果第一点做了之后,仍然无法解决,就要留意被加载的动态链接库所依赖的DLL文件是否缺失。PHP官方提供了一个在Windows下安装PHP扩展的指南,里面指出了依赖关系。 通常上述两个方案就能解决无法装载动态链接库的问题了,但是也会有例外的。上个星期我在搭建PHP开发环境的时候,就遇到了无法装载php_curl.dll动态链接库的问题。不管是环境变量还是依赖的DLL文件(官方文档指出:php_curl.dll所依赖的文件是libeay32.dll, ssleay32.dll)都是齐备的,这让我百思不得其解。我把网上能够找到的办法都试了个遍,甚至还把相关的dll文件全部复制到了Windows的system32目录当中(其实这样做是毫无意义的)。这个小问题让我整个周末如鲠在喉,甚是不爽。经过一番思考,我还是把问题定位到了动态链接库所依赖的DLL文件缺失上。
尽管官方文档告诉我php_curl只依赖上述两个DLL文件,但这是真的么?于是,我在下载了查看DLL依赖关系的软件——Dependency Walker。用这个软件一看,果然不出我所料:php_curl.dll所依赖的zlib.dll不存在!找到问题根源,接下来的事情都好办了,通过Google找到zlib的老巢,下载最新的zlib.dll,然后将该文件放到PHP的安装目录下即可(这里仍然需要注意两点,一是对于下载的DLL文件,如果文件名不是zlib.dll,需要改为zlib.dll;二是PHP安装的目录必须加入到PATH环境变量中)。至此,问题解决!