转的一杂谈

1、HTML静态化其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。
2、图片服务器分离大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。

3、数据库集群和库表散列大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。

4、缓存缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多了,.net不是很熟悉,相信也肯定有。

5、镜像镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如 ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。
6、负载均衡负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。

7、硬件四层交换第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚 IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了

。8、软件四层交换大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。对于大型网站来说,前面提到的每个方法可能都会被同时使用到,我这里介绍得比较浅显,具体实现过程中很多细节还需要大家慢慢熟悉和体会,有时一个很小的squid参数或者apache参数设置,对于系统性能的影响就会很大,希望大家一起讨论,达到抛砖引玉之效。


用squid做web cache server,而apache在squid的后面提供真正的web服务。当然使用这样的架构必须要保证主页上大部分都是静态页面。这就需要程序员的配合将页面在反馈给客户端之前将页面全部转换成静态页面。
基本看出sina和sohu对于频道等栏目都用了相同的技术,即squid来监听这些IP的80端口,而真正的web server来监听另外一个端口。从用户的感觉上来说不会有任何的区别,而相对于将web server直接和客户端连在一起的方式,这样的方式明显的节省的带宽和服务器。用户访问的速度感觉也会更快。
http://www.dbanotes.net/arch/yupoo_arch.html 

带宽:4000M/S (参考) 
服务器数量:60 台左右 
Web服务器:Lighttpd, Apache, nginx 
应用服务器:Tomcat 
其他:Python, Java, MogileFS 、ImageMagick 等 

关于 Squid 与 Tomcat 

Squid 与 Tomcat 似乎在 Web 2.0 站点的架构中较少看到。我首先是对 Squid 有点疑问,对此阿华的解释是"目前暂时还没找到效率比 Squid 高的缓存系统,原来命中率的确很差,后来在 Squid 前又装了层 Lighttpd, 基于 url 做 hash, 同一个图片始终会到同一台 squid 去,所以命中率彻底提高了"

对于应用服务器层的 Tomcat,现在 Yupoo! 技术人员也在逐渐用其他轻量级的东西替代,而 YPWS/YPFS 现在已经用 Python 进行开发了。 

名次解释: 

· YPWS--Yupoo Web Server YPWS 是用 Python开发的一个小型 Web 服务器,提供基本的 Web 服务外,可以增加针对用户、图片、外链网站显示的逻辑判断,可以安装于任何有空闲资源的服务器中,遇到性能瓶颈时方便横向扩展。

· YPFS--Yupoo File System 与 YPWS 类似,YPFS 也是基于这个 Web 服务器上开发的图片上传服务器。 


【Updated: 有网友留言质疑 Python 的效率,Yupoo 老大刘平阳在 del.icio.us 上写到 "YPWS用Python自己写的,每台机器每秒可以处理294个请求, 现在压力几乎都在10%以下"】

图片处理层 

接下来的 Image Process Server 负责处理用户上传的图片。使用的软件包也是 ImageMagick,在上次存储升级的同时,对于锐化的比率也调整过了(我个人感觉,效果的确好了很多)。”Magickd“ 是图像处理的一个远程接口服务,可以安装在任何有空闲 CPU资源的机器上,类似 Memcached的服务方式。

我们知道 Flickr 的缩略图功能原来是用 ImageMagick 软件包的,后来被雅虎收购后出于版权原因而不用了(?);EXIF 与 IPTC Flicke 是用 Perl 抽取的,我是非常建议 Yupoo! 针对 EXIF 做些文章,这也是潜在产生受益的一个重点。

图片存储层 

原来 Yupoo! 的存储采用了磁盘阵列柜,基于 NFS 方式的,随着数据量的增大,”Yupoo! 开发部从07年6月份就开始着手研究一套大容量的、能满足 Yupoo! 今后发展需要的、安全可靠的存储系统“,看来 Yupoo! 系统比较有信心,也是满怀期待的,毕竟这要支撑以 TB 计算的海量图片的存储和管理。我们知道,一张图片除了原图外,还有不同尺寸的,这些图片统一存储在 MogileFS 中。

对于其他部分,常见的 Web 2.0 网站必须软件都能看到,如 MySQL、Memcached 、Lighttpd 等。Yupoo! 一方面采用不少相对比较成熟的开源软件,一方面也在自行开发定制适合自己的架构组件。这也是一个 Web 2.0 公司所必需要走的一个途径。

非常感谢一下 Yupoo! 阿华对于技术信息的分享,技术是共通的。下一个能爆料是哪家? 

--EOF-- 

lighttpd+squid这套缓存是放在另外一个机房作为cdn的一个节点使用的,图中没描绘清楚,给大家带来不便了。 
squid前端用lighttpd没用nginx,主要是用了这么久,没出啥大问题,所以就没想其他的了。 
URL Hash的扩展性的确不好,能做的就是不轻易去增减服务器,我们目前是5台服务器做一组hash. 

我们现在用Python写的Web Server,在效率方面,我可以给个测试数据,根据目前的访问日志模拟访问测试的结果是1台ypws,平均每秒处理294个请求(加载所有的逻辑判断)。
在可靠性上,还不没具体的数据,目前运行1个多月还没有任何异常。 

lvs每个节点上都装nginx,主要是为了反向代理及处理静态内容,不过apache已显得不是那么必需,准备逐渐去掉。 

我们处理图片都是即时的,我们目前半数以上的服务器都装了magickd服务,用来分担图片处理请求。 



http://www.dbanotes.net/review/tailrank_arch.html 

每天数以千万计的 Blog 内容中,实时的热点是什么? Tailrank 这个 Web 2.0 Startup 致力于回答这个问题。 

专门爆料网站架构的 Todd Hoff 对 Kevin Burton 进行了采访。于是我们能了解一下 Tailrank 架构的一些信息。每小时索引 2400 万的 Blog 与 Feed,内容处理能力为 160-200Mbps,IO 写入大约在10-15MBps。每个月要处理 52T 之多的原始数据。Tailrank 所用的爬虫现在已经成为一个独立产品:spinn3r。

服务器硬件 

目前大约 15 台服务器,CPU 是 64 位的 Opteron。每台主机上挂两个 SATA 盘,做 RAID 0。据我所知,国内很多 Web 2.0 公司也用的是类似的方式,SATA 盘容量达,低廉价格,堪称不二之选。操作系统用的是 Debian Linux 。Web 服务器用 Apache 2.0,Squid 做反向代理服务器。

数据库 

Tailrank 用 MySQL 数据库,联邦数据库形式。存储引擎用 InnoDB, 数据量 500GB。Kevin Burton 也指出了 MySQL 5 在修了一些 多核模式下互斥锁的问题(This Bug?)。到数据库的JDBC 驱动连接池用 lbpool 做负载均衡。MySQL Slave 或者 Master的复制用 MySQLSlaveSync 来轻松完成。不过即使这样,还要花费 20%的时间来折腾 DB。

其他开放的软件 

任何一套系统都离不开合适的 Profiling 工具,Tailrank 也不利外,针对 Java 程序的 Benchmark 用 Benchmark4j。Log 工具用 Log5j(不是 Log4j)。Tailrank 所用的大部分工具都是开放的。

Tailrank 的一个比较大的竞争对手是 Techmeme,虽然二者暂时看面向内容的侧重点有所不同。其实,最大的对手还是自己,当需要挖掘的信息量越来越大,如果精准并及时的呈现给用户内容的成本会越来越高。从现在来看,Tailrank 离预期目标还差的很远。期待罗马早日建成


YouTube架构学习 

关键字: YouTube 

原文: YouTube Architecture 

YouTube发展迅速,每天超过1亿的视频点击量,但只有很少人在维护站点和确保伸缩性。 

平台 
Apache 
Python 
Linux(SuSe) 
MySQL 
psyco,一个动态的Python到C的编译器 
lighttpd代替Apache做视频查看 

状态 
支持每天超过1亿的视频点击量 
成立于2005年2月 
于2006年3月达到每天3千万的视频点击量 
于2006年7月达到每天1亿的视频点击量 
2个系统管理员,2个伸缩性软件架构师 
2个软件开发工程师,2个网络工程师,1个DBA 

处理飞速增长的流量 

Java代码 

1. while (true) 

2. { 

3. identify_and_fix_bottlenecks(); 

4. drink(); 

5. sleep(); 

6. notice_new_bottleneck(); 

7. } 

while (true) 



identify_and_fix_bottlenecks(); 

drink(); 

sleep(); 

notice_new_bottleneck(); 




每天运行该循环多次 

Web服务器 
1,NetScaler用于负载均衡和静态内容缓存 
2,使用mod_fast_cgi运行Apache 
3,使用一个Python应用服务器来处理请求的路由 
4,应用服务器与多个数据库和其他信息源交互来获取数据和格式化html页面 
5,一般可以通过添加更多的机器来在Web层提高伸缩性 
6,Python的Web层代码通常不是性能瓶颈,大部分时间阻塞在RPC 
7,Python允许快速而灵活的开发和部署 
8,通常每个页面服务少于100毫秒的时间 
9,使用psyco(一个类似于JIT编译器的动态的Python到C的编译器)来优化内部循环 
10,对于像加密等密集型CPU活动,使用C扩展 
11,对于一些开销昂贵的块使用预先生成并缓存的html 
12,数据库里使用行级缓存 
13,缓存完整的Python对象 
14,有些数据被计算出来并发送给各个程序,所以这些值缓存在本地内存中。这是个使用不当的策略。应用服务器里最快的缓存将预先计算的值发送给所有服务器也花不了多少时间。只需弄一个代理来监听更改,预计算,然后发送。

视频服务 
1,花费包括带宽,硬件和能源消耗 
2,每个视频由一个迷你集群来host,每个视频被超过一台机器持有 
3,使用一个集群意味着: 
-更多的硬盘来持有内容意味着更快的速度 
-failover。如果一台机器出故障了,另外的机器可以继续服务 
-在线备份 
4,使用lighttpd作为Web服务器来提供视频服务: 
-Apache开销太大 
-使用epoll来等待多个fds 
-从单进程配置转变为多进程配置来处理更多的连接 
5,大部分流行的内容移到CDN: 
-CDN在多个地方备份内容,这样内容离用户更近的机会就会更高 
-CDN机器经常内存不足,因为内容太流行以致很少有内容进出内存的颠簸 
6,不太流行的内容(每天1-20浏览次数)在许多colo站点使用YouTube服务器 
-长尾效应。一个视频可以有多个播放,但是许多视频正在播放。随机硬盘块被访问 
-在这种情况下缓存不会很好,所以花钱在更多的缓存上可能没太大意义。 
-调节RAID控制并注意其他低级问题 
-调节每台机器上的内存,不要太多也不要太少 

视频服务关键点 
1,保持简单和廉价 
2,保持简单网络路径,在内容和用户间不要有太多设备 
3,使用常用硬件,昂贵的硬件很难找到帮助文档 
4,使用简单而常见的工具,使用构建在Linux里或之上的大部分工具 
5,很好的处理随机查找(SATA,tweaks) 

缩略图服务 
1,做到高效令人惊奇的难 
2,每个视频大概4张缩略图,所以缩略图比视频多很多 
3,缩略图仅仅host在几个机器上 
4,持有一些小东西所遇到的问题: 
-OS级别的大量的硬盘查找和inode和页面缓存问题 
-单目录文件限制,特别是Ext3,后来移到多分层的结构。内核2.6的最近改进可能让Ext3允许大目录,但在一个文件系统里存储大量文件不是个好主意 
-每秒大量的请求,因为Web页面可能在页面上显示60个缩略图 
-在这种高负载下Apache表现的非常糟糕 
-在Apache前端使用squid,这种方式工作了一段时间,但是由于负载继续增加而以失败告终。它让每秒300个请求变为20个 
-尝试使用lighttpd但是由于使用单线程它陷于困境。遇到多进程的问题,因为它们各自保持自己单独的缓存 
-如此多的图片以致一台新机器只能接管24小时 
-重启机器需要6-10小时来缓存 
5,为了解决所有这些问题YouTube开始使用Google的BigTable,一个分布式数据存储: 
-避免小文件问题,因为它将文件收集到一起 
-快,错误容忍 
-更低的延迟,因为它使用分布式多级缓存,该缓存与多个不同collocation站点工作 
-更多信息参考Google Architecture,GoogleTalk Architecture和BigTable 

数据库 
1,早期 
-使用MySQL来存储元数据,如用户,tags和描述 
-使用一整个10硬盘的RAID 10来存储数据 
-依赖于信用卡所以YouTube租用硬件 
-YouTube经过一个常见的革命:单服务器,然后单master和多read slaves,然后数据库分区,然后sharding方式 
-痛苦与备份延迟。master数据库是多线程的并且运行在一个大机器上所以它可以处理许多工作,slaves是单线程的并且通常运行在小一些的服务器上并且备份是异步的,所以slaves会远远落后于master
-更新引起缓存失效,硬盘的慢I/O导致慢备份 
-使用备份架构需要花费大量的money来获得增加的写性能 
-YouTube的一个解决方案是通过把数据分成两个集群来将传输分出优先次序:一个视频查看池和一个一般的集群 
2,后期 
-数据库分区 
-分成shards,不同的用户指定到不同的shards 
-扩散读写 
-更好的缓存位置意味着更少的IO 
-导致硬件减少30% 
-备份延迟降低到0 
-现在可以任意提升数据库的伸缩性 

数据中心策略 
1,依赖于信用卡,所以最初只能使用受管主机提供商 
2,受管主机提供商不能提供伸缩性,不能控制硬件或使用良好的网络协议 
3,YouTube改为使用colocation arrangement。现在YouTube可以自定义所有东西并且协定自己的契约 
4,使用5到6个数据中心加CDN 
5,视频来自任意的数据中心,不是最近的匹配或其他什么。如果一个视频足够流行则移到CDN 
6,依赖于视频带宽而不是真正的延迟。可以来自任何colo 
7,图片延迟很严重,特别是当一个页面有60张图片时 
8,使用BigTable将图片备份到不同的数据中心,代码查看谁是最近的 

学到的东西 
1,Stall for time。创造性和风险性的技巧让你在短期内解决问题而同时你会发现长期的解决方案 
2,Proioritize。找出你的服务中核心的东西并对你的资源分出优先级别 
3,Pick your battles。别怕将你的核心服务分出去。YouTube使用CDN来分布它们最流行的内容。创建自己的网络将花费太多时间和太多money 
4,Keep it simple!简单允许你更快的重新架构来回应问题 
5,Shard。Sharding帮助隔离存储,CPU,内存和IO,不仅仅是获得更多的写性能 
6,Constant iteration on bottlenecks: 
-软件:DB,缓存 
-OS:硬盘I/O 
-硬件:内存,RAID 
7,You succeed as a team。拥有一个跨越条律的了解整个系统并知道系统内部是什么样的团队,如安装打印机,安装机器,安装网络等等的人。With a good team all things are possible。

http://hideto.javaeye.com/blog/130815 

Google架构学习 

关键字: Google 

原文:Google Architecture 

Google是伸缩性的王者。Google一直的目标就是构建高性能高伸缩性的基础组织来支持它们的产品。 

平台 
Linux 
大量语言:Python,Java,C++ 

状态 
在2006年大约有450,000台廉价服务器 
在2005年Google索引了80亿Web页面,现在没有人知道数目 
目前在Google有超过200个GFS集群。一个集群可以有1000或者甚至5000台机器。成千上万的机器从运行着5000000000000000字节存储的GFS集群获取数据,集群总的读写吞吐量可以达到每秒40兆字节
目前在Google有6000个MapReduce程序,而且每个月都写成百个新程序 
BigTable伸缩存储几十亿的URL,几百千千兆的卫星图片和几亿用户的参数选择 

堆栈 
Google形象化它们的基础组织为三层架构: 
1,产品:搜索,广告,email,地图,视频,聊天,博客 
2,分布式系统基础组织:GFS,MapReduce和BigTable 
3,计算平台:一群不同的数据中心里的机器 
4,确保公司里的人们部署起来开销很小 
5,花费更多的钱在避免丢失日志数据的硬件上,其他类型的数据则花费较少 

可信赖的存储机制GFS(Google File System) 
1,可信赖的伸缩性存储是任何程序的核心需求。GFS就是Google的核心存储平台 
2,Google File System - 大型分布式结构化日志文件系统,Google在里面扔了大量的数据 
3,为什么构建GFS而不是利用已有的东西?因为可以自己控制一切并且这个平台与别的不一样,Google需要: 
-跨数据中心的高可靠性 
-成千上万的网络节点的伸缩性 
-大读写带宽的需求 
-支持大块的数据,可能为上千兆字节 
-高效的跨节点操作分发来减少瓶颈 
4,系统有Master和Chunk服务器 
-Master服务器在不同的数据文件里保持元数据。数据以64MB为单位存储在文件系统中。客户端与Master服务器交流来在文件上做元数据操作并且找到包含用户需要数据的那些Chunk服务器
-Chunk服务器在硬盘上存储实际数据。每个Chunk服务器跨越3个不同的Chunk服务器备份以创建冗余来避免服务器崩溃。一旦被Master服务器指明,客户端程序就会直接从Chunk服务器读取文件
6,一个上线的新程序可以使用已有的GFS集群或者可以制作自己的GFS集群 
7,关键点在于有足够的基础组织来让人们对自己的程序有所选择,GFS可以调整来适应个别程序的需求 

使用MapReduce来处理数据 
1,现在你已经有了一个很好的存储系统,你该怎样处理如此多的数据呢?比如你有许多TB的数据存储在1000台机器上。数据库不能伸缩或者伸缩到这种级别花费极大,这就是 MapReduce出现的原因
2, MapReduce是一个处理和生成大量数据集的编程模型和相关实现。用户指定一个 map方法来处理一个键/值对来生成一个中间的键/值对,还有一个reduce方法来合并所有关联到同样的中间键的中间值。许多真实世界的任务都可以使用这种模型来表现。以这种风格来写的程序会自动并行的在一个大量机器的集群里运行。运行时系统照顾输入数据划分、程序在机器集之间执行的调度、机器失败处理和必需的内部机器交流等细节。这允许程序员没有多少并行和分布式系统的经验就可以很容易使用一个大型分布式系统资源
3,为什么使用 MapReduce? 
-跨越大量机器分割任务的好方式 
-处理机器失败 
-可以与不同类型的程序工作,例如搜索和广告。几乎任何程序都有 map和reduce类型的操作。你可以预先计算有用的数据、查询字数统计、对TB的数据排序等等
4, MapReduce系统有三种不同类型的服务器 
-Master服务器分配用户任务到 Map和Reduce服务器。它也跟踪任务的状态
- Map服务器接收用户输入并在其基础上处理 map操作。结果写入中间文件
-Reduce服务器接收 Map服务器产生的中间文件并在其基础上处理reduce操作
5,例如,你想在所有Web页面里的字数。你将存储在GFS里的所有页面抛入 MapReduce。这将在成千上万台机器上同时进行并且所有的调整、工作调度、失败处理和数据传输将自动完成
-步骤类似于:GFS ->  Map -> Shuffle -> Reduction -> Store Results back into GFS
-在 MapReduce里一个 map操作将一些数据映射到另一个中,产生一个键值对,在我们的例子里就是字和字数
-Shuffling操作聚集键类型 
-Reduction操作计算所有键值对的综合并产生最终的结果 
6,Google索引操作管道有大约20个不同的 map和reduction。
7,程序可以非常小,如20到50行代码 
8,一个问题是掉队者。掉队者是一个比其他程序慢的计算,它阻塞了其他程序。掉队者可能因为缓慢的IO或者临时的CPU不能使用而发生。解决方案是运行多个同样的计算并且当一个完成后杀死所有其他的
9,数据在 Map和Reduce服务器之间传输时被压缩了。这可以节省带宽和I/O。

在BigTable里存储结构化数据 
1,BigTable是一个大伸缩性、错误容忍、自管理的系统,它包含千千兆的内存和1000000000000000的存储。它可以每秒钟处理百万的读写 
2,BigTable是一个构建于GFS之上的分布式哈希机制。它不是关系型数据库。它不支持join或者SQL类型查询 
3,它提供查询机制来通过键访问结构化数据。GFS存储存储不透明的数据而许多程序需求有结构化数据 
4,商业数据库不能达到这种级别的伸缩性并且不能在成千上万台机器上工作 
5,通过控制它们自己的低级存储系统Google得到更多的控制权来改进它们的系统。例如,如果它们想让跨数据中心的操作更简单这个特性,它们可以内建它 
6,系统运行时机器可以自由的增删而整个系统保持工作 
7,每个数据条目存储在一个格子里,它可以通过一个行key和列key或者时间戳来访问 
8,每一行存储在一个或多个tablet中。一个tablet是一个64KB块的数据序列并且格式为SSTable 
9,BigTable有三种类型的服务器: 
-Master服务器分配tablet服务器,它跟踪tablet在哪里并且如果需要则重新分配任务 
-Tablet服务器为tablet处理读写请求。当tablet超过大小限制(通常是100MB-200MB)时它们拆开tablet。当一个Tablet服务器失败时,则100个Tablet服务器各自挑选一个新的tablet然后系统恢复。
-Lock服务器形成一个分布式锁服务。像打开一个tablet来写、Master调整和访问控制检查等都需要互斥 
10,一个locality组可以用来在物理上将相关的数据存储在一起来得到更好的locality选择 
11,tablet尽可能的缓存在RAM里 

硬件 
1,当你有很多机器时你怎样组织它们来使得使用和花费有效? 
2,使用非常廉价的硬件 
3,A 1,000-fold computer power increase can be had for a 33 times lower cost if you you use a failure-prone infrastructure rather than an infrastructure built on highly reliable components. You must build reliability on top of unreliability for this strategy to work. 
4,Linux,in-house rack design,PC主板,低端存储 
5,Price per wattage on performance basis isn't getting better. Have huge power and cooling issues
6,使用一些collocation和Google自己的数据中心 

其他 
1,迅速更改而不是等待QA 
2,库是构建程序的卓越方式 
3,一些程序作为服务提供 
4,一个基础组织处理程序的版本,这样它们可以发布而不用害怕会破坏什么东西 

Google将来的方向 
1,支持地理位置分布的集群 
2,为所有数据创建一个单独的全局名字空间。当前的数据由集群分离 
3,更多和更好的自动化数据迁移和计算 
4,解决当使用网络划分来做广阔区域的备份时的一致性问题(例如保持服务即使一个集群离线维护或由于一些损耗问题) 

学到的东西 
1,基础组织是有竞争性的优势。特别是对Google而言。Google可以很快很廉价的推出新服务,并且伸缩性其他人很难达到。许多公司采取完全不同的方式。许多公司认为基础组织开销太大。Google认为自己是一个系统工程公司,这是一个新的看待软件构建的方式
2,跨越多个数据中心仍然是一个未解决的问题。大部分网站都是一个或者最多两个数据中心。我们不得不承认怎样在一些数据中心之间完整的分布网站是很需要技巧的 
3,如果你自己没有时间从零开始重新构建所有这些基础组织你可以看看Hadoop。Hadoop是这里很多同样的主意的一个开源实现 
4,平台的一个优点是初级开发人员可以在平台的基础上快速并且放心的创建健全的程序。如果每个项目都需要发明同样的分布式基础组织的轮子,那么你将陷入困境因为知道怎样完成这项工作的人相对较少
5,协同工作不一直是掷骰子。通过让系统中的所有部分一起工作则一个部分的改进将帮助所有的部分。改进文件系统则每个人从中受益而且是透明的。如果每个项目使用不同的文件系统则在整个堆栈中享受不到持续增加的改进
6,构建自管理系统让你没必要让系统关机。这允许你更容易在服务器之间平衡资源、动态添加更大的容量、让机器离线和优雅的处理升级 
7,创建可进化的基础组织,并行的执行消耗时间的操作并采取较好的方案 
8,不要忽略学院。学院有许多没有转变为产品的好主意。Most of what Google has done has prior art, just not prior large scale deployment.
9,考虑压缩。当你有许多CPU而IO有限时压缩是一个好的选择。 



http://blog.daviesliu.net/2006/09/09/010620/ 

Lighttpd+Squid+Apache搭建高效率Web服务器 

架构原理 

Apache通常是开源界的首选Web服务器,因为它的强大和可靠,已经具有了品牌效应,可以适用于绝大部分的应用场合。但是它的强大有时候却显得笨重,配置文件得让人望而生畏,高并发情况下效率不太高。而轻量级的Web服务器Lighttpd却是后起之秀,其静态文件的响应能力远高于 Apache,据说是Apache的2-3倍。Lighttpd的高性能和易用性,足以打动我们,在它能够胜任的领域,尽量用它。Lighttpd对 PHP的支持也很好,还可以通过Fastcgi方式支持其他的语言,比如Python。

毕竟Lighttpd是轻量级的服务器,功能上不能跟Apache比,某些应用无法胜任。比如Lighttpd还不支持缓存,而现在的绝大部分站点都是用程序生成动态内容,没有缓存的话即使程序的效率再高也很难满足大访问量的需求,而且让程序不停的去做同一件事情也实在没有意义。首先,Web程序是需要做缓存处理的,即把反复使用的数据做缓存。即使这样也还不够,单单是启动Web处理程序的代价就不少,缓存最后生成的静态页面是必不可少的。而做这个是 Squid的强项,它本是做代理的,支持高效的缓存,可以用来给站点做反向代理加速。把Squid放在Apache或者Lighttpd的前端来缓存 Web服务器生成的动态内容,而Web应用程序只需要适当地设置页面实效时间即可。 

即使是大部分内容动态生成的网站,仍免不了会有一些静态元素,比如图片、JS脚本、CSS等等,将Squid放在Apache或者Lighttp 前端后,反而会使性能下降,毕竟处理HTTP请求是Web服务器的强项。而且已经存在于文件系统中的静态内容再在Squid中缓存一下,浪费内存和硬盘空间。因此可以考虑将Lighttpd再放在Squid的前面,构成 Lighttpd+Squid+Apache的一条处理链,Lighttpd在最前面,专门用来处理静态内容的请求,把动态内容请求通过proxy模块转发给Squid,如果Squid中有该请求的内容且没有过期,则直接返回给Lighttpd。新请求或者过期的页面请求交由Apache中Web程序来处理。经过Lighttpd和Squid的两级过滤,Apache需要处理的请求将大大减少,减少了Web应用程序的压力。同时这样的构架,便于把不同的处理分散到多台计算机上进行,由Lighttpd在前面统一把关。

在这种架构下,每一级都是可以进行单独优化的,比如Lighttpd可以采用异步IO方式,Squid可以启用内存来缓存,Apache可以启用MPM 等,并且每一级都可以使用多台机器来均衡负载,伸缩性很好。
2009  -  10  -  31

Java基础学习笔记

文章分类:Java编程
1.Java语言的特点:面向对象,跨平台,多线程 

2.Java运行环境:JVM+Java API 

3.数据类型: 
boolean 1 
char 16 
byte 8 
short 16 
int 32 
long 64 
float 32 
double 64 

4.面向对象: 
封装:类  
继承:单一继承  
多态:重写(Overridding)与重载(Overloading) 
在子类中,方法的参数个数和返回值都与父类相同,称为重写 
在同一个类中,方法的参数不同,称为重载 

5.作用域: 
private 子类不能继承 
default 如果不在同一包中,子类不能继承 
protected 
public 
        
6.垃圾回收原理:有向图原则(另一种为计数器类型),可能会有内存泄漏,计数器类型与有向图类型相比:效率更高,但是精度偏低,因为它很难发现变量循环引用的问题 
会有内存泄漏的代码: 
Vector v=new Vector(10) 
for (int i=0;i<10;i++){ 
Object o=new Object(); 
v.add(o); 
o=null; 

解决方法: 
v=null; 

7.栈与堆:原始数据类型存放在栈里,对象数据类型存放在堆中,栈中存放堆中的地址。 

8.变量比较:==比较的是栈,原始数据类型相同,但是引用类型值不等,equals比较的是堆,特例是string,java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。

9.变量复制:原始数据类型复制的是值,引用数据类型复制的是栈中的引用,所以当一个修改的时候,会影响另一个。对象复制:Object.clone()方法 

10.引用传递和值传递:原始数据类型传递的是值,引用数据类型传递的是栈中的引用 

11.异常:(Java.lang.Exception)检查时异常,(Java.lang.RuntimeException)运行时异常,((java.lang.Error)错误,检查时异常必须处理

12.集合:collection: set:HashSet TreeSet 
list:ArrayList LinkedList Vector Stack 
map:Hash Map Tree Map HashTable Properties

13.Set里的元素是不能重复的,什么方法来区分重复与否呢? 是用==还是 
equals()? 它们有何区别? 
Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两 
个Set是否相等。 
equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个 
分离的对象的内容和类型相配的话,返回真值 

14.ArrayList, Vector, LinkedList的存储性能和特性 
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据 
以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元 
素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方 
法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序 
号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即 
可,所以插入速度较快。 

15、Hash Map和Hashtable的区别。 
Hash Map是Hashtable的轻量级实现(非线程安全的实现),他们都完成了 Map接口,
主要区别在于Hash Map允许空(null)键值(key),由于非线程安全,效率上可能高于
Hashtable。 
Hash Map允许将null作为一个entry的key或者value,而Hashtable不允许。
Hash Map把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为
contains方法容易让人引起误解。 
Hashtable继承自Dictionary类,而Hash Map是Java1.2引进的 Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而Hash Map不是,在多个线程访问
Hashtable时,不需要自己为它的方法实现同步,而Hash Map 就必须为之提供外同步。
Hashtable和Hash Map采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
定时执行任务的三种方法: 

1)java.util.Timer. 

2)ServletContextListener. 

3)org.springframework.scheduling.timer.ScheduledTimerTask 

1)java.util.Timer 
这个方法应该是最常用的,不过这个方法需要手工启动你的任务: 
Timer timer=new Timer(); 
timer.schedule(new ListByDayTimerTask(),10000,86400000); 
这里的ListByDayTimerTask类必须extends TimerTask里面的run()方法。 

2)ServletContextListener 
这个方法在web容器环境比较方便,这样,在web server启动后就可以自动运行该任务,不需要手工操作。 
将ListByDayListener implements ServletContextListener接口,在contextInitialized方法中加入启动Timer的代码,在 contextDestroyed方法中加入cancel该Timer的代码;然后在web.xml中,加入listener:
<-listener> 
<-listener-class>com.qq.customer.ListByDayListener</listener-class> 
<-/listener> 

3)org.springframework.scheduling.timer.ScheduledTimerTask如果你用spring,那么你不需要写Timer类了,在schedulingContext-timer.xml中加入下面的内容就可以了:
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans> 
<bean id="timer" class="org.springframework.scheduling.timer.TimerFactoryBean"> 
<property name="scheduledTimerTasks"> 
<list> 
<ref local="MyTimeTask1"/> 
</list> 
</property> 
</bean> 

<bean id="MyTimeTask" class="com.qq.timer.ListByDayTimerTask"/> 

<bean id="MyTimeTask1" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask"> 
<ref bean="MyTimeTask"/> 
</property> 
<property name="delay"> 
<value>10000</value> 
</property> 
<property name="period"> 
<value>86400000</value> 
</property> 
</bean> 
</beans> 

以上内容转载自:http://dev.csdn.net/author/xtpdcsse/ec8e8080a5b04fa79e7d4828bc807d3f.html

下面是我的实现。 

1)利用java.util.Timer. 代码如下 

<1>StartThread.java 

[java]  view plain copy
  1. package com.jview.main;<BR>
  2. import java.util.Date;<BR>
  3. import java.util.Timer;<BR>
  4. import java.util.TimerTask;<BR>
  5. import org.apache.log4j.Logger;<BR>
  6. public class StartThreadextends Thread {<BR>
  7. private static Logger logger = Logger.getLogger("StartThread");<BR>
  8. public static final int EXECUTE_CYC = 86400000//24*60*60*1000毫秒<BR>
  9. int startH = 9;<BR>
  10. int startM = 52;<BR>
  11. private Timer _timer ;<BR>
  12. private Date _statDate;<BR>
  13. private Date _nowDate;<BR>
  14. public StartThread(){<BR>
  15. _nowDate = new Date();<BR>
  16. _timer = new Timer();<BR>
  17. _statDate = new Date(_nowDate.getYear(),_nowDate.getMonth(),_nowDate.getDate(),startH,startM);<BR>
  18. }<BR>
  19. public void StartUp(){<BR>
  20. _timer.schedule(<BR>
  21. new TimerTask() {<BR>
  22. public void run()<BR>
  23. {<BR>
  24. logger.info("开始统计...");<BR>
  25. try {<BR>
  26. Class.forName("com.jview.stat.StatPlan").newInstance();<BR>
  27. catch (InstantiationException e) {<BR>
  28. // TODO Auto-generated catch block<BR>
  29. e.printStackTrace();<BR>
  30. catch (IllegalAccessException e) {<BR>
  31. // TODO Auto-generated catch block<BR>
  32. e.printStackTrace();<BR>
  33. catch (ClassNotFoundException e) {<BR>
  34. // TODO Auto-generated catch block<BR>
  35. e.printStackTrace();<BR>
  36. }<BR>
  37. }<BR>
  38. },_statDate,EXECUTE_CYC);<BR>
  39. }<BR>
  40. public static void main(String[] args) {<BR>
  41. StartThread _statUp = new StartThread();<BR>
  42. _statUp.StartUp();<BR>
  43. } <BR>
  44. }
[java]  view plain  copy
  1. package com.jview.main;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import java.util.Timer;  
  6.   
  7. import java.util.TimerTask;  
  8.   
  9. import org.apache.log4j.Logger;  
  10.   
  11. public class StartThread extends Thread {  
  12.   
  13.     private static Logger logger = Logger.getLogger("StartThread");  
  14.   
  15.     public static final int EXECUTE_CYC = 86400000//24*60*60*1000毫秒  
  16.   
  17.     int startH = 9;  
  18.   
  19.     int startM = 52;  
  20.   
  21.     private Timer _timer ;  
  22.   
  23.     private Date _statDate;  
  24.   
  25.     private Date _nowDate;  
  26.   
  27.     public StartThread(){  
  28.   
  29.         _nowDate = new Date();  
  30.   
  31.         _timer = new Timer();  
  32.   
  33.         _statDate = new Date(_nowDate.getYear(),_nowDate.getMonth(),_nowDate.getDate(),startH,startM);  
  34.   
  35.     }  
  36.   
  37.     public void StartUp(){  
  38.   
  39.         _timer.schedule(  
  40.   
  41.                 new TimerTask() {  
  42.   
  43.                     public void run()  
  44.   
  45.                     {  
  46.   
  47.                         logger.info("开始统计...");  
  48.   
  49.                         try {  
  50.   
  51.                             Class.forName("com.jview.stat.StatPlan").newInstance();  
  52.   
  53.                         } catch (InstantiationException e) {  
  54.   
  55.                             // TODO Auto-generated catch block  
  56.   
  57.                             e.printStackTrace();  
  58.   
  59.                         } catch (IllegalAccessException e) {  
  60.   
  61.                             // TODO Auto-generated catch block  
  62.   
  63.                             e.printStackTrace();  
  64.   
  65.                         } catch (ClassNotFoundException e) {  
  66.   
  67.                             // TODO Auto-generated catch block  
  68.   
  69.                             e.printStackTrace();  
  70.   
  71.                         }  
  72.   
  73.                     }  
  74.   
  75.                 },_statDate,EXECUTE_CYC);  
  76.   
  77.     }  
  78.   
  79.     public static void main(String[] args) {  
  80.   
  81.         StartThread _statUp = new StartThread();  
  82.   
  83.         _statUp.StartUp();  
  84.   
  85.     }     
  86.   
  87. }  

<2>StatPlan.java 
[java]  view plain copy
  1. package com.jview.stat;<BR>
  2. import java.util.Calendar;<BR>
  3. import org.apache.log4j.Logger;<BR>
  4. public class StatPlan {<BR>
  5. <BR>
  6. <BR>
  7. private static Logger logger = Logger.getLogger("StatPlan");<BR>
  8. private int i = 0;<BR>
  9. private StatPlanService _sps ;<BR>
  10. public StatPlan(){<BR>
  11. _sps = new StatWeekPlan();<BR>
  12. statPlan();<BR>
  13. }<BR>
  14. <BR>
  15. public void statPlan(){<BR>
  16. Calendar _c = Calendar.getInstance();<BR>
  17. logger.info("stat plan ... 执行"+ i +"次,时间:"+_c.getTime());<BR>
  18. _sps.StatPlan();<BR>
  19. i++;<BR>
  20. for(int i = 0; i<9999;i++){<BR>
  21. if(i==0 || i==9998){<BR>
  22. logger.info(""+i);<BR>
  23. }<BR>
  24. }<BR>
  25. }<BR>
  26. }
[java]  view plain  copy
  1. package com.jview.stat;  
  2.   
  3. import java.util.Calendar;  
  4.   
  5. import org.apache.log4j.Logger;  
  6.   
  7. public class StatPlan {  
  8.   
  9.    
  10.   
  11.   
  12.   
  13.     private static Logger logger = Logger.getLogger("StatPlan");  
  14.   
  15.     private int i = 0;  
  16.   
  17.     private StatPlanService _sps ;  
  18.   
  19.     public StatPlan(){  
  20.   
  21.         _sps = new StatWeekPlan();  
  22.   
  23.         statPlan();  
  24.   
  25.     }  
  26.   
  27.       
  28.   
  29.     public void statPlan(){  
  30.   
  31.         Calendar _c = Calendar.getInstance();  
  32.   
  33.         logger.info("stat plan ... 执行"+ i +"次,时间:"+_c.getTime());  
  34.   
  35.         _sps.StatPlan();  
  36.   
  37.         i++;  
  38.   
  39.         for(int i = 0; i<9999;i++){  
  40.   
  41.             if(i==0 || i== 9998){  
  42.   
  43.                 logger.info(""+i);  
  44.   
  45.             }  
  46.   
  47.         }  
  48.   
  49.     }  
  50.   
  51. }  

<3>StatWeekPlan .java 
[java]  view plain copy
  1. import org.apache.log4j.Logger;<BR>
  2. <BR>
  3. public class StatWeekPlanextends StatPlanService {<BR>
  4. private static Logger logger = Logger.getLogger("StatWeekPlan");<BR>
  5. public void StatPlan(){<BR>
  6. logger.info("this is statWeekPlan");<BR>
  7. }<BR>
  8. }<BR>
  9. <4>StatPlanService .java<BR>
  10. public class StatPlanService {<BR>
  11. public void StatPlan(){ <BR>
  12. }<BR>
  13. }
[java]  view plain  copy
  1. import org.apache.log4j.Logger;  
  2.   
  3.   
  4.   
  5. public class StatWeekPlan extends StatPlanService {  
  6.   
  7.     private static Logger logger = Logger.getLogger("StatWeekPlan");  
  8.   
  9.     public void StatPlan(){  
  10.   
  11.         logger.info("this is statWeekPlan");  
  12.   
  13.     }  
  14.   
  15. }  
  16.   
  17. <4>StatPlanService .java  
  18.   
  19. public class StatPlanService {  
  20.   
  21.     public void StatPlan(){      
  22.   
  23.     }  
  24.   
  25. }  

2)ServletContextListener.实现 
<1> SysStatListener .java 
[java]  view plain copy
  1. import java.util.Date;<BR>
  2. import java.util.Timer;<BR>
  3. import java.util.TimerTask;<BR>
  4. import javax.servlet.ServletContextEvent;<BR>
  5. import javax.servlet.ServletContextListener;<BR>
  6. import org.apache.log4j.Logger;<BR>
  7. public class SysStatListenerimplements ServletContextListener{<BR>
  8. private static Logger logger = Logger.getLogger("ListByDayListener");<BR>
  9. private StatTask _sTask;<BR>
  10. public void contextDestroyed(ServletContextEvent scevent) {<BR>
  11. String status = "停止系统统计线程";<BR>
  12. scevent.getServletContext().log(status);<BR>
  13. logger.info(status);<BR>
  14. _sTask.shutDown();<BR>
  15. }<BR>
  16. public void contextInitialized(ServletContextEvent scevent) {<BR>
  17. String status = "启动系统统计线程";<BR>
  18. scevent.getServletContext().log(status);<BR>
  19. logger.info(status);<BR>
  20. _sTask = new StatTask();<BR>
  21. _sTask.startUp();<BR>
  22. }<BR>
  23. }
[java]  view plain  copy
  1. import java.util.Date;  
  2.   
  3. import java.util.Timer;  
  4.   
  5. import java.util.TimerTask;  
  6.   
  7. import javax.servlet.ServletContextEvent;  
  8.   
  9. import javax.servlet.ServletContextListener;  
  10.   
  11. import org.apache.log4j.Logger;  
  12.   
  13. public class SysStatListener implements ServletContextListener{  
  14.   
  15.     private static Logger logger = Logger.getLogger("ListByDayListener");  
  16.   
  17.     private StatTask _sTask;  
  18.   
  19.     public void contextDestroyed(ServletContextEvent scevent) {  
  20.   
  21.         String status = "停止系统统计线程";  
  22.   
  23.         scevent.getServletContext().log(status);  
  24.   
  25.         logger.info(status);  
  26.   
  27.         _sTask.shutDown();  
  28.   
  29.     }  
  30.   
  31.     public void contextInitialized(ServletContextEvent scevent) {  
  32.   
  33.         String status = "启动系统统计线程";  
  34.   
  35.         scevent.getServletContext().log(status);  
  36.   
  37.         logger.info(status);  
  38.   
  39.         _sTask = new StatTask();  
  40.   
  41.         _sTask.startUp();  
  42.   
  43.     }  
  44.   
  45. }  

<2> StatTask .java 
[java]  view plain copy
  1. import java.util.Date;<BR>
  2. import java.util.Timer;<BR>
  3. import java.util.TimerTask;<BR>
  4. import org.apache.log4j.Logger;<BR>
  5. public class StatTaskextends Thread {<BR>
  6. private static Logger logger = Logger.getLogger("StartThread");<BR>
  7. public staticfinal int EXECUTE_CYC =86400000;<BR>
  8. int startH = 9;<BR>
  9. int startM = 52;<BR>
  10. private Timer _timer ;<BR>
  11. private Date _statDate;<BR>
  12. private Date _nowDate;<BR>
  13. public StatTask(){<BR>
  14. _nowDate = new Date();<BR>
  15. _timer = new Timer();<BR>
  16. _statDate = new Date(_nowDate.getYear(),_nowDate.getMonth(),_nowDate.getDate(),startH,startM);<BR>
  17. }<BR>
  18. public void startUp(){<BR>
  19. _timer.schedule(<BR>
  20. new TimerTask() {<BR>
  21. public void run()<BR>
  22. {<BR>
  23. logger.info("开始统计...");<BR>
  24. try {<BR>
  25. Class.forName("com.jview.stat.StatPlan").newInstance();<BR>
  26. catch (InstantiationException e) {<BR>
  27. // TODO Auto-generated catch block<BR>
  28. e.printStackTrace();<BR>
  29. catch (IllegalAccessException e) {<BR>
  30. // TODO Auto-generated catch block<BR>
  31. e.printStackTrace();<BR>
  32. catch (ClassNotFoundException e) {<BR>
  33. // TODO Auto-generated catch block<BR>
  34. e.printStackTrace();<BR>
  35. }<BR>
  36. }<BR>
  37. },_statDate,EXECUTE_CYC);<BR>
  38. }<BR>
  39. public void shutDown(){<BR>
  40. _timer.cancel();<BR>
  41. }
[java]  view plain  copy
  1. import java.util.Date;  
  2.   
  3. import java.util.Timer;  
  4.   
  5. import java.util.TimerTask;  
  6.   
  7. import org.apache.log4j.Logger;  
  8.   
  9. public class StatTask extends Thread {  
  10.   
  11.     private static Logger logger = Logger.getLogger("StartThread");  
  12.   
  13.     public static final int EXECUTE_CYC = 86400000;  
  14.   
  15.     int startH = 9;  
  16.   
  17.     int startM = 52;  
  18.   
  19.     private Timer _timer ;  
  20.   
  21.     private Date _statDate;  
  22.   
  23.     private Date _nowDate;  
  24.   
  25.     public StatTask(){  
  26.   
  27.         _nowDate = new Date();  
  28.   
  29.         _timer = new Timer();  
  30.   
  31.         _statDate = new Date(_nowDate.getYear(),_nowDate.getMonth(),_nowDate.getDate(),startH,startM);  
  32.   
  33.     }  
  34.   
  35.     public void startUp(){  
  36.   
  37.         _timer.schedule(  
  38.   
  39.                 new TimerTask() {  
  40.   
  41.                     public void run()  
  42.   
  43.                     {  
  44.   
  45.                         logger.info("开始统计...");  
  46.   
  47.                           try {  
  48.   
  49.                               Class.forName("com.jview.stat.StatPlan").newInstance();  
  50.   
  51.                           } catch (InstantiationException e) {  
  52.   
  53.                               // TODO Auto-generated catch block  
  54.   
  55.                               e.printStackTrace();  
  56.   
  57.                           } catch (IllegalAccessException e) {  
  58.   
  59.                              // TODO Auto-generated catch block  
  60.   
  61.                               e.printStackTrace();  
  62.   
  63.                          } catch (ClassNotFoundException e) {  
  64.   
  65.                             // TODO Auto-generated catch block  
  66.   
  67.                              e.printStackTrace();  
  68.   
  69.                          }  
  70.   
  71.                     }  
  72.   
  73.                 },_statDate,EXECUTE_CYC);  
  74.   
  75.     }  
  76.   
  77.     public void shutDown(){  
  78.   
  79.         _timer.cancel();  
  80.   
  81.     }  

<3>在web.xml中添加下面的内容(注:下面的内容放到<filter- mapping>的后面)
<listener> 
<listener-class>com.jview.auto.stat.SysStatListener </listener-class> 
</listener> 

这篇文章是由José M. Aguilar在他卓越的博客中以西班牙语的形式首发,其后Timm Martin在获得Aguilar先生的授权下,对该文章进行翻译、修改,并且在DevTopics上发布。

以下13个小技巧可以使得你的代码在长时间内依然能够保持容易理解和维护。 

1. 对不同级别的代码进行注释 

对于不同级别的代码块,要使用统一的方法来进行注释。例如: 

对于每一个类,需要包含一段简明扼要的描述,作者和上一次修改的时间 
对于每一个方法,需要包含这个方法的用途,功能,参数以及返回结果 
当你在一个团队里面的时候,采用一套注释的标准是非常重要的。当然,使用一种大家都认可的注释约定和工具(例如C#的XML注释和Java的Javadoc)在一定程度上能推动这项任务。

2. 使用段落注释 

首先把代码块分解成多个“段落”,每一个段落都执行单一的任务;然后在每一个“段落”开始之前添加注释,告诉阅读代码的人接下来的这段代码是干什么用的 

// 检查所有记录都是正确的 
foreach (Record record in records) 

if (rec.checkStatus()==Status.OK) 

. . . 


// 现在开始进行处理 
Context ctx = new ApplicationContext(); 
ctx.BeginTransaction(); 
. . . 
3. 对齐注释行 

对于那些在行末写有注释的代码,应该对齐注释行来使得方便阅读 

const MAX_ITEMS = 10; // maximum number of packets 
const MASK = 0x1F; // mask bit TCP 

有些开发人员使用tab来对齐注释,而另外一些人会用空格来对齐。由于tab在不同的编辑器和集成开发环境中会有所不同,所以最佳的方法是使用空格来对齐注释行。 

4. 不要侮辱阅读者的智慧 

要避免没用的注释,例如 

if (a == 5) //如果a等于5 
counter = 0 //把counte设为0 

这不单把时间浪费在写没用的注释上面,同时也在分散读者的注意力。 

5. 要有礼貌 

应当避免没有礼貌的注释,例如“要注意一些愚蠢的用户会输入一个负数”,或者“修正由菜鸟工程师写的愚蠢得可怜的代码而导致的副作用”。这样的注释对于代码的写注释的人来说并没有任何好处,同时你永远都不会知道将来这些注释会被谁来阅读,你的老板,一个客户或者是刚才被你数落的愚蠢得可怜的工程师。

6. 直截了当 

不要在注释里面写过多的废话。避免在注释里面卖弄ASCII艺术,写笑话,作诗和过于冗长。简而言之就是保持注释的简单和直接。 

7. 使用统一的风格 

有些人觉得注释应该让非程序员也能看懂。另外一些人觉得注释需要面对的读者只是程序员。无论如何,正如Successful Strategies for Commenting Code中所说的,最重要的是注释的风格需要统一,并且总是面向相同的读者。就自己而论,我怀疑非程序员是否会去读代码,所以我觉得注释应该面向程序员来写。

8. 在内部使用特殊的标签 

当你在一个团队里工作的时候,采用一组一致的标签能帮助不同的程序员沟通。例如,很多团队会采用“TODO”标签来表示一段尚未完成的代码 

int Estimate(int x, int y) 

// TODO: implement the calculations 
return 0; 


标签注释并不会解释代码,它们寻求注意或者是传递信息。但是如果适当地使用这种技术,要记住跟进这段代码并且完成该标签传递的任务。 

9. 在写代码的同时添加注释 

当你在写代码而且记忆犹新的同时就添加注释。如果等到项目后期才添加注释,会让你事倍功半。“我没有时间写注释”,“我的时间很紧迫”和“项目已经延迟了”,这些都是不写注释的常见借口。有些工程师觉最佳的解决方法是“注释先行”。例如:

public void ProcessOrder() 

// Make sure the products are available 
// Check that the customer is valid 
// Send the order to the store 
// Generate bill 


10. 把自己想象为注释的读者(事实上就是如此) 

当你正在给代码写注释的时候,不仅仅为日后维护你的代码的开发者考虑,同时也设想一下如果自己就是注释的读者。Phil Haack曾经说过: 

“一旦一行代码被敲到文件中, 你就已经要开始维护那一行代码了。” 

所以,我们自己就是好(或者坏)注释的第一个受益者(或者受害者)。 

11. 更新代码的时候要更新注释 

如果注释没有随着代码的修改而更新,那么这些注释将是毫无意义的。代码和注释需要同步,否则注释只会让维护代码的开发者更加痛苦。需要特别注意的是,一些重构的工具会自动更新代码,但是却没有自动更新注释,那么注释就自然而然地过期作废了。

12. 良好可读性代码是注释的金科玉律 

对于很多开发者来说,一个基本的原则就是:让代码自己描述自己。虽然有人怀疑这是由不喜欢写注释的程序员所倡导的一场运动,但是无需解释的代码有很大的好处,这些代码更加容易理解甚至让注释变得没有必要。例如,在我的文章Fluid Interfaces中就给大家展示了什么是清晰的无需解释的代码。

Calculator calc = new Calculator(); 
calc.Set(0); 
calc.Add(10); 
calc.Multiply(2); 
calc.Subtract(4); 
Console.WriteLine( “Result: {0}”, calc.Get() ); 

在这个例子里面,注释就像是违反了第4条技巧那样,变得毫无必要。要写出可读性好的代码,你需要使用适当的命名方式(在经典的 Ottinger’s Rules中有阐述),保证恰当的缩进,并且采用编码风格指导。如果代码不遵守这条技巧,那么注释看起来就好像是为自己不好的代码的写道歉信一样。

13. 跟你的同事分享这些技巧 

虽然从第10条技巧中我们已经知道了自己就是好注释的得益者,但是这些技巧对于所有的开发者来说都是很有帮助的,尤其是整个团队都有相同共识的情况下。因此,大方地跟你的同事去分享这些技巧,让我们写出更加容易理解和维护的代码。
2009  -  03  -  10

log4j配置文件的含义

今天试着用了一下log4j来处理java中的日志,感觉良好,顺便记录一下log4j的配置文件log4j.properties各语句的含义。

这是一个数据库配置文件 

#这是一个配置文件实例,PropertyConfigurator将使用这个文件 : 
#声明一个appender变量名为JDBC 
log4j.rootLogger=DEBUG, JDBC 

#JDBC是一个JDBCAppender类,这个类可以写消息到数据库 
log4j.appender.JDBC=com.benqguru.palau.log.jdbc.test.JDBCAppender 

#1.连接数据库的数据库选项 
log4j.appender.JDBC.url=jdbc:mysql://localhost:3306/logtest 
log4j.appender.JDBC.username=root 
log4j.appender.JDBC.password= 

#2.指定你自己的JDBCConnectionHandler的连接器选项 
log4j.appender.JDBC.connection_class=com.benqguru.palau.log.jdbc.test.MyConnectionHandler

#3.指定一个静态的SQL语句的SQL选项,这个语句将在每次消息事件发生时被执行 
log4j.appender.JDBC.sql=INSERT INTO LOGTEST (id, msg, created_on, created_by) VALUES (1, @MSG@, sysdate, 'me')

#4. 指定数据库中一个表的表选项。 
log4j.appender.JDBC.table=logtest 

#5.描述表的重要列的列选项(非空列是必须被描述的) 
log4j.appender.JDBC.columns=id_seq~EMPTY id~ID~MyIDHandler msg~MSG created_on~TIMESTAMP created_by~STATIC~Thomas Fenner

#6.定义消息布局器的布局器选项(可选) 
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout 
log4j.appender.JDBC.layout.ConversionPattern=%m 

#7.定义消息事件缓冲器的大小的缓冲器选项(可选) 
log4j.appender.JDBC.buffer_size=1 

#8.定义自动提交的提交选项(可选) 
log4j.appender.JDBC.docommit=N 

##########下面是英文说明############# 
#Date - %d{DATE}[slf5s.DATE] 
#Priority - %p[slf5s.PRIORITY] 
#NDC - %x[slf5s.NDC] 
#Thread - %t[slf5s.THREAD] 
#Category - %c[slf5s.CATEGORY] 
#Location - %l[slf5s.LOCATION] 
#Message - %m[slf5s.MESSAGE] 

#log4j.appender.R.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n/ 
# %p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n/ 
# %c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n 
##########下面是中文说明############# 
#%m 输出代码中指定的消息 
#%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL 
#%r 输出自应用启动到输出该log信息耗费的毫秒数 
#%c 输出所属的类目,通常就是所在类的全名 
#%t 输出产生该日志事件的线程名 
#%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n” 
#%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式, 
#比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 
#%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10) 


这是一个普通的配置文件 

#log4j会解析这个文件 
log4j.debug=false 
#暂时还不清楚这两个属性的作用 
log4j.disableOverride=true 
log4j.disable=INFO 
#设置记录所有类的日志的优先级别 
log4j.rootLogger=DEBUG,dest1,dest2 
#设置这个包记录日志为假的话 
#dist1,dist2就不会记录com.benqguru.commons.logging.test.LoggingSample的日志,只有dist3会记录. 
#反之,会记录,这样就会重复记录 
log4j.additivity.com.benqguru.commons.logging.test.LoggingSample=false 
#特别指定某个特殊包的日志级别和目标设备 
log4j.category.com.benqguru.commons.logging.test.LoggingSample=WARN, dest3 
#这个目标设备用来debug 
log4j.appender.dest1=org.apache.log4j.ConsoleAppender 
#log4j.appender.dest1.layout=org.apache.log4j.SimpleLayout 
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout 
#%-4r %-5p [%t] %37c %3x - %m%n 
log4j.appender.dest1.layout.ConversionPattern=%d %p %c - <%m> (%F.%M:%L) %t%n 

#这个目标设备用来trace 
log4j.appender.dest2=org.apache.log4j.RollingFileAppender 
#该文件记录日志的级别(INFO以下的级别不记录) 
log4j.appender.dest2.Threshold=INFO 
#文件保存路径 
log4j.appender.dest2.File=c:/log4jlog.htm 
#是否往文件追加信息 
log4j.appender.dest2.Append=true 
#设置文件最大值 
log4j.appender.dest2.MaxFileSize=5KB 
#设置备份文件的最大数量 
log4j.appender.dest2.MaxBackupIndex=10 
#使用一个html格式来记录日志 
log4j.appender.dest2.layout=org.apache.log4j.HTMLLayout 
#是否打印该消息的代码行 
log4j.appender.dest2.layout.LocationInfo=true 
#设置该日志的html的标题 
log4j.appender.dest2.layout.Title=My app title 

#这个目标设备用来trace指定类或包 
log4j.appender.dest3=org.apache.log4j.DailyRollingFileAppender 
#log4j.appender.dest3.Threshold=DEBUG 
log4j.appender.dest3.File=c:/SpecPackageLog.htm 
log4j.appender.dest3.Append=false 
log4j.appender.dest3.layout=org.apache.log4j.HTMLLayout 
log4j.appender.dest3.layout.LocationInfo=true 
log4j.appender.dest3.layout.Title=My app title 

在Sun的API中对在对 “最大匹配Greedy”“最小匹配Reluctant”“完全匹配Possessive”的描述,不能让我明白他们有什么区别,现在将我对这三种匹配模式的理解写出来,供大家参考。


1、Greediness(贪心)匹配: 

X?、X*、X+、X{n,}都是最大匹配。例如你要用“<.+>”去匹配“a<tr>aava </tr>abb”,也许你所期待的结果是想匹配“<tr>”,但是实际结果却会匹配到“<tr>aava </tr>”。这是为什么呢?下面我们跟踪下最大匹配的匹配过程。

①“<”匹配字符串的“<”。②“.+”匹配字符串的“tr>aava </tr>ab”,在进行最大匹配时,它把两个“>”都匹配了,它匹配了所有字符,直到文本的最后字符“b” ③这时,发现不能成功匹配“>”,开始按原路回退,用“a”与“>”匹配,直到“ab”前面的“>”匹配成功。


2、Reluctant(Laziness)最小匹配 

X?、X*、X+、X{n,}都是最大匹配。好,加个?就成了Laziness匹配。例如X??、X*?、X+?、X{n,}?都是最小匹配,其实X{n,m}?和X{n }?有些多余。

最小匹配意味者,.+? 匹配一个字符后,马上试一试>的匹配可能,失败了,则.+? 再匹配一个字符,再马上试一试>的匹配可能。JDK文档中Greedy 和 Reluctant,它是以eat一口来隐喻的,所以翻译成贪吃和(勉强的)厌食最贴切了。不过我喜欢最大匹配、最小匹配的说法。


3、Possessive完全匹配 

与最大匹配不同,还有一种匹配形式:X?+、X*+、X++、X{n,}+等,成为完全匹配。它和最大匹配一样,一直匹配所有的字符,直到文本的最后,但它不由原路返回。也就是说,一口匹配,搞不定就算了,到也干脆,偶喜欢。

Use a possessive quantifier for situations where you want to seize all of something without ever backing off; it will outperform the equivalent greedy quantifier in cases where the match is not immediately found.

[java]  view plain copy
  1. import java.util.regex.Matcher;<BR>
  2. import java.util.regex.Pattern;<BR>
  3. <BR>
  4. public class RegularExpression {<BR>
  5. <BR>
  6. public static void main(String[] args) {<BR>
  7. // 简单认识正则表达式的概念<BR>
  8. <BR>
  9. // p("abc".matches("..."));<BR>
  10. // p("a8729a".replaceAll("//d", "-"));<BR>
  11. // Pattern p = Pattern.compile("[a-z]{3}");<BR>
  12. // Matcher m = p.matcher("fgh");<BR>
  13. // p(m.matches());<BR>
  14. // p("aaas".matches("[a-z]{3,}"));<BR>
  15. <BR>
  16. // 初步认识. * + ?<BR>
  17. <BR>
  18. // p("a".matches("."));<BR>
  19. // p("aa".matches("aa"));<BR>
  20. // p("aaaa".matches("a*"));<BR>
  21. // p("aaaa".matches("a+"));<BR>
  22. // p("".matches("a*"));<BR>
  23. // p("aaaa".matches("a?"));<BR>
  24. // p("".matches("a?"));<BR>
  25. // p("a".matches("a?"));<BR>
  26. // p("214523145234532".matches("//d{3,100}"));<BR>
  27. // p("192.168.0.231".matches("//d{1,3}//.//d{1,3}//.//d{1,3}//.//d{1,3}"));<BR>
  28. // p("192".matches("[0-2][0-9][0-9]"));<BR>
  29. <BR>
  30. // 范围<BR>
  31. <BR>
  32. // p("a".matches("[abc]"));<BR>
  33. // p("a".matches("[^abc]"));<BR>
  34. // p("A".matches("[a-zA-Z]"));<BR>
  35. // p("a".matches("[a-z]|[A-Z]"));<BR>
  36. // p("A".matches("[a-z[A-Z]]"));<BR>
  37. // p("R".matches("[A-Z&&[RFG]]"));<BR>
  38. <BR>
  39. // 认识/s /w /d /<BR>
  40. <BR>
  41. // p(" /n/r/t".matches("//s{4}"));<BR>
  42. // p(" ".matches("//S"));<BR>
  43. // p("a_8".matches("//w{3}"));<BR>
  44. // p("abc888&^%".matches("[a-z]{1,3}//d+[&^#%]+"));<BR>
  45. // p("//".matches(""));<BR>
  46. <BR>
  47. // POSIX Style<BR>
  48. <BR>
  49. // p("a".matches("//p{Lower}"));<BR>
  50. <BR>
  51. // boundary<BR>
  52. <BR>
  53. // p("hello sir".matches("^h.*"));<BR>
  54. // p("hello sir".matches(".*ir$"));<BR>
  55. // p("hello sir".matches("^h[a-z]{1,3}o//b.*"));<BR>
  56. // p("hellosir".matches("^h[a-z]{1,3}o//b.*")); // whilte lines<BR>
  57. // p("/n".matches("^[//s&&[^//n<BR>
  58. // p("aaa 8888c".matches(".*//d{4}."));<BR>
  59. // p("aaa8888c".matches(".*//b//d{4}."));<BR>
  60. // p("aaa8888c".matches(".*//d{4}."));<BR>
  61. // p("aaa 8888c".matches(".*//b//d{4}."));<BR>
  62. <BR>
  63. // email<BR>
  64. <BR>
  65. // p("asdfasdfsafsf@dsdfsdf.com".matches("[//w[.-]]+@[//w[.-]]+//.[//w]+"));<BR>
  66. <BR>
  67. // matches find lookingAt<BR>
  68. <BR>
  69. // Pattern p = Pattern.compile("//d{3,5}");<BR>
  70. // String s = "123-34345-234-00";<BR>
  71. // Matcher m = p.matcher(s);<BR>
  72. // p(m.matches());<BR>
  73. // m.reset();<BR>
  74. // p(m.find());<BR>
  75. // p(m.start() + "-" + m.end());<BR>
  76. // p(m.find());<BR>
  77. // p(m.start() + "-" + m.end());<BR>
  78. // p(m.find());<BR>
  79. // p(m.start() + "-" + m.end());<BR>
  80. // p(m.find());<BR>
  81. // //p(m.start() + "-" + m.end());<BR>
  82. // p(m.lookingAt());<BR>
  83. // p(m.lookingAt());<BR>
  84. // p(m.lookingAt());<BR>
  85. // p(m.lookingAt());<BR>
  86. <BR>
  87. // replacement<BR>
  88. <BR>
  89. // Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);<BR>
  90. // Matcher m = p<BR>
  91. // .matcher("java Java JAVa JaVa IloveJAVA you hateJava afasdfasdf");<BR>
  92. // StringBuffer buf = new StringBuffer();<BR>
  93. // int i = 0;<BR>
  94. // while (m.find()) {<BR>
  95. // i++;<BR>
  96. // if (i % 2 == 0) {<BR>
  97. // m.appendReplacement(buf, "java");<BR>
  98. // } else {<BR>
  99. // m.appendReplacement(buf, "JAVA");<BR>
  100. // }<BR>
  101. // }<BR>
  102. // m.appendTail(buf);<BR>
  103. // p(buf);<BR>
  104. <BR>
  105. // group<BR>
  106. <BR>
  107. // Pattern p = Pattern.compile("(//d{3,5})([a-z]{2})");<BR>
  108. // String s = "123aa-34345bb-234cc-00";<BR>
  109. // Matcher m = p.matcher(s);<BR>
  110. // while (m.find()) {<BR>
  111. // p(m.group());<BR>
  112. // }<BR>
  113. <BR>
  114. // qulifiers<BR>
  115. <BR>
  116. // Pattern p = Pattern.compile(".{3,10}+[0-9]");<BR>
  117. // String s = "aaaa5bbbb68";<BR>
  118. // Matcher m = p.matcher(s);<BR>
  119. // if (m.find())<BR>
  120. // p(m.start() + "-" + m.end());<BR>
  121. // else<BR>
  122. // p("not match!");<BR>
  123. <BR>
  124. // non-capturing groups<BR>
  125. <BR>
  126. // Pattern p = Pattern.compile(".{3}(?=a)");<BR>
  127. // String s = "444a66b";<BR>
  128. // Matcher m = p.matcher(s);<BR>
  129. // while (m.find()) {<BR>
  130. // p(m.group());<BR>
  131. // }<BR>
  132. <BR>
  133. // back refenrences<BR>
  134. <BR>
  135. // Pattern p = Pattern.compile("(//d(//d))//2");<BR>
  136. // String s = "122";<BR>
  137. // Matcher m = p.matcher(s);<BR>
  138. // p(m.matches());<BR>
  139. <BR>
  140. // flags的简写<BR>
  141. Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);<BR>
  142. p("Java".matches("(?i)(java)"));<BR>
  143. }<BR>
  144. <BR>
  145. public staticvoid p(Object o) {<BR>
  146. System.out.println(o);<BR>
  147. }<BR>
  148. <BR>
  149. }<BR>
[java]  view plain  copy
  1. import java.util.regex.Matcher;  
  2.   
  3. import java.util.regex.Pattern;  
  4.   
  5.   
  6.   
  7. public class RegularExpression {  
  8.   
  9.   
  10.   
  11.     public static void main(String[] args) {  
  12.   
  13.         // 简单认识正则表达式的概念  
  14.   
  15.   
  16.   
  17.         // p("abc".matches("..."));  
  18.   
  19.         // p("a8729a".replaceAll("//d", "-"));  
  20.   
  21.         // Pattern p = Pattern.compile("[a-z]{3}");  
  22.   
  23.         // Matcher m = p.matcher("fgh");  
  24.   
  25.         // p(m.matches());  
  26.   
  27.         // p("aaas".matches("[a-z]{3,}"));  
  28.   
  29.   
  30.   
  31.         // 初步认识. * + ?  
  32.   
  33.   
  34.   
  35.         // p("a".matches("."));  
  36.   
  37.         // p("aa".matches("aa"));  
  38.   
  39.         // p("aaaa".matches("a*"));  
  40.   
  41.         // p("aaaa".matches("a+"));  
  42.   
  43.         // p("".matches("a*"));  
  44.   
  45.         // p("aaaa".matches("a?"));  
  46.   
  47.         // p("".matches("a?"));  
  48.   
  49.         // p("a".matches("a?"));  
  50.   
  51.         // p("214523145234532".matches("//d{3,100}"));  
  52.   
  53.         // p("192.168.0.231".matches("//d{1,3}//.//d{1,3}//.//d{1,3}//.//d{1,3}"));  
  54.   
  55.         // p("192".matches("[0-2][0-9][0-9]"));  
  56.   
  57.   
  58.   
  59.         // 范围  
  60.   
  61.   
  62.   
  63.         // p("a".matches("[abc]"));  
  64.   
  65.         // p("a".matches("[^abc]"));  
  66.   
  67.         // p("A".matches("[a-zA-Z]"));  
  68.   
  69.         // p("a".matches("[a-z]|[A-Z]"));  
  70.   
  71.         // p("A".matches("[a-z[A-Z]]"));  
  72.   
  73.         // p("R".matches("[A-Z&&[RFG]]"));  
  74.   
  75.   
  76.   
  77.         // 认识/s /w /d /  
  78.   
  79.   
  80.   
  81.         // p(" /n/r/t".matches("//s{4}"));  
  82.   
  83.         // p(" ".matches("//S"));  
  84.   
  85.         // p("a_8".matches("//w{3}"));  
  86.   
  87.         // p("abc888&^%".matches("[a-z]{1,3}//d+[&^#%]+"));  
  88.   
  89.         // p("//".matches(""));  
  90.   
  91.   
  92.   
  93.         // POSIX Style  
  94.   
  95.   
  96.   
  97.         // p("a".matches("//p{Lower}"));  
  98.   
  99.   
  100.   
  101.         // boundary  
  102.   
  103.   
  104.   
  105.         // p("hello sir".matches("^h.*"));  
  106.   
  107.         // p("hello sir".matches(".*ir$"));  
  108.   
  109.         // p("hello sir".matches("^h[a-z]{1,3}o//b.*"));  
  110.   
  111.         // p("hellosir".matches("^h[a-z]{1,3}o//b.*")); // whilte lines  
  112.   
  113.         // p("/n".matches("^[//s&&[^//n  
  114.   
  115.         // p("aaa 8888c".matches(".*//d{4}."));  
  116.   
  117.         // p("aaa8888c".matches(".*//b//d{4}."));  
  118.   
  119.         // p("aaa8888c".matches(".*//d{4}."));  
  120.   
  121.         // p("aaa 8888c".matches(".*//b//d{4}."));  
  122.   
  123.   
  124.   
  125.         // email  
  126.   
  127.   
  128.   
  129.         // p("asdfasdfsafsf@dsdfsdf.com".matches("[//w[.-]]+@[//w[.-]]+//.[//w]+"));  
  130.   
  131.   
  132.   
  133.         // matches find lookingAt  
  134.   
  135.   
  136.   
  137.         // Pattern p = Pattern.compile("//d{3,5}");  
  138.   
  139.         // String s = "123-34345-234-00";  
  140.   
  141.         // Matcher m = p.matcher(s);  
  142.   
  143.         // p(m.matches());  
  144.   
  145.         // m.reset();  
  146.   
  147.         // p(m.find());  
  148.   
  149.         // p(m.start() + "-" + m.end());  
  150.   
  151.         // p(m.find());  
  152.   
  153.         // p(m.start() + "-" + m.end());  
  154.   
  155.         // p(m.find());  
  156.   
  157.         // p(m.start() + "-" + m.end());  
  158.   
  159.         // p(m.find());  
  160.   
  161.         // //p(m.start() + "-" + m.end());  
  162.   
  163.         // p(m.lookingAt());  
  164.   
  165.         // p(m.lookingAt());  
  166.   
  167.         // p(m.lookingAt());  
  168.   
  169.         // p(m.lookingAt());  
  170.   
  171.   
  172.   
  173.         // replacement  
  174.   
  175.   
  176.   
  177.         // Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);  
  178.   
  179.         // Matcher m = p  
  180.   
  181.         // .matcher("java Java JAVa JaVa IloveJAVA you hateJava afasdfasdf");  
  182.   
  183.         // StringBuffer buf = new StringBuffer();  
  184.   
  185.         // int i = 0;  
  186.   
  187.         // while (m.find()) {  
  188.   
  189.         // i++;  
  190.   
  191.         // if (i % 2 == 0) {  
  192.   
  193.         // m.appendReplacement(buf, "java");  
  194.   
  195.         // } else {  
  196.   
  197.         // m.appendReplacement(buf, "JAVA");  
  198.   
  199.         // }  
  200.   
  201.         // }  
  202.   
  203.         // m.appendTail(buf);  
  204.   
  205.         // p(buf);  
  206.   
  207.   
  208.   
  209.         // group  
  210.   
  211.   
  212.   
  213.         // Pattern p = Pattern.compile("(//d{3,5})([a-z]{2})");  
  214.   
  215.         // String s = "123aa-34345bb-234cc-00";  
  216.   
  217.         // Matcher m = p.matcher(s);  
  218.   
  219.         // while (m.find()) {  
  220.   
  221.         // p(m.group());  
  222.   
  223.         // }  
  224.   
  225.   
  226.   
  227.         // qulifiers  
  228.   
  229.   
  230.   
  231.         // Pattern p = Pattern.compile(".{3,10}+[0-9]");  
  232.   
  233.         // String s = "aaaa5bbbb68";  
  234.   
  235.         // Matcher m = p.matcher(s);  
  236.   
  237.         // if (m.find())  
  238.   
  239.         // p(m.start() + "-" + m.end());  
  240.   
  241.         // else  
  242.   
  243.         // p("not match!");  
  244.   
  245.   
  246.   
  247.         // non-capturing groups  
  248.   
  249.   
  250.   
  251.         // Pattern p = Pattern.compile(".{3}(?=a)");  
  252.   
  253.         // String s = "444a66b";  
  254.   
  255.         // Matcher m = p.matcher(s);  
  256.   
  257.         // while (m.find()) {  
  258.   
  259.         // p(m.group());  
  260.   
  261.         // }  
  262.   
  263.   
  264.   
  265.         // back refenrences  
  266.   
  267.   
  268.   
  269.         // Pattern p = Pattern.compile("(//d(//d))//2");  
  270.   
  271.         // String s = "122";  
  272.   
  273.         // Matcher m = p.matcher(s);  
  274.   
  275.         // p(m.matches());  
  276.   
  277.   
  278.   
  279.         // flags的简写  
  280.   
  281.         Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);  
  282.   
  283.         p("Java".matches("(?i)(java)"));  
  284.   
  285.     }  
  286.   
  287.   
  288.   
  289.     public static void p(Object o) {  
  290.   
  291.         System.out.println(o);  
  292.   
  293.     }  
  294.   
  295.   
  296.   
  297. }  
2009  -  02  -  06

Java snippets02

[java]  view plain copy
  1. if (Character.isLowerCase(ch[i])) {<BR>
  2. char temp = Character.toUpperCase(ch[i]);<BR>
  3. ch[i] = temp;<BR>
  4. else if (Character.isUpperCase(ch[i])) {<BR>
  5. char temp = Character.toLowerCase(ch[i]);<BR>
  6. ch[i] = temp;<BR>
  7. }
[java]  view plain  copy
  1. if (Character.isLowerCase(ch[i])) {  
  2.   
  3.     char temp = Character.toUpperCase(ch[i]);  
  4.   
  5.     ch[i] = temp;  
  6.   
  7. else if (Character.isUpperCase(ch[i])) {  
  8.   
  9.     char temp = Character.toLowerCase(ch[i]);  
  10.   
  11.     ch[i] = temp;  
  12.   
  13. }  

[java]  view plain copy
  1. while (true) {<BR>
  2. flag = 0;<BR>
  3. result = tc.getNum();<BR>
  4. >
  5. input = Integer.parseInt(br.readLine());<BR>
  6. >
  7. while (flag == 0) {<BR>
  8. if (input == result) {<BR>
  9. System.out.println("very good!");<BR>
  10. flag = 1;<BR>
  11. else {<BR>
  12. flag = 0;<BR>
  13. System.out.println("no,please try again.");<BR>
  14. input = Integer.parseInt(br.readLine());<BR>
  15. }<BR>
  16. }<BR>
  17. }
[java]  view plain  copy
  1. while (true) {  
  2.   
  3.     flag = 0;  
  4.   
  5.     result = tc.getNum();  
  6.   
  7.   
  8.   
  9.     input = Integer.parseInt(br.readLine());  
  10.   
  11.   
  12.   
  13.     while (flag == 0) {  
  14.   
  15.         if (input == result) {  
  16.   
  17.             System.out.println("very good!");  
  18.   
  19.             flag = 1;  
  20.   
  21.         } else {  
  22.   
  23.             flag = 0;  
  24.   
  25.             System.out.println("no,please try again.");  
  26.   
  27.             input = Integer.parseInt(br.readLine());  
  28.   
  29.         }  
  30.   
  31.     }  
  32.   
  33. }  

[java]  view plain copy
  1. L1: while (true) {<BR>
  2. int question = new Times().question();<BR>
  3. L2: while (true) {<BR>
  4. int answer = scanner.nextInt();<BR>
  5. if (answer == question) {<BR>
  6. System.out.println("very good!");<BR>
  7. continue L1;<BR>
  8. else {<BR>
  9. System.out.println("no,please try again.");<BR>
  10. continue L2;<BR>
  11. }<BR>
  12. }<BR>
  13. }
[java]  view plain  copy
  1. L1: while (true) {  
  2.   
  3.     int question = new Times().question();  
  4.   
  5.     L2: while (true) {  
  6.   
  7.         int answer = scanner.nextInt();  
  8.   
  9.         if (answer == question) {  
  10.   
  11.             System.out.println("very good!");  
  12.   
  13.             continue L1;  
  14.   
  15.         } else {  
  16.   
  17.             System.out.println("no,please try again.");  
  18.   
  19.             continue L2;  
  20.   
  21.         }  
  22.   
  23.     }  
  24.   
  25. }  

[java]  view plain copy
  1. char[] c1 = s1.toCharArray();
[java]  view plain  copy
  1. char[] c1 = s1.toCharArray();  

[java]  view plain copy
  1. Map<Integer, String> m =new HashMap<Integer, String>();<BR>
  2. m.put(1"one");<BR>
  3. m.put(2"two");<BR>
  4. m.put(3"three");<BR>
  5. Object o[] = m.values().toArray();
[java]  view plain  copy
  1. Map<Integer, String> m = new HashMap<Integer, String>();  
  2.   
  3. m.put(1"one");  
  4.   
  5. m.put(2"two");  
  6.   
  7. m.put(3"three");  
  8.   
  9. Object o[] = m.values().toArray();  

[java]  view plain copy
  1. GregorianCalendar ca = new GregorianCalendar();<BR>
  2. System.out.println(ca.get(GregorianCalendar.AM_PM));
[java]  view plain  copy
  1. GregorianCalendar ca = new GregorianCalendar();  
  2.   
  3. System.out.println(ca.get(GregorianCalendar.AM_PM));  

2009  -  02  -  06

Java snippets01

[java]  view plain copy
  1. for (int i =0; i < number.length; i++) {<BR>
  2. for (int j = 0; j < number.length - i - 1; j++) {<BR>
  3. if (number[j] < number[j + 1]) {<BR>
  4. int temp = number[j];<BR>
  5. number[j] = number[j + 1];<BR>
  6. number[j + 1] = temp;<BR>
  7. }<BR>
  8. }<BR>
  9. }<BR>
[java]  view plain  copy
  1. for (int i = 0; i < number.length; i++) {  
  2.   
  3.     for (int j = 0; j < number.length - i - 1; j++) {  
  4.   
  5.         if (number[j] < number[j + 1]) {  
  6.   
  7.             int temp = number[j];  
  8.   
  9.             number[j] = number[j + 1];  
  10.   
  11.             number[j + 1] = temp;  
  12.   
  13.         }  
  14.   
  15.     }  
  16.   
  17. }  

[java]  view plain copy
  1. BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));<BR>
  2. String str = buffer.readLine();
[java]  view plain  copy
  1. BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));  
  2.   
  3. String str = buffer.readLine();  

[java]  view plain copy
  1. Scanner scanner = new Scanner(System.in);<BR>
  2. String line = scanner.nextLine();
[java]  view plain  copy
  1. Scanner scanner = new Scanner(System.in);  
  2.   
  3. String line = scanner.nextLine();  


[java]  view plain copy
  1. InputStreamReader in = null;<BR>
  2. OutputStreamWriter out = null;<BR>
  3. BufferedReader br = null;<BR>
  4. <BR>
  5. in = new InputStreamReader(new FileInputStream(System<BR>
  6. .getProperty("user.dir")<BR>
  7. "//old.txt"), "UTF-8");<BR>
  8. br = new BufferedReader(in);<BR>
  9. out = new OutputStreamWriter(new FileOutputStream(<BR>
  10. "C://WINDOWS//new.txt"), "UTF-8");
[java]  view plain  copy
  1. InputStreamReader in = null;  
  2.   
  3. OutputStreamWriter out = null;  
  4.   
  5. BufferedReader br = null;  
  6.   
  7.   
  8.   
  9. in = new InputStreamReader(new FileInputStream(System  
  10.   
  11.                     .getProperty("user.dir")  
  12.   
  13.                     + "//old.txt"), "UTF-8");  
  14.   
  15. br = new BufferedReader(in);  
  16.   
  17. out = new OutputStreamWriter(new FileOutputStream(  
  18.   
  19.                     "C://WINDOWS//new.txt"), "UTF-8");  

[java]  view plain copy
  1. String[] temp;<BR>
  2. temp = text.split("//s{1,}");// 按照空格分割字符串,多个空格作为一个空格对字符串进行分割
[java]  view plain  copy
  1. String[] temp;  
  2.   
  3. temp = text.split("//s{1,}");// 按照空格分割字符串,多个空格作为一个空格对字符串进行分割  

[java]  view plain copy
  1. String s = String.valueOf(1);<BR>
  2. if (s.charAt(i) == '1'){}<BR>
[java]  view plain  copy
  1. String s = String.valueOf(1);  
  2.   
  3. if (s.charAt(i) == '1'){}  

[java]  view plain copy
  1. System.nanoTime();
[java]  view plain  copy
  1. System.nanoTime();  

[java]  view plain copy
  1. SimpleDateFormat sdt = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");<BR>
  2. String date = sdt.format(System.currentTimeMillis());
[java]  view plain  copy
  1. SimpleDateFormat sdt = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");  
  2.   
  3. String date = sdt.format(System.currentTimeMillis());  

[java]  view plain copy
  1. DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();<BR>
  2. df.applyPattern("00");
[java]  view plain  copy
  1. DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();  
  2.   
  3. df.applyPattern("00");  

[java]  view plain copy
  1. Calendar current_time = new GregorianCalendar();<BR>
  2. Calendar target_time = new GregorianCalendar(2009, Calendar.MAY,1);<BR>
  3. long diffMillis = target_time.getTimeInMillis()<BR>
  4. - current_time.getTimeInMillis();<BR>
  5. long diffDays = diffMillis / (24 *60 * 60 * 1000) + 1;<BR>
  6. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-DD");<BR>
  7. <BR>
  8. System.out.println("距" + sdf.format(target_time.getTimeInMillis())<BR>
  9. "还有:" + diffDays + "天");
[java]  view plain  copy
  1. Calendar current_time = new GregorianCalendar();  
  2.   
  3. Calendar target_time = new GregorianCalendar(2009, Calendar.MAY, 1);  
  4.   
  5. long diffMillis = target_time.getTimeInMillis()  
  6.   
  7.         - current_time.getTimeInMillis();  
  8.   
  9. long diffDays = diffMillis / (24 * 60 * 60 * 1000) + 1;  
  10.   
  11. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-DD");  
  12.   
  13.   
  14.   
  15. System.out.println("距" + sdf.format(target_time.getTimeInMillis())  
  16.   
  17.         + "还有:" + diffDays + "天");  

[java]  view plain copy
  1. Arrays.sort(array);
[java]  view plain  copy
  1. Arrays.sort(array);  

[java]  view plain copy
  1. StringBuilder s1 = new StringBuilder(temp);<BR>
  2. // StringBuffer s1 = new StringBuffer(temp);<BR>
  3. System.out.println(s1.reverse());
[java]  view plain  copy
  1. StringBuilder s1 = new StringBuilder(temp);  
  2.   
  3. // StringBuffer s1 = new StringBuffer(temp);  
  4.   
  5. System.out.println(s1.reverse());  

2009  -  02  -  06

双色球算号器

我是个彩民,特别喜欢买双色球。最近看了几种算法,写了一个很简单的双色球的算号器,分享给大家,仅供娱乐,呵呵 
[java]  view plain copy
  1. package com.tester.luckly;<BR>
  2. <BR>
  3. import java.util.Random;<BR>
  4. import java.util.Scanner;<BR>
  5. import java.util.Set;<BR>
  6. import java.util.TreeSet;<BR>
  7. <BR>
  8. public class DoubleBall {<BR>
  9. private Set<Integer> hs;<BR>
  10. private static boolean flag = true;<BR>
  11. <BR>
  12. public enum oddOrEven {<BR>
  13. Odd, Even<BR>
  14. }<BR>
  15. <BR>
  16. public enum aOrBOrC {<BR>
  17. A, B, C<BR>
  18. }<BR>
  19. <BR>
  20. public static void main(String[] args) {<BR>
  21. DoubleBall db = new DoubleBall();<BR>
  22. System.out<BR>
  23. .println("====================Red Balls============================");<BR>
  24. String url1 = "http://map.zhcw.com/ssq//html/h7fenqu_ascstr=20.html";<BR>
  25. System.out.println();<BR>
  26. System.err.println(url1);<BR>
  27. Scanner scanner1 = new Scanner(System.in);<BR>
  28. System.out.println("Please select:1.Input your own two numbers");<BR>
  29. System.out<BR>
  30. .println(" 2.Input the range of the two numbers");<BR>
  31. int select = scanner1.nextInt();<BR>
  32. if (select == 1) {<BR>
  33. flag = false;<BR>
  34. else {<BR>
  35. flag = true;<BR>
  36. }<BR>
  37. System.out.println("Please input two numbers like this: 1 2");<BR>
  38. scanner1.nextLine();<BR>
  39. String[] str = scanner1.nextLine().split(" ");<BR>
  40. Set<Integer> redBall = db.calcRedBall(Integer.parseInt(str[0]), Integer<BR>
  41. .parseInt(str[1]));<BR>
  42. <BR>
  43. System.out<BR>
  44. .println("====================Blue Ball============================");<BR>
  45. String url2 = "http://sports.sohu.com/s2007/0445/s252476794/";<BR>
  46. System.out.println();<BR>
  47. System.err.println(url2);<BR>
  48. Scanner scanner2 = new Scanner(System.in);<BR>
  49. <BR>
  50. System.out.println("1.Please select:" + oddOrEven.Odd +" or "<BR>
  51. + oddOrEven.Even);<BR>
  52. String select1 = scanner2.nextLine();<BR>
  53. <BR>
  54. System.out.println("2.Please select:" + aOrBOrC.A +" or " + aOrBOrC.B<BR>
  55. " or " + aOrBOrC.C);<BR>
  56. String select2 = scanner2.nextLine();<BR>
  57. <BR>
  58. int blueBall = db.calcBlueBall(select1, select2);<BR>
  59. <BR>
  60. System.out<BR>
  61. .println("====================The Result============================");<BR>
  62. System.out.println();<BR>
  63. for (int i : redBall) {<BR>
  64. System.err.print(i + " ");<BR>
  65. }<BR>
  66. System.err.println("| " + blueBall);<BR>
  67. String url3 = "http://www.bwlc.net/dhtz/";<BR>
  68. System.err.println(url3);<BR>
  69. }<BR>
  70. <BR>
  71. public Set<Integer> calcRedBall(int begin,int end) {<BR>
  72. hs = new TreeSet<Integer>();<BR>
  73. <BR>
  74. /*<BR>
  75. * 固定恒码:就是每期都必备的号码,通常为2-3个,如02,13,27。 这2-3个号码长期备选(至少50期)。<BR>
  76. */<BR>
  77. hs.add(10);<BR>
  78. hs.add(27);<BR>
  79. <BR>
  80. /*<BR>
  81. * 边缘捡“胆”:就是在边缘码“05、10、15、20、25、30”及“01、<BR>
  82. * 06、11、16、21、26、31”共13个号码中巧妙地捡出胆码。之所以 把边缘码作为“胆”码的一种选取方法,是因为从历史中奖号码来看,<BR>
  83. * 几乎每一期都会在具备这种特性的号码中出现2-3个。<BR>
  84. */<BR>
  85. int[] array = { 51520253001061116212631 };<BR>
  86. for (int i = 0; i < 2; i++) {<BR>
  87. Random random = new Random();<BR>
  88. hs.add(array[random.nextInt(array.length)]);<BR>
  89. }<BR>
  90. <BR>
  91. /*<BR>
  92. * 重码追邻:在上上期出号的左右选取的上期号码,这话不好理解,现举例说明:双色球2007109期开01 04 07 08 13 14;<BR>
  93. * 110期开02 04 07 15 24 28;其中这期的04<BR>
  94. * 07,刚好是109期二、三位的重码,那么111期的重码该选取哪个呢?重码追邻就是在110期的04 07 的左右选取,110期04 07<BR>
  95. * 的左右是02 15。所以111期的备选号就是02 15 了。实际上111期重码刚好开的是02。重码追邻一般选取2-3个号码。<BR>
  96. */<BR>
  97. /* ========= 或者========= */<BR>
  98. /* 旺区落“胆”。就是在最近几期热号区选择胆码。比如,如果最近的5期内,在中区12~22出号比较密集,那么就要在这个区域里选取3个胆码。这样选择的理由是热码恒热原理,即号码总是在某个区域相对集中出现。 */<BR>
  99. if (flag == true) {<BR>
  100. hs.add(begin);<BR>
  101. hs.add(end);<BR>
  102. else {<BR>
  103. Random random = new Random();<BR>
  104. hs.add(begin + random.nextInt(end - begin + 1));<BR>
  105. }<BR>
  106. /* Luck number! */<BR>
  107. while (hs.size() < 6) {<BR>
  108. Random random = new Random();<BR>
  109. hs.add(1 + random.nextInt(33));<BR>
  110. }<BR>
  111. <BR>
  112. return hs;<BR>
  113. }<BR>
  114. <BR>
  115. public int calcBlueBall(String select1, String select2) {<BR>
  116. int begin = 1;<BR>
  117. int end = 16;<BR>
  118. <BR>
  119. if (select2.equals(aOrBOrC.A.toString())) {<BR>
  120. begin = 1;<BR>
  121. end = 5;<BR>
  122. else if (select2.equals(aOrBOrC.B.toString())) {<BR>
  123. begin = 6;<BR>
  124. end = 10;<BR>
  125. else {<BR>
  126. begin = 11;<BR>
  127. end = 16;<BR>
  128. }<BR>
  129. <BR>
  130. Random random = new Random();<BR>
  131. int blueBall = begin + random.nextInt(end - begin +1);<BR>
  132. if (select1.equals(oddOrEven.Odd.toString())) {<BR>
  133. while (blueBall % 2 == 0) {<BR>
  134. blueBall = begin + random.nextInt(end - begin + 1);<BR>
  135. }<BR>
  136. else {<BR>
  137. while (blueBall % 2 == 1) {<BR>
  138. blueBall = begin + random.nextInt(end - begin + 1);<BR>
  139. }<BR>
  140. }<BR>
  141. <BR>
  142. return blueBall;<BR>
  143. }<BR>
  144. }
[java]  view plain  copy
  1. package com.tester.luckly;  
  2.   
  3.   
  4.   
  5. import java.util.Random;  
  6.   
  7. import java.util.Scanner;  
  8.   
  9. import java.util.Set;  
  10.   
  11. import java.util.TreeSet;  
  12.   
  13.   
  14.   
  15. public class DoubleBall {  
  16.   
  17.     private Set<Integer> hs;  
  18.   
  19.     private static boolean flag = true;  
  20.   
  21.   
  22.   
  23.     public enum oddOrEven {  
  24.   
  25.         Odd, Even  
  26.   
  27.     }  
  28.   
  29.   
  30.   
  31.     public enum aOrBOrC {  
  32.   
  33.         A, B, C  
  34.   
  35.     }  
  36.   
  37.   
  38.   
  39.     public static void main(String[] args) {  
  40.   
  41.         DoubleBall db = new DoubleBall();  
  42.   
  43.         System.out  
  44.   
  45.                 .println("====================Red Balls============================");  
  46.   
  47.         String url1 = "http://map.zhcw.com/ssq//html/h7fenqu_ascstr=20.html";  
  48.   
  49.         System.out.println();  
  50.   
  51.         System.err.println(url1);  
  52.   
  53.         Scanner scanner1 = new Scanner(System.in);  
  54.   
  55.         System.out.println("Please select:1.Input your own two numbers");  
  56.   
  57.         System.out  
  58.   
  59.                 .println("              2.Input the range of the two numbers");  
  60.   
  61.         int select = scanner1.nextInt();  
  62.   
  63.         if (select == 1) {  
  64.   
  65.             flag = false;  
  66.   
  67.         } else {  
  68.   
  69.             flag = true;  
  70.   
  71.         }  
  72.   
  73.         System.out.println("Please input two numbers like this: 1 2");  
  74.   
  75.         scanner1.nextLine();  
  76.   
  77.         String[] str = scanner1.nextLine().split(" ");  
  78.   
  79.         Set<Integer> redBall = db.calcRedBall(Integer.parseInt(str[0]), Integer  
  80.   
  81.                 .parseInt(str[1]));  
  82.   
  83.   
  84.   
  85.         System.out  
  86.   
  87.                 .println("====================Blue Ball============================");  
  88.   
  89.         String url2 = "http://sports.sohu.com/s2007/0445/s252476794/";  
  90.   
  91.         System.out.println();  
  92.   
  93.         System.err.println(url2);  
  94.   
  95.         Scanner scanner2 = new Scanner(System.in);  
  96.   
  97.   
  98.   
  99.         System.out.println("1.Please select:" + oddOrEven.Odd + " or "  
  100.   
  101.                 + oddOrEven.Even);  
  102.   
  103.         String select1 = scanner2.nextLine();  
  104.   
  105.   
  106.   
  107.         System.out.println("2.Please select:" + aOrBOrC.A + " or " + aOrBOrC.B  
  108.   
  109.                 + " or " + aOrBOrC.C);  
  110.   
  111.         String select2 = scanner2.nextLine();  
  112.   
  113.   
  114.   
  115.         int blueBall = db.calcBlueBall(select1, select2);  
  116.   
  117.   
  118.   
  119.         System.out  
  120.   
  121.                 .println("====================The Result============================");  
  122.   
  123.         System.out.println();  
  124.   
  125.         for (int i : redBall) {  
  126.   
  127.             System.err.print(i + " ");  
  128.   
  129.         }  
  130.   
  131.         System.err.println("| " + blueBall);  
  132.   
  133.         String url3 = "http://www.bwlc.net/dhtz/";  
  134.   
  135.         System.err.println(url3);  
  136.   
  137.     }  
  138.   
  139.   
  140.   
  141.     public Set<Integer> calcRedBall(int begin, int end) {  
  142.   
  143.         hs = new TreeSet<Integer>();  
  144.   
  145.   
  146.   
  147.         /* 
  148.  
  149.          * 固定恒码:就是每期都必备的号码,通常为2-3个,如02,13,27。 这2-3个号码长期备选(至少50期)。 
  150.  
  151.          */  
  152.   
  153.         hs.add(10);  
  154.   
  155.         hs.add(27);  
  156.   
  157.   
  158.   
  159.         /* 
  160.  
  161.          * 边缘捡“胆”:就是在边缘码“05、10、15、20、25、30”及“01、 
  162.  
  163.          * 06、11、16、21、26、31”共13个号码中巧妙地捡出胆码。之所以 把边缘码作为“胆”码的一种选取方法,是因为从历史中奖号码来看, 
  164.  
  165.          * 几乎每一期都会在具备这种特性的号码中出现2-3个。 
  166.  
  167.          */  
  168.   
  169.         int[] array = { 51520253001061116212631 };  
  170.   
  171.         for (int i = 0; i < 2; i++) {  
  172.   
  173.             Random random = new Random();  
  174.   
  175.             hs.add(array[random.nextInt(array.length)]);  
  176.   
  177.         }  
  178.   
  179.   
  180.   
  181.         /* 
  182.  
  183.          * 重码追邻:在上上期出号的左右选取的上期号码,这话不好理解,现举例说明:双色球2007109期开01 04 07 08 13 14; 
  184.  
  185.          * 110期开02 04 07 15 24 28;其中这期的04 
  186.  
  187.          * 07,刚好是109期二、三位的重码,那么111期的重码该选取哪个呢?重码追邻就是在110期的04 07 的左右选取,110期04 07 
  188.  
  189.          * 的左右是02 15。所以111期的备选号就是02 15 了。实际上111期重码刚好开的是02。重码追邻一般选取2-3个号码。 
  190.  
  191.          */  
  192.   
  193.         /* ========= 或者========= */  
  194.   
  195.         /* 旺区落“胆”。就是在最近几期热号区选择胆码。比如,如果最近的5期内,在中区12~22出号比较密集,那么就要在这个区域里选取3个胆码。这样选择的理由是热码恒热原理,即号码总是在某个区域相对集中出现。 */  
  196.   
  197.         if (flag == true) {  
  198.   
  199.             hs.add(begin);  
  200.   
  201.             hs.add(end);  
  202.   
  203.         } else {  
  204.   
  205.             Random random = new Random();  
  206.   
  207.             hs.add(begin + random.nextInt(end - begin + 1));  
  208.   
  209.         }  
  210.   
  211.         /* Luck number! */  
  212.   
  213.         while (hs.size() < 6) {  
  214.   
  215.             Random random = new Random();  
  216.   
  217.             hs.add(1 + random.nextInt(33));  
  218.   
  219.         }  
  220.   
  221.   
  222.   
  223.         return hs;  
  224.   
  225.     }  
  226.   
  227.   
  228.   
  229.     public int calcBlueBall(String select1, String select2) {  
  230.   
  231.         int begin = 1;  
  232.   
  233.         int end = 16;  
  234.   
  235.   
  236.   
  237.         if (select2.equals(aOrBOrC.A.toString())) {  
  238.   
  239.             begin = 1;  
  240.   
  241.             end = 5;  
  242.   
  243.         } else if (select2.equals(aOrBOrC.B.toString())) {  
  244.   
  245.             begin = 6;  
  246.   
  247.             end = 10;  
  248.   
  249.         } else {  
  250.   
  251.             begin = 11;  
  252.   
  253.             end = 16;  
  254.   
  255.         }  
  256.   
  257.   
  258.   
  259.         Random random = new Random();  
  260.   
  261.         int blueBall = begin + random.nextInt(end - begin + 1);  
  262.   
  263.         if (select1.equals(oddOrEven.Odd.toString())) {  
  264.   
  265.             while (blueBall % 2 == 0) {  
  266.   
  267.                 blueBall = begin + random.nextInt(end - begin + 1);  
  268.   
  269.             }  
  270.   
  271.         } else {  
  272.   
  273.             while (blueBall % 2 == 1) {  
  274.   
  275.                 blueBall = begin + random.nextInt(end - begin + 1);  
  276.   
  277.             }  
  278.   
  279.         }  
  280.   
  281.   
  282.   
  283.         return blueBall;  
  284.   
  285.     }  
  286.   
  287. }  

今天遇到了一个极其郁闷的问题,想写一段代码,可以给windows自动安装一种字体。 
原理就是将4个ttf字体文件复制到C://WINDOWS//Fonts//目录下。本来以为很简单,但用java I/O复制过去的字体不能使用(将记事本的字体改成DejaVuSansMono,如果有效果变化,就是正常的),直接手动复制同样的文件过去,就可以使用。不知道问题出在哪里?
哪位朋友帮忙看看,万分感谢,字体文件在附件中,代码如下: 
[java]  view plain copy
  1. package com.test;<BR>
  2. import java.io.FileInputStream;<BR>
  3. import java.io.FileOutputStream;<BR>
  4. import java.io.IOException;<BR>
  5. import java.nio.channels.FileChannel;<BR>
  6. <BR>
  7. public class FontInstall {<BR>
  8. <BR>
  9. public staticvoid main(String[] args) {<BR>
  10. try {<BR>
  11. String[] fonts = { "DejaVuSansMono-Oblique.ttf",<BR>
  12. "DejaVuSansMono-BoldOblique.ttf""DejaVuSansMono.ttf",<BR>
  13. "DejaVuSansMono-Bold.ttf" };<BR>
  14. System.out.println();<BR>
  15. for (int i =0; i < fonts.length; i++) {<BR>
  16. // Create channel on the source<BR>
  17. FileChannel srcChannel = new FileInputStream(System<BR>
  18. .getProperty("user.dir")<BR>
  19. "//" + fonts[i]).getChannel();<BR>
  20. <BR>
  21. // Create channel on the destination<BR>
  22. FileChannel dstChannel = new FileOutputStream(<BR>
  23. "C://WINDOWS//Fonts//" + fonts[i]).getChannel();<BR>
  24. <BR>
  25. // Copy file contents from source to destination<BR>
  26. dstChannel.transferFrom(srcChannel, 0, srcChannel.size());<BR>
  27. <BR>
  28. // Close the channels<BR>
  29. srcChannel.close();<BR>
  30. dstChannel.close();<BR>
  31. }<BR>
  32. catch (IOException e) {<BR>
  33. }<BR>
  34. }<BR>
  35. }<BR>
[java]  view plain  copy
  1. package com.test;  
  2.   
  3. import java.io.FileInputStream;  
  4.   
  5. import java.io.FileOutputStream;  
  6.   
  7. import java.io.IOException;  
  8.   
  9. import java.nio.channels.FileChannel;  
  10.   
  11.   
  12.   
  13. public class FontInstall {  
  14.   
  15.   
  16.   
  17.     public static void main(String[] args) {  
  18.   
  19.         try {  
  20.   
  21.             String[] fonts = { "DejaVuSansMono-Oblique.ttf",  
  22.   
  23.                     "DejaVuSansMono-BoldOblique.ttf""DejaVuSansMono.ttf",  
  24.   
  25.                     "DejaVuSansMono-Bold.ttf" };  
  26.   
  27.             System.out.println();  
  28.   
  29.             for (int i = 0; i < fonts.length; i++) {  
  30.   
  31.                 // Create channel on the source  
  32.   
  33.                 FileChannel srcChannel = new FileInputStream(System  
  34.   
  35.                         .getProperty("user.dir")  
  36.   
  37.                         + "//" + fonts[i]).getChannel();  
  38.   
  39.   
  40.   
  41.                 // Create channel on the destination  
  42.   
  43.                 FileChannel dstChannel = new FileOutputStream(  
  44.   
  45.                         "C://WINDOWS//Fonts//" + fonts[i]).getChannel();  
  46.   
  47.   
  48.   
  49.                 // Copy file contents from source to destination  
  50.   
  51.                 dstChannel.transferFrom(srcChannel, 0, srcChannel.size());  
  52.   
  53.   
  54.   
  55.                 // Close the channels  
  56.   
  57.                 srcChannel.close();  
  58.   
  59.                 dstChannel.close();  
  60.   
  61.             }  
  62.   
  63.         } catch (IOException e) {  
  64.   
  65.         }  
  66.   
  67.     }  
  68.   
  69. }  

用另一种写法试了下,也是不行,复制过去的文件大小是相同的,用比较工具比较也没问题。 
[java]  view plain copy
  1. package com.test;<BR>
  2. <BR>
  3. import java.io.FileInputStream;<BR>
  4. import java.io.FileOutputStream;<BR>
  5. import java.io.IOException;<BR>
  6. import java.io.InputStream;<BR>
  7. import java.io.OutputStream;<BR>
  8. <BR>
  9. public class FontInstall2 {<BR>
  10. <BR>
  11. public staticvoid main(String[] args) {<BR>
  12. try {<BR>
  13. String[] fonts = { "DejaVuSansMono-Oblique.ttf",<BR>
  14. "DejaVuSansMono-BoldOblique.ttf""DejaVuSansMono.ttf",<BR>
  15. "DejaVuSansMono-Bold.ttf" };<BR>
  16. System.out.println();<BR>
  17. for (int i =0; i < fonts.length; i++) {<BR>
  18. InputStream in = new FileInputStream(System<BR>
  19. .getProperty("user.dir")<BR>
  20. "//" + fonts[i]);<BR>
  21. OutputStream out = new FileOutputStream("C://WINDOWS//Fonts//"<BR>
  22. + fonts[i]);<BR>
  23. <BR>
  24. // Transfer bytes from in to out<BR>
  25. byte[] buf = newbyte[1024];<BR>
  26. int len;<BR>
  27. while ((len = in.read(buf)) > 0) {<BR>
  28. out.write(buf, 0, len);<BR>
  29. }<BR>
  30. in.close();<BR>
  31. out.close();<BR>
  32. }<BR>
  33. catch (IOException e) {<BR>
  34. }<BR>
  35. }<BR>
  36. }<BR>
[java]  view plain  copy
  1. package com.test;  
  2.   
  3.   
  4.   
  5. import java.io.FileInputStream;  
  6.   
  7. import java.io.FileOutputStream;  
  8.   
  9. import java.io.IOException;  
  10.   
  11. import java.io.InputStream;  
  12.   
  13. import java.io.OutputStream;  
  14.   
  15.   
  16.   
  17. public class FontInstall2 {  
  18.   
  19.   
  20.   
  21.     public static void main(String[] args) {  
  22.   
  23.         try {  
  24.   
  25.             String[] fonts = { "DejaVuSansMono-Oblique.ttf",  
  26.   
  27.                     "DejaVuSansMono-BoldOblique.ttf""DejaVuSansMono.ttf",  
  28.   
  29.                     "DejaVuSansMono-Bold.ttf" };  
  30.   
  31.             System.out.println();  
  32.   
  33.             for (int i = 0; i < fonts.length; i++) {  
  34.   
  35.                 InputStream in = new FileInputStream(System  
  36.   
  37.                         .getProperty("user.dir")  
  38.   
  39.                         + "//" + fonts[i]);  
  40.   
  41.                 OutputStream out = new FileOutputStream("C://WINDOWS//Fonts//"  
  42.   
  43.                         + fonts[i]);  
  44.   
  45.   
  46.   
  47.                 // Transfer bytes from in to out  
  48.   
  49.                 byte[] buf = new byte[1024];  
  50.   
  51.                 int len;  
  52.   
  53.                 while ((len = in.read(buf)) > 0) {  
  54.   
  55.                     out.write(buf, 0, len);  
  56.   
  57.                 }  
  58.   
  59.                 in.close();  
  60.   
  61.                 out.close();  
  62.   
  63.             }  
  64.   
  65.         } catch (IOException e) {  
  66.   
  67.         }  
  68.   
  69.     }  
  70.   
  71. }  


java.util就相当于c++的STL,是Java的一个非常重要的包,有很多常用的数据类型,不同数据类型有不同的用途,而有些数据类似乎很相似,怎样选择应用,就需要对它们进行辨析。
下面列出了这些数据类型的特点,根据这些特点,就可以有针对性的选用 
  
* 蓝色为接口,绿色为具体实现类 
* 缩进的层次结构,就是implement或extend的层次关系 
* 每个接口或类都具备其所有上层接口、类的特性 
  
Collection 
........|--------List 
........|..........|----------ArrayList 
........|..........|----------Vector 
........|..........|.............|-----Stack 
........|..........|----------LinkedList 
........|--------Set 
...................|----------HashSet. 
...................|.............|-----LinkedHashSet 
...................|----------SortedSet 
.................................|-----TreeSet 
  
Iterator 
.....|-------ListIterator 
  
Map 
.....|------Hashtable 
.....|..........|------Properties 
.....|------Hash Map 
.....|..........|------LinkedHash Map
.....|------WeakHash Map 
.....|------Sorted Map 
................|------Tree Map 

  
Collection. 
●..实现该接口及其子接口的所有类都可应用clone()方法,并是序列化类. 

.....List. 
.....●..可随机访问包含的元素 
.....●..元素是有序的 
.....●..可在任意位置增、删元素 
.....●..不管访问多少次,元素位置不变 
.....●..允许重复元素 
.....●..用Iterator实现单向遍历,也可用ListIterator实现双向遍历 

..........ArrayList 
..........●..用数组作为根本的数据结构来实现List 
..........●..元素顺序存储 
..........●..新增元素改变List大小时,内部会新建一个数组,在将添加元素前将所有数据拷贝到新数组中 
..........●..随机访问很快,删除非头尾元素慢,新增元素慢而且费资源 
..........●..较适用于无频繁增删的情况 
..........●..比数组效率低,如果不是需要可变数组,可考虑使用数组 
..........●..非线程安全 

..........Vector. 
..........●..另一种ArrayList,具备ArrayList的特性 
..........●..所有方法都是线程安全的(双刃剑,和ArrayList的主要区别) 
..........●..比ArrayList效率低 

...............Stack 
...............●..LIFO的数据结构 

..........LinkedList. 
..........●..链接对象数据结构(类似链表) 
..........●..随机访问很慢,增删操作很快,不耗费多余资源 
..........●..非线程安全 

.....Set. 
.....●..不允许重复元素,可以有一个空元素 
.....●..不可随机访问包含的元素 
.....●..只能用Iterator实现单向遍历 

..........HashSet 
..........●..用Hash Map作为根本数据结构来实现Set
..........●..元素是无序的 
..........●..迭代访问元素的顺序和加入的顺序不同 
..........●..多次迭代访问,元素的顺序可能不同 
..........●..非线程安全 

...............LinkedHashSet 
...............●..基于Hash Map和链表的Set实现
...............●..迭代访问元素的顺序和加入的顺序相同 
...............●..多次迭代访问,元素的顺序不便 
...............●..因此可说这是一种有序的数据结构 
...............●..性能比HashSet差 
...............●..非线程安全 

..........SortedSet 
..........●..加入SortedSet的所有元素必须实现Comparable接口 
..........●..元素是有序的 

...............TreeSet. 
...............●..基于Tree Map实现的SortedSet
...............●..排序后按升序排列元素 
...............●..非线程安全 

----------------------------------- 
  
Iterator.. 
●..对Set、List进行单向遍历的迭代器 

..........ListIterator. 
..........●..对List进行双向遍历的迭代器 

----------------------------------- 

Map 
●..键值对,键和值一一对应 
●..不允许重复的键. 

.....Hashtable. 
.....●..用作键的对象必须实现了hashcode()、equals()方法,也就是说只有Object及其子类可用作键 
.....●..键、值都不能是空对象 
.....●..多次访问,映射元素的顺序相同 
.....●..线程安全的 

..........Properties 
..........●..键和值都是字符串 

.....Hash Map 
.....●..键和值都可以是空对象 
.....●..不保证映射的顺序 
.....●..多次访问,映射元素的顺序可能不同 
.....●..非线程安全 

...............LinkedHash Map 
...............●..多次访问,映射元素的顺序是相同的 
...............●..性能比Hash Map差 

.....WeakHash Map.. 
.....●..当某个键不再正常使用时,垃圾收集器会移除它,即便有映射关系存在 
.....●..非线程安全 

.....Sorted Map
.....●..键按升序排列 
.....●..所有键都必须实现.Comparable.接口. 

...............Tree Map
...............●..基于红黑树的Sorted Map实现
...............●..非线程安全 
正则表达式是一种通用的标准,大部分计算机语言都支持正则表达式,包括as3,这里转摘出了一些常用的正则表达式语句,大家用到的时候就不用自己写了

^/d+$  //匹配非负整数(正整数 + 0) 
^[0-9]*[1-9][0-9]*$  //匹配正整数 
^((-/d+)|(0+))$  //匹配非正整数(负整数 + 0) 
^-[0-9]*[1-9][0-9]*$  //匹配负整数 
^-?/d+$    //匹配整数 
^/d+(/./d+)?$  //匹配非负浮点数(正浮点数 + 0) 
^(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*))$  //匹配正浮点数
^((-/d+(/./d+)?)|(0+(/.0+)?))$  //匹配非正浮点数(负浮点数 + 0) 
^(-(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*)))$  //匹配负浮点数
^(-?/d+)(/./d+)?$  //匹配浮点数 
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串 
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串 
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串 
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串 
^/w+$  //匹配由数字、26个英文字母或者下划线组成的字符串 
^[/w-]+(/.[/w-]+)*@[/w-]+(/.[/w-]+)+$    //匹配email地址 
^[a-zA-z]+://匹配(/w+(-/w+)*)(/.(/w+(-/w+)*))*(/?/S*)?$  //匹配url 

匹配中文字符的正则表达式: [/u4e00-/u9fa5] 
匹配双字节字符(包括汉字在内):[^/x00-/xff] 
匹配空行的正则表达式:/n[/s| ]*/r 
匹配HTML标记的正则表达式:/<(.*)>.*<//>|<(.*) //>/ 
匹配首尾空格的正则表达式:(^/s*)|(/s*$) 
匹配Email地址的正则表达式:/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)* 
匹配网址URL的正则表达式:^[a-zA-z]+://(/w+(-/w+)*)(/.(/w+(-/w+)*))*(/?/S*)?$ 
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 
匹配国内电话号码:(/d{3}-|/d{4}-)?(/d{8}|/d{7})? 
匹配腾讯QQ号:^[1-9]*[1-9][0-9]*$ 
下表是元字符及其在正则表达式上下文中的行为的一个完整列表: 
/ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。 
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的Multiline 属性,^ 也匹配 ’/n’ 或 ’/r’ 之后的位置。 
$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的Multiline 属性,$ 也匹配 ’/n’ 或 ’/r’ 之前的位置。 
* 匹配前面的子表达式零次或多次。 
+ 匹配前面的子表达式一次或多次。+ 等价于 {1,}。 
? 匹配前面的子表达式零次或一次。? 等价于 {0,1}。 
{n} n 是一个非负整数,匹配确定的n 次。 
{n,} n 是一个非负整数,至少匹配n 次。 
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。在逗号和两个数之间不能有空格。 
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。
. 匹配除 "/n" 之外的任何单个字符。要匹配包括 ’/n’ 在内的任何字符,请使用象 ’[./n]’ 的模式。 
(pattern) 匹配pattern 并获取这一匹配。 
(?:pattern) 匹配pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。 
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。 
(?!pattern) 负向预查,与(?=pattern)作用相反 
x|y 匹配 x 或 y。 
[xyz] 字符集合。 
[^xyz] 负值字符集合。 
[a-z] 字符范围,匹配指定范围内的任意字符。 
[^a-z] 负值字符范围,匹配任何不在指定范围内的任意字符。 
/b 匹配一个单词边界,也就是指单词和空格间的位置。 
/B 匹配非单词边界。 
/cx 匹配由x指明的控制字符。 
/d 匹配一个数字字符。等价于 [0-9]。 
/D 匹配一个非数字字符。等价于 [^0-9]。 
/f 匹配一个换页符。等价于 /x0c 和 /cL。 
/n 匹配一个换行符。等价于 /x0a 和 /cJ。 
/r 匹配一个回车符。等价于 /x0d 和 /cM。 
/s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ /f/n/r/t/v]。 
/S 匹配任何非空白字符。等价于 [^ /f/n/r/t/v]。 
/t 匹配一个制表符。等价于 /x09 和 /cI。 
/v 匹配一个垂直制表符。等价于 /x0b 和 /cK。 
/w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 
/W 匹配任何非单词字符。等价于 ’[^A-Za-z0-9_]’。 
/xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。 
/num 匹配 num,其中num是一个正整数。对所获取的匹配的引用。 
/n 标识一个八进制转义值或一个后向引用。如果 /n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
/nm 标识一个八进制转义值或一个后向引用。如果 /nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 /nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 /nm 将匹配八进制转义值 nm。
/nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八 
2009  -  01  -  21

编程经典问题

【程序1】 
题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 
1.程序分析: 兔子的规律为数列1,1,2,3,5,8,13,21.... 

【程序2】 
题目:判断101-200之间有多少个素数,并输出所有素数。 
1.程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 
则表明此数不是素数,反之是素数。 

【程序3】 
题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方。
1.程序分析:利用for循环控制100-999个数,每个数分解出个位,十位,百位。 

【程序4】 
题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。 
程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: 
(1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。 
(2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。 
(3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。 

【程序5】 
题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。 
1.程序分析:(a>b)?a:b这是条件运算符的基本例子。 

【程序6】 
题目:输入两个正整数m和n,求其最大公约数和最小公倍数。 
1.程序分析:利用辗除法。 

【程序7】 
题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。 
1.程序分析:利用while语句,条件为输入的字符不为'/n'. 

【程序8】 
题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加有键盘控制。
1.程序分析:关键是计算出每一项的值。 

【程序9】 
题目:一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程 找出1000以内的所有完数。 

【程序10】 
题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高? 

【程序11】 
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 
1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。 

【程序12】 
题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按 10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?
1.程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。 

【程序13】 
题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少? 
1.程序分析:在10万以内判断,先将该数加上100后再开方,再将该数加上268后再开方,如果开方后的结果满足如下条件,即是结果。请看具体分析: 

【程序14】 
题目:输入某年某月某日,判断这一天是这一年的第几天? 
1.程序分析:以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天,特殊情况,闰年且输入月份大于3时需考虑多加一天。 

【程序15】 
题目:输入三个整数x,y,z,请把这三个数由小到大输出。 
1.程序分析:我们想办法把最小的数放到x上,先将x与y进行比较,如果x>y则将x与y的值进行交换,然后再用x与z进行比较,如果x>z则将x与z的值进行交换,这样能使x最小。

【程序16】 
题目:输出9*9口诀。 
1.程序分析:分行与列考虑,共9行9列,i控制行,j控制列。 

【程序17】 
题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下 的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。
1.程序分析:采取逆向思维的方法,从后往前推断。 

【程序18】 
题目:两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
1.程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。 

【程序19】 
题目:打印出如下图案(菱形) 

*** 
****** 
******** 
****** 
*** 

1.程序分析:先把图形分成两部分来看待,前四行一个规律,后三行一个规律,利用双重 for循环,第一层控制行,第二层控制列。 

【程序20】 
题目:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。 
1.程序分析:请抓住分子与分母的变化规律。 

【程序21】 
题目:求1+2!+3!+...+20!的和 
1.程序分析:此程序只是把累加变成了累乘。 

【程序22】 
题目:利用递归方法求5!。 
1.程序分析:递归公式:fn=fn_1*4! 

【程序23】 
题目:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?
1.程序分析:利用递归的方法,递归分为回推和递推两个阶段。要想知道第五个人岁数,需知道第四人的岁数,依次类推,推到第一人(10岁),再往回推。 

【程序24】 
题目:给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。 

【程序25】 
题目:一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。 

【程序26】 
题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二个字母。 
1.程序分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母。 

【程序27】 
题目:求100之内的素数 

【程序28】 
题目:对10个数进行排序 
1.程序分析:可以利用选择法,即从后9个比较过程中,选择一个最小的与第一个元素交换, 下次类推,即用第二个元素与后8个进行比较,并进行交换。 

【程序29】 
题目:求一个3*3矩阵对角线元素之和 
1.程序分析:利用双重for循环控制输入二维数组,再将a[i][i]累加后输出。 

【程序30】 
题目:有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。 
1. 程序分析:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后此元素之后的数,依次后移一个位置。 

【程序31】 
题目:将一个数组逆序输出。 
1.程序分析:用第一个与最后一个交换。 

【程序32】 
题目:取一个整数a从右端开始的4~7位。 
程序分析:可以这样考虑: 
(1)先使a右移4位。 
(2)设置一个低4位全为1,其余全为0的数。可用~(~0<<4) 
(3)将上面二者进行&运算。 

【程序33】 
题目:打印出杨辉三角形(要求打印出10行如下图) 
1.程序分析: 

1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 

【程序34】 
题目:输入3个数a,b,c,按大小顺序输出。 
1.程序分析:利用指针方法。 

【程序35】 
题目:输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。 

【程序36】 
题目:有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数 

【程序37】 
题目:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。 

【程序38】 
题目:写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度。 

【程序39】 
题目:编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n(利用指针函数) 

【程序40】 
题目:字符串排序。 

【程序41】 
题目:海滩上有一堆桃子,五只猴子来分。第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海中,拿走了一份。第二只猴子把剩下的桃子又平均分成五份,又多了一个,它同样把多的一个扔入海中,拿走了一份,第三、第四、第五只猴子都是这样做的,问海滩上原来最少有多少个桃子?

【程序42】 
题目:809*??=800*??+9*??+1 其中??代表的两位数,8*??的结果为两位数,9*??的结果为3位数。求??代表的两位数,及809*??后的结果。

【程序43】 
题目:求0—7所能组成的奇数个数。 

【程序44】 
题目:一个偶数总能表示为两个素数之和。 

【程序45】 
题目:判断一个素数能被几个9整除 

【程序46】 
题目:两个字符串连接程序 

【程序47】 
题目:读取7个数(1—50)的整数值,每读取一个值,程序