﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-毛里求斯的化石博物馆-文章分类-java&amp;js相关</title><link>http://www.blogjava.net/dudubird/category/15776.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:35:39 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:35:39 GMT</pubDate><ttl>60</ttl><item><title>JCS(Java Caching System)简介以及相关文档(cjsdn)</title><link>http://www.blogjava.net/dudubird/articles/72770.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 29 Sep 2006 04:13:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72770.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72770.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72770.html</trackback:ping><description><![CDATA[
		<div style="FONT-SIZE: 12px">
				<p align="center">JCS(Java Caching System)简介以及相关文档(cjsdn)</p>
				<p>概述<br />JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架，以实现高性能的应用。<br />对于一些需要频繁访问而每访问一次都非常消耗资源的对象，可以临时存放在缓冲区中，这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。<br />JCS的详细说明在 <a href="http://jakarta.apache.org/turbine/jcs/" target="_blank"><font color="#002c99">http://jakarta.apache.org/turbine/jcs/</font></a></p>
				<p>JCS的特性<br />JCS除了简单的将对象缓冲在内存中以外，还具有几个特性，以适应企业级缓冲系统的需要。这些特性包括时间过期、索引式硬盘缓冲、并行式的分布缓冲等。<br />内存缓冲<br />JCS现在支持两种内存缓冲算法LRU和MRU。通常都是使用LRU算法。<br />org.apache.stratum.jcs.engine.memory.lru.LRUMemoryCache<br />使用内存缓冲区需要定义缓冲区大小，当超过缓冲区限制时，会将缓冲内容抛弃掉。如果有配硬盘缓冲，则将挤出来的缓冲内容写入硬盘缓冲区。</p>
				<p>时间过期<br />JCS对于缓冲的对象，可以设定缓冲过期时间，一个对象在缓冲区中停留的时间超过这个时间，就会被认为是“不新鲜”而被放弃。</p>
				<p>索引式硬盘缓冲<br />一方面，为了避免缓冲区过大，撑爆虚拟机的内存，另一方面又希望能够缓冲更多的对象，JCS可以将超出缓冲区大小的对象缓存到硬盘上。配置上也比较方便，只需要指定缓冲临时文件的存放目录位置。硬盘缓冲将缓冲对象的内容写到文件上，但是将访问索引保存在内存中，因此也能够达到尽可能高的访问效率。</p>
				<p>并行式的分布缓冲(Lateral)<br />通常，将对象缓冲在内存中，一方面提高了应用的性能，而另一方面却使得应用不可以分布式发布。因为假设一个应用配置在两台服务器上并行运行，而两台服务器单独缓冲，则很容易导致两个缓冲区内容出现版本上的不一致而出错。一个机器上修改了数据，这个动作会影响到本地内存缓冲区和数据库服务器，但是却不会通知到另一台服务器，导致另一台上缓冲的数据实际上已经无效了。<br />并行式的分布缓冲就是解决这个问题。可以通过配置，将几台服务器配成一个缓冲组，组内每台服务器上有数据更新，会横向将更新的内容通过TCP/IP协议传输到其他服务器的缓冲层，这样就可以保证不会出现上述情况。这个的缺点是如果组内的并行的服务器数量增大后，组内的数据传输量将会迅速上升。这种方案适合并行服务器的数量比较少的情况。</p>
				<p>Client/Server式的缓冲(Remote)<br />客户/服务端式的缓冲集群。这种方式支持一个主服务器和最高达到256个客户端。客户端的缓冲层会尝试连接主服务器，如果连接成功，就会在主服务器上注册。每个客户端有数据更新，就会通知到主服务器，主服务器会将更新通知到除消息来源的客户端以外的所有的客户端。<br />每个客户端可以配置超过一个服务器，第一个服务器是主服务器，如果与第一个服务器连接失败，客户端会尝试与备用的服务器连接，如果连接成功，就会通过备用服务器与其他客户端对话，同时会定期继续尝试与主服务器取得连接。如果备用服务器也连接失败，就会按照配置顺序尝试与下一个备用服务器连接。<br />这种方式下，更新通知是一种轻量级的，一个机器上的数据更新，不会把整个数据传输出去，而只是通知一个ID，当远程的其他机器收到更新通知后，就会把对应ID的缓冲对象从本地的内存缓冲区中移除，以保证不会在缓冲区内出现错误数据。<br />这种构造需要分别配置客户端和服务器，配置比较麻烦。<br /></p>
				<p>配置方法<br />JCS的好处之一，就是应用在开发的时候，可以不用去构思底层的缓冲配置构架。同一个应用，只需要修改配置，就可以改变缓冲构架，不需要修改应用的源代码。配置方法也比较简单，就是修改配置文件cache.ccf。这个文件放置在WEB-INF/classes目录下。配置格式类似log4j的配置文件格式。下面介绍一下使用各种缓冲结构的配置方法。</p>
				<p>内存缓冲<br />#WEB-INF/classes/cache.ccf(以下内容不要换行)<br />jcs.default=<br />jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes<br />jcs.default.cacheattributes.MaxObjects=1000<br />jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache<br />上面配置了默认缓冲属性。一个应用中，由于对象类型的不同，可能会使用多个缓冲区，每个缓冲区都会有一个名字，如果在配置文件中没有指明特定的缓冲区的属性，所有的缓冲区都会根据默认属性来构建。上面的内容，指明缓冲区的大小为存放1000个对象，内存缓冲器使用LRUMemoryCache对象。可选的还有MRUMemoryCache，应该可以自定义新的内存缓冲区。1000个缓冲对象这个容量，是指每个缓冲区都缓冲1000个，而不是指所有缓冲区总容量。以上配置，就可以让应用运行起来。</p>
				<p>时间过期<br />如果需要引入时间过期机制，则需要加上<br />jcs.default.cacheattributes.cacheattributes.UseMemoryShrinker=true<br />jcs.default.cacheattributes.cacheattributes.MaxMemoryIdleTimeSeconds=3600<br />jcs.default.cacheattributes.cacheattributes.ShrinkerIntervalSeconds=60<br />这里指明对象超过3600秒则过期，每隔60秒检查一次。</p>
				<p>
						<br />索引式硬盘缓冲<br />索引式硬盘缓冲是辅助缓冲的一种，使用时需要做以下事情<br />#定义一个硬盘缓冲区产生器(Factory)，取名为DC<br />jcs.auxiliary.DC=org.apache.stratum.jcs.auxiliary.disk.indexed.IndexedDiskCacheFactory<br />jcs.auxiliary.DC.attributes=org.apache.stratum.jcs.auxiliary.disk.indexed.IndexedDiskCacheAttributes<br />jcs.auxiliary.DC.attributes.DiskPath=g:/dev/jakarta-turbine-stratum/raf<br />#这里其实就是指明了缓冲文件存放到那里去。<br />然后，做以下修改<br />jcs.default=DC<br />这样，所有未特别指定属性的缓冲区都会自己使用一个硬盘缓冲区，缓冲文件会以缓冲区的名字来命名。存放在指定的目录下。</p>
				<p>
						<br />横向式的并行缓冲<br />并行式的配置如下<br />jcs.auxiliary.LTCP=org.apache.jcs.auxiliary.lateral.LateralCacheFactory<br />jcs.auxiliary.LTCP.attributes=org.apache.jcs.auxiliary.lateral.LateralCacheAttributes<br />jcs.auxiliary.LTCP.attributes.TransmissionTypeName=TCP<br />jcs.auxiliary.LTCP.attributes.TcpServers=192.168.10.129:1121,192.168.10.222:1121<br />jcs.auxiliary.LTCP.attributes.TcpListenerPort=1121<br />jcs.auxiliary.LTCP.attributes.PutOnlyMode=false<br />这里的配置是在41,129,221三台机器上实现并行缓冲的。<br />大家都在1121端口上监听，同时与另外两台机器连接。如果连接失败，就会等待一个时间后再连接一次，直到连接成功为止。三台机器中任意一台的缓冲区发生更新，比如put和remove动作，就会把更新传递给另外两台。</p>
				<p>
						<br />单独指明某个缓冲区的属性<br />如果，针对某个缓冲区，比如叫做TestCache1，需要单独配置属性，可以如下配置。<br />jcs.region.testCache1=DC,LTCP<br />jcs.region.testCache1.cacheattributes=org.apache.stratum.jcs.engine.CompositeCacheAttributes<br />jcs.region.testCache1.cacheattributes.MaxObjects=1000<br />jcs.region.testCache1.cacheattributes.MemoryCacheName=org.apache.stratum.jcs.engine.memory.lru.LRUMemoryCache<br />jcs.region.testCache1.cacheattributes.UseMemoryShrinker=true<br />jcs.region.testCache1.cacheattributes.MaxMemoryIdleTimeSeconds=3600<br />jcs.region.testCache1.cacheattributes.ShrinkerIntervalSeconds=60<br /></p>
				<p>system.GroupIdCache<br />这个概念我也不是很清楚。不过JCS文档中指出配置以下内容会比较好。<br />jcs.system.groupIdCache=DC<br />jcs.system.groupIdCache.cacheattributes=org.apache.stratum.jcs.engine.CompositeCacheAttributes<br />jcs.system.groupIdCache.cacheattributes.MaxObjects=10000</p>
				<p>jcs.system.groupIdCache.cacheattributes.MemoryCacheName=org.apache.stratum.jcs.engine.memory.lru.LRUMemoryCache<br />这可能是JCS自己的组管理体系上的缓冲区。</p>
				<p>
						<br />Client/Server式的缓冲(Remote)<br />这种构架需要单独配置客户端和服务端，如果要研究，可以查看 <a href="http://jakarta.apache.org/turbine/jcs/RemoteAuxCache.html" target="_blank"><font color="#002c99">http://jakarta.apache.org/turbine/jcs/RemoteAuxCache.html</font></a></p>
		</div>
<img src ="http://www.blogjava.net/dudubird/aggbug/72770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-29 12:13 <a href="http://www.blogjava.net/dudubird/articles/72770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几个著名java开源缓存系统的介绍</title><link>http://www.blogjava.net/dudubird/articles/72769.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 29 Sep 2006 04:12:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72769.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72769.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72769.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72769.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72769.html</trackback:ping><description><![CDATA[
		<div style="FONT-SIZE: 12px">
				<h3 align="center">几个著名java开源缓存系统的介绍 </h3>
				<p align="center">作者：不详 　来源：360doc 　 <font color="red">http://www.csai.cn</font> 2005年09月08日</p>
				<p>　<strong>　OSCache </strong><br />　<strong>　</strong>OSCache是个一个广泛采用的高性能的J2EE缓存框架，OSCache能用于任何Java应用程序的普通的缓存解决方案。 <br />　<strong>　</strong>OSCache有以下特点： <br />　<strong>　</strong>缓存任何对象，你可以不受限制的缓存部分jsp页面或HTTP请求，任何java对象都可以缓存。 <br />　<strong>　</strong>拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。 <br />　<strong>　</strong>永久缓存--缓存能随意的写入硬盘，因此允许昂贵的创建（expensive-to-create）数据来保持缓存，甚至能让应用重启。 <br />　<strong>　</strong>支持集群--集群缓存数据能被单个的进行参数配置，不需要修改代码。 <br />缓存记录的过期--你可以有最大限度的控制缓存对象的过期，包括可插入式的刷新策略（如果默认性能不需要时）。 <br />　<strong>　</strong>官方网站 <a href="http://www.opensymphony.com/oscache/" target="_blank">http://www.opensymphony.com/oscache/ </a></p>
				<p>　<strong>　Java Caching System </strong><br />　<strong>　</strong>JSC(Java Caching System)是一个用分布式的缓存系统，是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。 <br />　<strong>　</strong>JCS和其他缓存系统一样，也是一个用于高速读取，低速写入的应用程序。 <br />　<strong>　</strong>动态内容和报表系统能够获得更好的性能。 <br />　<strong>　</strong>如果一个网站，有重复的网站结构，使用间歇性更新方式的数据库（而不是连续不断的更新数据库），被重复搜索出相同结果的，就能够通过执行缓存方式改进其性能和伸缩性。 <br />　<strong>　</strong>官方网站 <a href="http://jakarta.apache.org/turbine/jcs/" target="_blank">http://jakarta.apache.org/turbine/jcs/ </a></p>
				<p>　<strong>　EHCache </strong><br />　<strong>　</strong>EHCache 是一个纯java的在进程中的缓存，它具有以下特性：快速，简单，为Hibernate2.1充当可插入的缓存，最小的依赖性，全面的文档和测试。 </p>
				<p>　<strong>　</strong>官方网站 <a href="http://ehcache.sourceforge.net/" target="_blank">http://ehcache.sourceforge.net/ </a></p>
				<p>　<strong>　JCache </strong><br />　<strong>　</strong>JCache是个开源程序，正在努力成为JSR-107开源规范，JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。 <br />　<strong>　</strong>官方网站 <a href="http://jcache.sourceforge.net/" target="_blank">http://jcache.sourceforge.net/ </a></p>
				<p>
						<strong>　<strong>　</strong>ShiftOne </strong>
						<br />　<strong>　</strong>ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib，就像一个轻量级的配置缓存工作状态的框架。 <br />　<strong>　</strong>官方网站 <a href="http://jocache.sourceforge.net/" target="_blank">http://jocache.sourceforge.net/</a></p>
				<p>　<strong>　SwarmCache </strong><br />　<strong>　</strong>SwarmCache是一个简单且有效的分布式缓存，它使用IP multicast与同一个局域网的其他主机进行通讯，是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。 <br />　<strong>　</strong>SwarmCache使用JavaGroups来管理从属关系和分布式缓存的通讯。 <br />　<strong>　</strong>官方网站 <a href="http://swarmcache.sourceforge.net/" target="_blank">http://swarmcache.sourceforge.net </a></p>
				<p>　<strong>　TreeCache / JBossCache </strong><br />　<strong>　</strong>JBossCache是一个复制的事务处理缓存，它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制，让你轻松进行JBoss服务器之间的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务，当然，它也能独立运行。 <br />　<strong>　</strong>JBossCache包括两个模块：TreeCache和TreeCacheAOP。 <br />　<strong>　</strong>TreeCache --是一个树形结构复制的事务处理缓存。 <br />　<strong>　</strong>TreeCacheAOP --是一个“面向对象”缓存，它使用AOP来动态管理POJO(Plain Old Java Objects) <br />　<strong>　</strong>注：AOP是OOP的延续，是Aspect Oriented Programming的缩写，意思是面向方面编程。 <br />　<strong>　</strong>官方网站 <a href="http://www.jboss.org/products/jbosscache" target="_blank">http://www.jboss.org/products/jbosscache </a></p>
				<p>　<strong>　WhirlyCache </strong><br />　<strong>　</strong>Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度，否则就必须通过查询数据库或其他代价较高的处理程序来建立。 <br />官方网站 <a href="https://whirlycache.dev.java.net/" target="_blank">https://whirlycache.dev.java.net/ </a><br /><br /></p>
		</div>
<img src ="http://www.blogjava.net/dudubird/aggbug/72769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-29 12:12 <a href="http://www.blogjava.net/dudubird/articles/72769.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何用java操作excel（二）（转）</title><link>http://www.blogjava.net/dudubird/articles/72762.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 29 Sep 2006 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72762.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72762.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72762.html</trackback:ping><description><![CDATA[
		<div class="quote">
				<p>以下是同事写的一个jxl的工具类<br /><br />package test.jxl.util;</p>
				<p>import java.io.IOException;<br />import java.util.Collection;<br />import java.util.List;<br />import java.util.Map;</p>
				<p>import jxl.Workbook;<br />import jxl.write.Blank;<br />import jxl.write.DateTime;<br />import jxl.write.Label;<br />import jxl.write.WritableCell;<br />import jxl.write.WritableSheet;<br />import jxl.write.WritableWorkbook;<br />import jxl.write.WriteException;<br />import jxl.write.biff.RowsExceededException;</p>
				<p>public class ConvinWriter {<br /><br />/**<br />* 写入一行<br />* @param sheet<br />* @param array<br />* @param row<br />* @return the number of cols written<br />*/<br />public static int writeRow(WritableSheet sheet, Object[] array, int row) {<br />int colsWritten = 0;<br />int col = 0;<br />for (Object value : array) {<br />colsWritten += writeObject(sheet, value, col ++, row) ? 1 : 0;<br />}<br />return colsWritten;<br />}<br /><br />/**<br />* 写入一行<br />* @param sheet<br />* @param array<br />* @param beginCol<br />* @param endCol<br />* @param row<br />* @return the number of cols written<br />*/<br />public static int writeRow(WritableSheet sheet, Object[] array, int beginCol, int endCol, int row) {<br />int colsWritten = 0;<br />int col = beginCol;<br />for (Object value : array) {<br />if (col == endCol) {<br />break;<br />}<br />colsWritten += writeObject(sheet, value, col ++, row) ? 1 : 0;<br />}<br />return colsWritten;<br />}<br /><br />/**<br />* 写入一行<br />* @param sheet 表单<br />* @param list 数据<br />* @param row 所在行<br />* @return the number of cols written<br />*/<br />public static int writeRow(WritableSheet sheet, Collection&lt;Object&gt; list, int row) {<br />int colsWritten = 0;<br />int col = 0;<br />for (Object value : list) {<br />colsWritten += writeObject(sheet, value, col ++, row) ? 1 : 0;<br />}<br />return colsWritten;<br />}<br /><br />/**<br />* 写入一行<br />* @param sheet<br />* @param list<br />* @param beginCol &gt;=0, inclusive<br />* @param endCol &gt;0, exclusive<br />* @param row<br />* @return the number of cols written<br />*/<br />public static int writeRow(WritableSheet sheet, Collection&lt;Object&gt; list, int beginCol, int endCol, int row) {<br />int colsWritten = 0;<br />int col = beginCol;<br />for (Object value : list) {<br />if (col == endCol) {<br />break;<br />}<br />colsWritten += writeObject(sheet, value, col ++, row) ? 1 : 0;<br />}<br />return colsWritten;<br />}<br /><br />/**<br />* 向Sheet写入List的数据<br />* @param sheet<br />* @param keyArray<br />* @param list<br />* @param beginRow<br />* @return the number of rows written<br />*/<br />public static int writeMapListOfStringKey(WritableSheet sheet, String[] keyArray, Collection&lt;Map&lt;String, Object&gt;&gt; list, int beginRow){<br />int count = 0;<br />int rowCount = beginRow;<br />for (Map&lt;String, Object&gt; element : list) {<br />boolean bl = writeStringKeyMap(sheet, keyArray, element, rowCount++);<br />if(bl)count++;<br />}<br />return count;<br />}<br /><br />/**<br />* 写入一个Map的数据到一行<br />* @param sheet<br />* @param keyArray<br />* @param map<br />* @param row<br />* @return<br />*/<br />public static boolean writeStringKeyMap(WritableSheet sheet, String[] keyArray, Map&lt;String,Object&gt; map, int row){<br />int col = 0;<br />for (String key : keyArray) {<br />key = key.trim();<br />Object value = map.get(key);<br />writeObject(sheet, value, col ++, row);<br />}<br />return false;<br />}<br /><br />/**<br />* 写入一个对象<br />* @param sheet<br />* @param value<br />* @param col<br />* @param row<br />*/<br />public static boolean writeObject(WritableSheet sheet, Object value, int col, int row) {<br />if (value == null) {<br />return addCell(sheet, new Blank(col, row));<br />} else if (value instanceof Number) {<br />Number new_name = (Number) value;<br />return addCell(sheet, new jxl.write.Number(col, row, new_name.doubleValue())); <br />} else if (value instanceof Boolean) {<br />Boolean bool = (Boolean) value;<br />return addCell(sheet, new jxl.write.Boolean(col, row, bool.booleanValue()));<br />} else if (value instanceof java.util.Date) {<br />java.util.Date new_name = (java.util.Date) value;<br />return addCell(sheet, new DateTime(col, row, new_name));<br />} else {<br />return addCell(sheet, new Label(col, row, value.toString()));<br />}<br />}<br /><br />private static boolean addCell(WritableSheet sheet, WritableCell cell) {<br />try {<br />sheet.addCell(cell);<br />} catch (RowsExceededException e) {<br />e.printStackTrace();<br />return false;<br />} catch (WriteException e) {<br />e.printStackTrace();<br />return false;<br />}<br />return true;<br />}<br /><br />/**<br />* 将一个List的内容写到一个新的Sheet<br />* @param path 文件路径<br />* @param titleArray 行题头<br />* @param keyArray 行题头 Key<br />* @param content<br />* @param sheetName<br />* @return boolean<br />*/<br />public static boolean writeInNewSheet (String path, String[] titleArray, String[] keyArray, Collection&lt;Map&lt;String, Object&gt;&gt; content, String sheetName) {<br />java.io.File file = new java.io.File(path);<br />return writeInNewSheet (file, titleArray, keyArray, content, sheetName);<br />}<br /><br />/**<br />* create file<br />* @param file<br />* @return<br />*/<br />private static boolean createFile(java.io.File file) {<br />if (!file.exists()) {<br />try {<br />if (file.getParentFile().mkdirs()) {<br />if (file.createNewFile()) {<br />// do nothing<br />} else {<br />return false;<br />}<br />} else {<br />return false;<br />}<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />return false;<br />}<br />}<br />return true;<br />}<br /><br />/**<br />* get the workbook<br />* @param file<br />* @return<br />*/<br />public static Workbook getWorkBook(java.io.File file) {<br />jxl.Workbook exists = null;<br />if (createFile(file)) {<br />try {<br />exists = jxl.Workbook.getWorkbook(file);<br />} catch (jxl.read.biff.BiffException e) {<br />e.printStackTrace();<br />return null;<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />return null;<br />}<br />} else {<br />return null;<br />}<br />return exists;<br />}<br /><br />/**<br />* 创建workbook<br />* @param file<br />* @return writableworkbook, or null when failed<br />*/<br />public static WritableWorkbook createWorkbook (java.io.File file) {<br />jxl.Workbook exists = getWorkBook(file);<br />jxl.write.WritableWorkbook workbook = null;<br />try {<br />if (exists != null) {<br />workbook = jxl.Workbook.createWorkbook(file, exists);<br />} else {<br />workbook = jxl.Workbook.createWorkbook(file);<br />}<br />} catch (IOException e) {<br />e.printStackTrace();<br />return null;<br />}<br />return workbook;<br />}<br /><br />/**<br />* 将一个List的内容写到一个新的Sheet<br />* @param file 文件<br />* @param titleArray 行题头<br />* @param keyArray 行题头 Key<br />* @param content<br />* @param sheetName<br />*/<br />public static boolean writeInNewSheet (java.io.File file, String[] titleArray, String[] keyArray, Collection&lt;Map&lt;String, Object&gt;&gt; content, String sheetName) {<br />jxl.write.WritableWorkbook wookbook = createWorkbook(file);<br />int sheetNum = wookbook.getNumberOfSheets();<br />try {<br />WritableSheet sheet = wookbook.createSheet(sheetName, sheetNum);<br />ConvinWriter.writeRow(sheet, titleArray, 0);<br />ConvinWriter.writeMapListOfStringKey(sheet, keyArray, content, 1);<br />wookbook.write();<br />} catch (IOException e) {<br />e.printStackTrace();<br />return false;<br />} finally {<br />try {<br />wookbook.close();<br />} catch (WriteException e) {<br />e.printStackTrace();<br />return false;<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />return false;<br />}<br />}<br />return true;<br />}<br /><br />/**<br />* @param args<br />*/<br />public static void main(String[] args) {<br /><br />List&lt;Object&gt; list = new java.util.ArrayList&lt;Object&gt;();<br />list.add(null);<br />list.add("String");<br />list.add(new java.util.Date());<br />list.add(12345);<br />list.add(false);<br />list.add(new ConvinWriter());<br /><br />List &lt;Map&lt;String, Object&gt;&gt; mapList = new java.util.ArrayList&lt;Map&lt;String, Object&gt;&gt;();<br />String[] keyArray = new String [] {<br />"Blank", "String", "DateTime", "Number", "Boolean", "Object"<br />};<br /><br />for (int i = 0; i &lt; 3; i ++) {<br />Map&lt;String, Object&gt; map = new java.util.HashMap&lt;String, Object&gt;(keyArray.length);<br />if (i == 0)map.put("Blank", null);<br />map.put("String", "String " + i);<br />map.put("DateTime", new java.util.Date());<br />map.put("Number", i);<br />map.put("Boolean", i % 2 == 0);<br />map.put("Object", map);<br />mapList.add(map);<br />}<br />// FIXME<br />java.io.File file = new java.io.File("E:/tempJxlFile.xls");<br />jxl.Workbook exists = null;<br />if (file.exists()) {<br />try {<br />exists = jxl.Workbook.getWorkbook(file);<br />} catch (jxl.read.biff.BiffException e) {<br />e.printStackTrace();<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />}<br />} else {<br />try {<br />file.createNewFile();<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />}<br />}<br /><br />jxl.write.WritableWorkbook wookbook = null;<br />try {<br />if (exists != null) {<br />wookbook = jxl.Workbook.createWorkbook(file, exists);<br />} else {<br />wookbook = jxl.Workbook.createWorkbook(file);<br />}<br />int sheetNum = wookbook.getNumberOfSheets();<br />WritableSheet sheet = wookbook.createSheet("testSheet" + (sheetNum + 1), sheetNum);<br />ConvinWriter.writeRow(sheet, keyArray, 0);<br />ConvinWriter.writeRow(sheet, list, 1);<br />ConvinWriter.writeMapListOfStringKey(sheet, keyArray, mapList, 2);<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />} finally {<br />try {<br />wookbook.write();<br />wookbook.close();<br />} catch (WriteException e) {<br />e.printStackTrace();<br />} catch (java.io.IOException e) {<br />e.printStackTrace();<br />}<br />}<br />}<br />}<br /></p>
		</div>
<img src ="http://www.blogjava.net/dudubird/aggbug/72762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-29 11:44 <a href="http://www.blogjava.net/dudubird/articles/72762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何用java操作excel（一）（转）</title><link>http://www.blogjava.net/dudubird/articles/72759.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 29 Sep 2006 03:42:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72759.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72759.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72759.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72759.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72759.html</trackback:ping><description><![CDATA[
		<blockquote>
				<p align="left">使用Windows操作系统的朋友对Excel（电子表格）一定不会陌生，但是要使用Java语言来操纵Excel文件并不是一件容易的事。在<br />Web应用日益盛行的今天，通过Web来操作Excel文件的需求越来越强烈，目前较为流行的操作是在JSP或Servlet 中创建一个CSV <br />（comma separated values）文件，并将这个文件以MIME，text/csv类型返回给浏览器，接着浏览器调用Excel并且显示CSV文件。这样<br />只是说可以访问到Excel文件，但是还不能真正的操纵Excel文件，本文将给大家一个惊喜，向大家介绍一个开放源码项目，Java <br />Excel API，使用它大家就可以方便地操纵Excel文件了。<br /></p>
		</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<a name="1">
						<span class="atitle">
								<font face="Arial" size="4">JAVA EXCEL API简介</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" size="4">
				</font>
		</p>
		<p>Java Excel是一开放源码项目，通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。使用该API非<br />Windows操作系统也可以通过纯Java应用来处理Excel数据表。因为是使用Java编写的，所以我们在Web应用中可以通过JSP、Servlet来调用API实<br />现对Excel数据表的访问。</p>
		<p>现在发布的稳定版本是V2.0，提供以下功能：</p>
		<ul>
				<li>从Excel 95、97、2000等格式的文件中读取数据； 
</li>
				<li>读取Excel公式（可以读取Excel 97以后的公式）； 
</li>
				<li>生成Excel数据表（格式为Excel 97）； 
</li>
				<li>支持字体、数字、日期的格式化； 
</li>
				<li>支持单元格的阴影操作，以及颜色操作； 
</li>
				<li>修改已经存在的数据表； </li>
		</ul>
		<p>现在还不支持以下功能，但不久就会提供了：</p>
		<ol>
				<li>不能够读取图表信息； 
</li>
				<li>可以读，但是不能生成公式，任何类型公式最后的计算值都可以读出； </li>
		</ol>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center"> <br /></td>
																<td valign="top" align="right">
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="2">
						<span class="atitle">
								<font face="Arial" size="4">应用示例</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" size="4">
				</font>
		</p>
		<a name="N1006F">
				<span class="smalltitle">
						<strong>
								<font face="Arial">1 从Excel文件读取数据表</font>
						</strong>
				</span>
		</a>
		<p>
		</p>
		<p>
				<strong>
						<font face="Arial">
						</font>
				</strong>
		</p>
		<p>Java Excel API既可以从本地文件系统的一个文件(.xls)，也可以从输入流中读取Excel数据表。读取Excel数据表的第一步是创建Workbook(术语：<br />工作薄)，下面的代码片段举例说明了应该如何操作：(完整代码见ExcelReading.java)</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">import java.io.*;
import jxl.*;
… … … …
try
{
//构建Workbook对象, 只读Workbook对象
	//直接从本地文件创建Workbook
//从输入流创建Workbook
    InputStream is = new FileInputStream(sourcefile);
    jxl.Workbook rwb = Workbook.getWorkbook(is);
}
catch (Exception e)
{
	e.printStackTrace();
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>一旦创建了Workbook，我们就可以通过它来访问Excel Sheet(术语：工作表)。参考下面的代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//获取第一张Sheet表
Sheet rs = rwb.getSheet(0);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>我们既可能通过Sheet的名称来访问它，也可以通过下标来访问它。如果通过下标来访问的话，要注意的一点是下标从0开始，就像数组一样。<br /></p>
		<p>一旦得到了Sheet，我们就可以通过它来访问Excel Cell(术语：单元格)。参考下面的代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//获取第一行，第一列的值
Cell c00 = rs.getCell(0, 0);
String strc00 = c00.getContents();

//获取第一行，第二列的值
Cell c10 = rs.getCell(1, 0);
String strc10 = c10.getContents();

//获取第二行，第二列的值
Cell c11 = rs.getCell(1, 1);
String strc11 = c11.getContents();

System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType());
System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType());
System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType());
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果仅仅是取得Cell的值，我们可以方便地通过getContents()方法，它可以将任何类型的Cell值都作为一个字符串返回。示例代码中Cell(0, 0)是文<br />本型，Cell(1, 0)是数字型，Cell(1,1)是日期型，通过getContents()，三种类型的返回值都是字符型。</p>
		<p>如果有需要知道Cell内容的确切类型，API也提供了一系列的方法。参考下面的代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">String strc00 = null;
double strc10 = 0.00;
Date strc11 = null;

Cell c00 = rs.getCell(0, 0);
Cell c10 = rs.getCell(1, 0);
Cell c11 = rs.getCell(1, 1);

if(c00.getType() == CellType.LABEL)
{
LabelCell labelc00 = (LabelCell)c00;
strc00 = labelc00.getString();
}
if(c10.getType() == CellType.NUMBER)
{
	NmberCell numc10 = (NumberCell)c10;
strc10 = numc10.getValue();
}
if(c11.getType() == CellType.DATE)
{
DateCell datec11 = (DateCell)c11;
strc11 = datec11.getDate();
}

System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType());
System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType());
System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType());
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在得到Cell对象后，通过getType()方法可以获得该单元格的类型，然后与API提供的基本类型相匹配，强制转换成相应的类型，最后调用相应的<br />取值方法getXXX()，就可以得到确定类型的值。API提供了以下基本类型，与Excel的数据格式相对应，如下图所示：</p>
		<br />
		<img height="218" alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-javaExcel/image001.jpg" width="365" />
		<br />
		<p>每种类型的具体意义，请参见Java Excel API Document。</p>
		<p>当你完成对Excel电子表格数据的处理后，一定要使用close()方法来关闭先前创建的对象，以释放读取数据表的过程中所占用的内存空间，在读<br />取大量数据时显得尤为重要。参考如下代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//操作完成时，关闭对象，释放占用的内存空间
rwb.close();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Java Excel API提供了许多访问Excel数据表的方法，在这里我只简要地介绍几个常用的方法，其它的方法请参考附录中的Java Excel <br />APIdocument。</p>
		<p>
				<b>Workbook类提供的方法</b>
		</p>
		<p>1. int getNumberOfSheets() <br />获得工作薄（Workbook）中工作表（Sheet）的个数，示例： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
int sheets = rwb.getNumberOfSheets();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>2. Sheet[] getSheets() <br />返回工作薄（Workbook）中工作表（Sheet）对象数组，示例： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
Sheet[] sheets = rwb.getSheets();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>3. String getVersion() <br />返回正在使用的API的版本号，好像是没什么太大的作用。 </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
String apiVersion = rwb.getVersion();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>Sheet接口提供的方法</b>
		</p>
		<p>1) String getName() <br />获取Sheet的名称，示例： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
String sheetName = rs.getName();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>2) int getColumns() <br />获取Sheet表中所包含的总列数，示例： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
int rsColumns = rs.getColumns();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>3) Cell[] getColumn(int column) <br />获取某一列的所有单元格，返回的是单元格对象数组，示例： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell[] cell = rs.getColumn(0);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>4) int getRows() <br />获取Sheet表中所包含的总行数，示例： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
int rsRows = rs.getRows();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>5) Cell[] getRow(int row) <br />获取某一行的所有单元格，返回的是单元格对象数组，示例子： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell[] cell = rs.getRow(0);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>6) Cell getCell(int column, int row) <br />获取指定单元格的对象引用，需要注意的是它的两个参数，第一个是列数，第二个是行数，这与通常的行、列组合有些不同。 </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell cell = rs.getCell(0, 0);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N10114">
						<span class="smalltitle">
								<strong>
										<font face="Arial">2 生成新的Excel工作薄</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
						<font face="Arial">
						</font>
				</strong>
		</p>
		<p>下面的代码主要是向大家介绍如何生成简单的Excel工作表，在这里单元格的内容是不带任何修饰的(如：字体，颜色等等)，所有的内容都作为<br />字符串写入。(完整代码见ExcelWriting.java)</p>
		<p>与读取Excel工作表相似，首先要使用Workbook类的工厂方法创建一个可写入的工作薄(Workbook)对象，这里要注意的是，只能通过API提供的<br />工厂方法来创建Workbook，而不能使用WritableWorkbook的构造函数，因为类WritableWorkbook的构造函数为protected类型。示例代码片段如<br />下：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">import java.io.*;
import jxl.*;
import jxl.write.*;
… … … …
try
{
//构建Workbook对象, 只读Workbook对象
//Method 1：创建可写入的Excel工作薄
    jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile));

//Method 2：将WritableWorkbook直接写入到输出流
/*
    OutputStream os = new FileOutputStream(targetfile);
    jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os);
*/
}
catch (Exception e)
{
	e.printStackTrace();
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>API提供了两种方式来处理可写入的输出流，一种是直接生成本地文件，如果文件名不带全路径的话，缺省的文件会定位在当前目录，如果文<br />件名带有全路径的话，则生成的Excel文件则会定位在相应的目录；另外一种是将Excel对象直接写入到输出流，例如：用户通过浏览器来访问<br />Web服务器，如果HTTP头设置正确的话，浏览器自动调用客户端的Excel应用程序，来显示动态生成的Excel电子表格。<br /></p>
		<p>接下来就是要创建工作表，创建工作表的方法与创建工作薄的方法几乎一样，同样是通过工厂模式方法获得相应的对象，该方法需要两个参<br />数，一个是工作表的名称，另一个是工作表在工作薄中的位置，参考下面的代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//创建Excel工作表
jxl.write.WritableSheet ws = wwb.createSheet("Test Sheet 1", 0);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>"这锅也支好了，材料也准备齐全了，可以开始下锅了！"，现在要做的只是实例化API所提供的Excel基本数据类型，并将它们添加到工作表中就可以了，参考下面的代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//1.添加Label对象
jxl.write.Label labelC = new jxl.write.Label(0, 0, "This is a Label cell");
ws.addCell(labelC);

//添加带有字型Formatting的对象
jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD, true);
jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf);
jxl.write.Label labelCF = new jxl.write.Label(1, 0, "This is a Label Cell", wcfF);
ws.addCell(labelCF);

//添加带有字体颜色Formatting的对象
jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false,
UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED);
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);
jxl.write.Label labelCFC = new jxl.write.Label(1, 0, "This is a Label Cell", wcfFC);
ws.addCell(labelCF);

//2.添加Number对象
jxl.write.Number labelN = new jxl.write.Number(0, 1, 3.1415926);
ws.addCell(labelN);

//添加带有formatting的Number对象
jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##");
jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf);
jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN);
ws.addCell(labelNF);

//3.添加Boolean对象
jxl.write.Boolean labelB = new jxl.write.Boolean(0, 2, false);
ws.addCell(labelB);

//4.添加DateTime对象
jxl.write.DateTime labelDT = new jxl.write.DateTime(0, 3, new java.util.Date());
ws.addCell(labelDT);

//添加带有formatting的DateFormat对象
jxl.write.DateFormat df = new jxl.write.DateFormat("dd MM yyyy hh:mm:ss");
jxl.write.WritableCellFormat wcfDF = new jxl.write.WritableCellFormat(df);
jxl.write.DateTime labelDTF = new jxl.write.DateTime(1, 3, new java.util.Date(), wcfDF);
ws.addCell(labelDTF);
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这里有两点大家要引起大家的注意。第一点，在构造单元格时，单元格在工作表中的位置就已经确定了。一旦创建后，单元格的位置是不能<br />够变更的，尽管单元格的内容是可以改变的。第二点，单元格的定位是按照下面这样的规律(column, row)，而且下标都是从0开始，例如，A1<br />被存储在(0, 0)，B1被存储在(1, 0)。</p>
		<p>最后，不要忘记关闭打开的Excel工作薄对象，以释放占用的内存，参见下面的代码片段：</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//写入Exel工作表
wwb.write();

//关闭Excel工作薄对象
wwb.close();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这可能与读取Excel文件的操作有少少不同，在关闭Excel对象之前，你必须要先调用write()方法，因为先前的操作都是存储在缓存中的，所以要<br />通过该方法将操作的内容保存在文件中。如果你先关闭了Excel对象，那么只能得到一张空的工作薄了。</p>
		<p>
				<a name="N10144">
						<span class="smalltitle">
								<strong>
										<font face="Arial">3 拷贝、更新Excel工作薄</font>
								</strong>
						</span>
				</a>
		</p>
		<p>接下来简要介绍一下如何更新一个已经存在的工作薄，主要是下面二步操作，第一步是构造只读的Excel工作薄，第二步是利用已经创建的<br />Excel工作薄创建新的可写入的Excel工作薄，参考下面的代码片段：(完整代码见ExcelModifying.java)</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">//创建只读的Excel工作薄的对象
jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(sourcefile));

//创建可写入的Excel工作薄对象
jxl.write.WritableWorkbook  wwb = Workbook.createWorkbook(new File(targetfile), rw);
            
//读取第一张工作表
jxl.write.WritableSheet ws = wwb.getSheet(0);

//获得第一个单元格对象
jxl.write.WritableCell wc = ws.getWritableCell(0, 0);
            
//判断单元格的类型, 做出相应的转化
if(wc.getType() == CellType.LABEL)
{
Label l = (Label)wc;
    l.setString("The value has been modified.");
}

//写入Excel对象
wwb.write();

//关闭可写入的Excel对象
wwb.close();

//关闭只读的Excel对象
rw.close();
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>之所以使用这种方式构建Excel对象，完全是因为效率的原因，因为上面的示例才是API的主要应用。为了提高性能，在读取工作表时，与数据<br />相关的一些输出信息，所有的格式信息，如：字体、颜色等等，是不被处理的，因为我们的目的是获得行数据的值，既使没有了修饰，也不<br />会对行数据的值产生什么影响。唯一的不利之处就是，在内存中会同时保存两个同样的工作表，这样当工作表体积比较大时，会占用相当大<br />的内存，但现在好像内存的大小并不是什么关键因素了。<br /></p>
		<p>一旦获得了可写入的工作表对象，我们就可以对单元格对象进行更新的操作了，在这里我们不必调用API提供的add()方法，因为单元格已经于<br /><br />工作表当中，所以我们只需要调用相应的setXXX()方法，就可以完成更新的操作了。</p>
		<p>尽单元格原有的格式化修饰是不能去掉的，我们还是可以将新的单元格修饰加上去，以使单元格的内容以不同的形式表现。</p>
		<p>新生成的工作表对象是可写入的，我们除了更新原有的单元格外，还可以添加新的单元格到工作表中，这与示例2的操作是完全一样的。</p>
		<p>最后，不要忘记调用write()方法，将更新的内容写入到文件中，然后关闭工作薄对象，这里有两个工作薄对象要关闭，一个是只读的，另外一<br />个是可写入的。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /> </td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center"> <br /></td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/l-javaExcel/#main">
																				<b> </b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="3">
						<span class="atitle">
								<font face="Arial" size="4">小结</font>
						</span>
				</a>
		</p>
		<p>
				<font face="Arial" size="4">
				</font>
		</p>
		<p>本文只是对Java Excel API中常用的方法作了介绍，要想更详尽地了解API，请大家参考API文档，或源代码。Java Excel API是一个开放源码项目，请大家关注它的最新进展，有兴趣的朋友也可以申请加入这个项目，或者是提出宝贵的意见。</p>
<img src ="http://www.blogjava.net/dudubird/aggbug/72759.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-29 11:42 <a href="http://www.blogjava.net/dudubird/articles/72759.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几种所见所得的在线编辑器（转）</title><link>http://www.blogjava.net/dudubird/articles/72756.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 29 Sep 2006 03:31:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72756.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72756.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72756.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72756.html</trackback:ping><description><![CDATA[
		<div style="FONT-SIZE: 12px">1.FCKeditor 编辑器<br /><br />FCKeditor is compatible with most internet browsers which include: IE 5.5+ (Windows), Firefox 1.0+, Mozilla 1.3+ and Netscape 7+.<br />最新版本:FCKeditor 2.0<br />语言环境:多国语言<br />特性功能:所见所得,支持平台众多,支持XHTML 1.0,文本格式设置,常见的编辑,复制,粘贴,撤销,文件上传等功能<br />授权方式:Open Source &amp; Free<br />官方地址:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.fckeditor.net/" target="_blank"><font color="#002c99">http://www.fckeditor.net/</font></a><br />下载地址:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.fckeditor.net/" target="_blank"><font color="#002c99">http://www.fckeditor.net/</font></a> download/default.html<br />演示:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.fckeditor.net/" target="_blank"><font color="#002c99">http://www.fckeditor.net/</font></a> demo/default.html<br />小节:FCKeditor的2.0版比1.6版有了许多的改进。首先是FCKeditor的文件结构更加清晰，可以更方便地将其部署在自己的系统中。另外2.0版开始支持了Firefox浏览器<br /><br /><br />2.WebEditor<br /><br />WebEditor系列文档控件，采用了ESS专业电子签名和电子盖章的技术，除继续支持手写签名，电子印章，痕迹保留外，<br />该版本采用了我们强大的B/S通讯技术，能够自由的将服务器数据库<br /><br />最新版本:WebEditor[V4.3.0.0 OCX版]<br />语言环境:简体中文<br />技术特性<br />采用IE5.0以上版本内置的传输协议，通讯性能稳定，高效。<br />采用标准HTTP通讯端口80，使用方便，无需特别配置、安全性好、更无需特别设置防火墙。<br />采用插件技术，可以完全融入IE浏览器中，方便系统维护、方便用户操作。<br />采用自定义协议包进行数据的组装和分析，系统开放性好，便于二次开发。<br />采用了Com组件和JavaBean组件技术，很好的实现了跨平台系统，便于开发。<br />官方地址:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.dragongod.com/" target="_blank"><font color="#002c99">http://www.dragongod.com/</font></a><br />演示:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.dragongod.com/" target="_blank"><font color="#002c99">http://www.dragongod.com/</font></a> WebEditor/Demo.asp<br />下载:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.dragongod.com/" target="_blank"><font color="#002c99">http://www.dragongod.com/</font></a> download/index.asp#item1<br />小节:这个编辑器很具有中国特色的,但必须支持安装WebEditor插件，才能正常运行对于很多用户来说,,这个是无法接收的。<br /><br /><br />3.InnovaStudio WYSIWYG Editor在线编辑器<br /><br />WYSIWYG 英文：What You See Is What You Get(所见所得)<br />一款基于web的WYSIWYG（所见即所得）的HTML编辑器，支持ASP, PHP, ASP.NET<br />最新版本:InnovaStudio WYSIWYG Editor version 2.9<br />功能特性:快速加载,融合所有的HTML标签,全屏编辑模式,所见所得预览,拼写检查.<br />特有的嵌入式WEB编辑.<br />官方:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.innovastudio.com/" target="_blank"><font color="#002c99">http://www.innovastudio.com/</font></a><br />演示:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.innovastudio.com/" target="_blank"><font color="#002c99">http://www.innovastudio.com/</font></a> editor_tutorial.asp<br />下载:官方好像都是收费的,,自己去网上搜索找找,好像有人已经做过有2.0的汉化版<br /><br />小节:采用DHTML, JavaScript 构件的WYSIWYG也有很多不足之处，由于代码放在远程服务器，一些控件事先没有下载到客户端，使得一些操作速度变慢，那些加入了ActiveX 控件的更慢，另外它无法在网页里直接调用CSS，所以在操作框里的界面效果和尺寸和实际上的界面有差距。有很多WYSIWYG对各种浏览器还不兼容，而且有的也要在IE的高版本下才能正常运行(此段出自老鬼的blog)。<br /><br /><br />4.eWebEditor在线编辑器<br /><br />eWebEditor是基于网页的、所见即所得的在线HTML编辑器。她能够在网页上实现许多桌面编辑软件<br />（如：Word）所具有的强大可视编辑功能；她是一个真正的绿色软件，不需要在计算机上安装<br />任何的客户端软件；她的易用使得WEB开发人员只要一行代码即可完成调用。<br />最新版本:Version 3.6 (ASP版、PHP版、JSP版、ASP.NET版)<br />官方:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.ewebsoft.com/" target="_blank"><font color="#002c99">http://www.ewebsoft.com/</font></a><br />演示:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://ewebeditor.webasp.net/demo.asp" target="_blank"><font color="#002c99">http://ewebeditor.webasp.net/demo.asp</font></a><br />下载:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://ewebeditor.webasp.net/download.asp" target="_blank"><font color="#002c99">http://ewebeditor.webasp.net/download.asp</font></a><br />功能特性:<br />纯静态：大大提高了效率，最佳的融入您的产品；<br />多样式支持：您只需要在您的整个网站中使用一个eWebEditor；<br />自动提交：无需在提交按钮中加入脚本进行处理；<br />自动获取远程文件：把别人服务器上的图片等文件自动传到自己的服务器；<br />相对或绝对路径：完全摆脱了站点或系统或目录迁移而带来的路径问题；<br />图形热点链接：始创能够在线编辑实现图形的热点链接功能；<br />多种编辑模式：HTML代码模式、可视设计模式、纯文本模式、预览模式；<br />大小自适应：可以按你调用的宽度和高度自适应编辑器的大小；<br />内附文件上传功能：自带有从客户端直接上传到服务器端的功能；<br />完善的接口：您可以通过接口实时控制或者获取编辑器的内容或者状态；<br /><br />小节:除了他是国产的外，比较符合国人的习惯，另外也可能是众多编辑器，唯一还带后台管理模式，可以直接在后台管理编辑模式，另外接口定制非常容易，具体的自己可以去官方下载回来看看。<br /><br /><br />5.htmlarea<br /><br />htmlarea.com is a directory of browser based wysiwyg editor components for use<br />in CMS (content management software) and other web software.<br />htmlArea是一款非常优秀的所见即所得编辑器,被使用在CMS系统或其他的WEB系统中..<br />语言环境:多国语言版<br />版本:version 3.0<br />官方:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.htmlarea.com/" target="_blank"><font color="#002c99">http://www.htmlarea.com/</font></a><br />演示:没找到,<br />下载:官方没找到下载地址，siyizhu找了个3.0的版本 <img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.92key.com/mp3/chinahtml@_HTMLArea3.rar" target="_blank"><font color="#002c99">http://www.92key.com/mp3/chinahtml@_HTMLArea3.rar</font></a><br />小节:这个编辑器调用也非常方便，已经广泛用在各种CMS和blog系统里，记得bo-blog、phpArticle里整合了这个编辑器。<br /><br /><br />6.XStandard XHTML (Strict or 1.1) <br /><br />WYSIWYG Editor 也是所见所得,比起前几个，它已经完全支持XHTML 1.1的严格验证，这个非常厉害 @@<br />版本:XStandard Version 1.6.2<br />官方:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://xstandard.com/" target="_blank"><font color="#002c99">http://xstandard.com/</font></a><br />下载:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://xstandard.com/" target="_blank"><font color="#002c99">http://xstandard.com/</font></a> download.asp<br />演示:<br /><br /><br /><br />小节:这个编辑器，也很少在国内的CMS，blog上见到有人使用，当然一个原因就是它是一个共享软件。XStandard Lite是免费的，XStandard Pro是30天的试用期，而且价格还不菲＄179。<br /><br /><br />7.Cross-Browser Rich Text Editor<br /><br />The cross-browser rich-text editor (RTE) is based on the designMode() functionality introduced in Internet Explorer 5, and implemented in Mozilla 1.3+ using the Mozilla Rich Text Editing API. The cross-browser rich-text editor now includes table support (as of 2/10/2005) as well as an option to generate xhtml-compliant code<br />官方:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.kevinroth.com/" target="_blank"><font color="#002c99">http://www.kevinroth.com</font></a><br />演示:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.kevinroth.com/" target="_blank"><font color="#002c99">http://www.kevinroth.com</font></a> /rte/demo.htm<br />下载:<img src="http://www.blogcn.com/images/aurl.gif" align="absBottom" border="0" /><a href="http://www.kevinroth.com/" target="_blank"><font color="#002c99">http://www.kevinroth.com</font></a> /rte/demo.htm<br /></div>
<img src ="http://www.blogjava.net/dudubird/aggbug/72756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-29 11:31 <a href="http://www.blogjava.net/dudubird/articles/72756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何给图片加水印（转载）</title><link>http://www.blogjava.net/dudubird/articles/72749.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 29 Sep 2006 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72749.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72749.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72749.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72749.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72749.html</trackback:ping><description><![CDATA[
		<p>我是结合在jspsmart.upload下使用的，这个是imgbean的代码<br />package com.dcampus;</p>
		<p>import java.awt.*;<br />import java.awt.event.*;<br />import java.io.*;<br />import java.awt.image.*;<br />import org.w3c.dom.*;<br />import com.sun.image.codec.jpeg.*;<br />import javax.imageio.*;</p>
		<p>public class ImgBean_i{<br />public void ImgBean_i(){</p>
		<p>}</p>
		<p>public void ImgYin(String Imagename_biao,String ImgName){<br />try{<br />File _file = new File(ImgName);<br />Image src = ImageIO.read(_file);<br />int wideth=src.getWidth(null);<br />int height=src.getHeight(null);<br />BufferedImage image=new BufferedImage(wideth,height,BufferedImage.TYPE_INT_RGB);<br />Graphics g=image.createGraphics();<br />g.drawImage(src,0,0,wideth,height,null);</p>
		<p>//水印文件<br />File _filebiao = new File(Imagename_biao);<br />Image src_biao = ImageIO.read(_filebiao);<br />int wideth_biao=src_biao.getWidth(null);<br />int height_biao=src_biao.getHeight(null);<br />g.drawImage(src_biao,wideth-110,height-110,wideth_biao,height_biao,null);<br />//水印文件在原图片文件的位置，原图片文件的右下角为wideth-0,height-0<br /> g.dispose();<br />FileOutputStream out=new FileOutputStream(ImgName);<br />JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); <br />encoder.encode(image);<br />out.close();<br />}<br />catch(Exception e){<br />System.out.println(e);<br />}<br />}<br />}<br />以下是修改过的smartupload代码<br />&lt;%@ page language="java" import="com.jspsmart.upload.*" import="java.util.*,java.text.*"%&gt;<br />&lt;%@ page contentType="text/html;charset=GBK" %&gt;<br /><br />&lt;jsp:useBean id="mySmartUpload" scope="page" class="com.jspsmart.upload.SmartUpload"/&gt;</p>
		<p>&lt;HTML&gt;&lt;META http-equiv=Content-Type content="text/html; charset=gb2312"&gt;<br />&lt;LINK href="images/css.css" rel=stylesheet&gt;<br />&lt;BODY BGCOLOR="white" leftmargin="0" topmargin="0"&gt;<br />&lt;%<br /> <br /> int count=0;       <br /> String path=request.getRealPath("");<br /> mySmartUpload.initialize(pageContext);</p>
		<p> mySmartUpload.upload();</p>
		<p> connectToDatabase();<br /> for (int i=0;i&lt;mySmartUpload.getFiles().getCount();i++){</p>
		<p>  com.jspsmart.upload.File myFile = mySmartUpload.getFiles().getFile(i);<br /><br />  if (!myFile.isMissing()) {<br />   int Size=myFile.getSize() ;<br />   String FileName=myFile.getFileName();<br />   String FileExt=myFile.getFileExt();<br />   String uploadtime=new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( java.util.Calendar.getInstance().getTime() );<br />   if(Size&gt;=1000000) {<br />    out.println("文件超过1000K！"); //限制大小<br />   }else{<br />    if((FileExt.equals("jpg")) || (FileExt.equals("JPG")) || (FileExt.equals("gif")) || (FileExt.equals("GIF"))) {<br />     java.util.Date date = new java.util.Date();<br />     SimpleDateFormat formatter1 = new SimpleDateFormat("yyyyMMddHHmmss");<br />                String name1=FileName.substring(0,FileName.indexOf("."));<br />                String name2=FileName.substring(FileName.indexOf("."),FileName.length());<br />                String newname=name1+formatter1.format(date)+name2;<br />     //session.putValue("path1",newname);<br />     myFile.saveAs("/photo/upfile/" + newname);<br />     if(Integer.parseInt(sy)==1) {<br />      com.pic.ImgBean_i bbb= new com.pic.ImgBean_i();<br />      bbb.ImgYin(path+"/photo/images/shuiyin.gif",path+"/photo/upfile/" + newname);//这里是水印文件的来源地址，可修改成取得下拉菜单值的形式，这样就可以实现打文字水印或者图片水印了<br />     }<br />     stmt.executeUpdate("insert into img_photo (name,http,userid,classid,title,content,imgsize,format,num,primflag,posttime) values ()");<br />     out.println(("&lt;br&gt;&lt;br&gt;&lt;center&gt;图片上传成功！&lt;br&gt;").toString()); <br />    }else{<br />     out.println("文件格式不对！"); <br />    }<br />   }<br />   count ++;<br />  }<br />   else<br />  {<br />   out.println("未找到上传文件！\n");<br />  }<br /> }<br /> disConnectToDatabase();<br />%&gt;<br />&lt;/BODY&gt;<br />&lt;/HTML&gt;<br /></p>
<img src ="http://www.blogjava.net/dudubird/aggbug/72749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-29 11:14 <a href="http://www.blogjava.net/dudubird/articles/72749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java Servlet动态生成图片（转）</title><link>http://www.blogjava.net/dudubird/articles/72618.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Thu, 28 Sep 2006 08:39:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/72618.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/72618.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/72618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/72618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/72618.html</trackback:ping><description><![CDATA[在Web应用中，经常需要动态生成图片，比如实时股市行情，各种统计图等等，这种情况下，图片只能在服务器内存中动态生成并发送给用户，然后在浏览器中显示出来。 <br /><br />　　本质上，浏览器向服务器请求静态图片如jpeg时，服务器返回的仍然是标准的http响应，只不过http头的contentType不是text/html，而是image/jpeg而已，因此，我们在Servlet中只要设置好contentType，然后发送图像的数据流，浏览器就能正确解析并显示出图片。<br /><br />　　在Java中，java.awt和java.awt.image包提供了基本的绘制图像的能力，我们可以在内存中绘制好需要的图形，然后编码成jpeg或其他图像格式，最后发送相应给浏览器即可。下面是使用Servlet动态创建图像的详细步骤：<br /><br />　　1．创建BufferedImage对象，该对象存在内存中，负责保存绘制的图像；<br /><br />　　2．创建Graphics2D对象，该对象负责绘制所需的图像；<br /><br />　　3．当绘制完成后，调用com.sun.image.codec.jpeg包的JPEG编码器对其编码；<br /><br />　　4．最后将编码后的数据输出至HttpResponse即可。<br /><br />　　注意com.sun.image.codec.jpeg包位于JDK目录的rt.jar包中，它不是公开的API，需要将rt.jar复制到web应用程序的WEB-INF/lib下。<br /><br />　　我们先创建一个最简单的Servlet：<br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><tr><td>public class CreateImageServlet extends HttpServlet {<br />　protected void doGet(HttpServletRequest request, HttpServletResponse response)<br />　throws ServletException, IOException<br />　{<br />　　response.setContentType("image/jpeg");<br />　}<br />}</td></tr></tbody></table><br />　　我们首先设置了response的contentType为image/jpeg，这样浏览器就可以正确识别。<br /><br />　　然后，创建一个大小为100x100的BufferedImage对象，准备绘图： 
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><br /><tr><td>int width = 100;<br />int height = 100;<br />BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);</td></tr></tbody></table><br />　　接着，BufferedImage对象中获取Graphics2D对象并绘图： 
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><br /><tbody><br /><tr><br /><td>Graphics2D g = bi.createGraphics(); // 创建Graphics2D对象<br />// 填充背景为白色：<br />g.setBackground(Color.BLUE);<br />g.clearRect(0, 0, width, height);<br />// 设置前景色：<br />g.setColor(Color.RED);<br />// 开始绘图：<br />g.drawLine(0, 0, 99, 99); // 绘制一条直线<br />// 绘图完成，释放资源：<br />g.dispose();<br />bi.flush();</td></tr></tbody></table><br />　　然后，对BufferedImage进行JPEG编码： 
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><br /><tbody><br /><tr><br /><td>JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);<br />JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);<br />param.setQuality(1.0f, false);<br />encoder.setJPEGEncodeParam(param);<br />try {<br />　encoder.encode(bi);<br />}<br />catch(IOException ioe) {<br />　ioe.printStackTrace();<br />}</td></tr></tbody></table><br />　　编码后的JPEG图像直接输出到了out对象中，我们只要传入response. getOutputStream()就可以直接输出到HttpResponse中。<br /><br />　　下面是完整的代码： 
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><tbody><br /><tr><br /><td>package com.crackj2ee.web.util;<br /><br />import java.io.*;<br />import java.awt.*;<br />import java.awt.image.*;<br /><br />import javax.servlet.*;<br />import javax.servlet.http.*;<br /><br />import com.sun.image.codec.jpeg.*;<br /><br />/**<br />* @author Liao Xue Feng<br />*/<br />public class CreateImageServlet extends HttpServlet {<br /><br />　protected void doGet(HttpServletRequest request, HttpServletResponse response)<br />　throws ServletException, IOException<br />　{<br />　　response.setContentType("image/jpeg");<br />　　createImage(response.getOutputStream());<br />　}<br /><br />　private void createImage(OutputStream out) {<br />　　int width = 100;<br />　　int height = 100;<br />　　BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);<br />　　Graphics2D g = bi.createGraphics();<br />　　// set background:<br />　　g.setBackground(Color.BLUE);<br />　　g.clearRect(0, 0, width, height);<br />　　// set fore color:<br />　　g.setColor(Color.RED);<br />　　// start draw:<br />　　g.drawLine(0, 0, 99, 199);<br />　　// end draw:<br />　　g.dispose();<br />　　bi.flush();<br />　　// encode:<br />　　JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);<br />　　JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);<br />　　param.setQuality(1.0f, false);<br />　　encoder.setJPEGEncodeParam(param);<br />　　try {<br />　　　encoder.encode(bi);<br />　　}<br />　　catch(IOException ioe) {<br />　　　ioe.printStackTrace();<br />　　}<br />　}<br />}</td></tr></tbody></table><br />　　最后将这个Servlet编译，注册到web.xml中，映射路径为/CreateImage，写一个简单的index.html测试：<br /><table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1"><br /><tbody><br /><tr><br /><td>＜html＞＜head＞＜/head＞<br />＜body＞<br />＜img src="CreateImage"＞<br />＜/body＞＜/html＞</td></tr></tbody></table><br />　　如能正确显示，大功告成！ <br /><script src="http://www.tot.name/js/ad_atl.js" type="text/javascript"></script><img src ="http://www.blogjava.net/dudubird/aggbug/72618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-09-28 16:39 <a href="http://www.blogjava.net/dudubird/articles/72618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存泄漏解决之道</title><link>http://www.blogjava.net/dudubird/articles/62934.html</link><dc:creator>毛里求斯的化石</dc:creator><author>毛里求斯的化石</author><pubDate>Fri, 11 Aug 2006 03:10:00 GMT</pubDate><guid>http://www.blogjava.net/dudubird/articles/62934.html</guid><wfw:comment>http://www.blogjava.net/dudubird/comments/62934.html</wfw:comment><comments>http://www.blogjava.net/dudubird/articles/62934.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dudubird/comments/commentRss/62934.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dudubird/services/trackbacks/62934.html</trackback:ping><description><![CDATA[
		<div style="FONT-SIZE: 12px">
				<p>
						<strong>摘要</strong>
				</p>
				<p>　　虽然Java虚拟机(JVM)及其垃圾收集器(garbage collector，GC)负责管理大多数的内存任务，Java软件程序中还是有可能出现内存泄漏。实际上，这在大型项目中是一个常见的问题。避免内存泄漏的第一步是要弄清楚它是如何发生的。本文介绍了编写Java代码的一些常见的内存泄漏陷阱，以及编写不泄漏代码的一些最佳实践。一旦发生了内存泄漏，要指出造成泄漏的代码是非常困难的。因此本文还介绍了一种新工具，用来诊断泄漏并指出根本原因。该工具的开销非常小，因此可以使用它来寻找处于生产中的系统的内存泄漏。</p>
				<p>
						<strong>垃圾收集器的作用</strong>
				</p>
				<p>　　虽然垃圾收集器处理了大多数内存管理问题，从而使编程人员的生活变得更轻松了，但是编程人员还是可能犯错而导致出现内存问题。简单地说，GC循环地跟踪所有来自“根”对象（堆栈对象、静态对象、JNI句柄指向的对象，诸如此类）的引用，并将所有它所能到达的对象标记为活动的。程序只可以操纵这些对象；其他的对象都被删除了。因为GC使程序不可能到达已被删除的对象，这么做就是安全的。</p>
				<p>　　虽然内存管理可以说是自动化的，但是这并不能使编程人员免受思考内存管理问题之苦。例如，分配（以及释放）内存总会有开销，虽然这种开销对编程人员来说是不可见的。创建了太多对象的程序将会比完成同样的功能而创建的对象却比较少的程序更慢一些（在其他条件相同的情况下）。</p>
				<p>　　而且，与本文更为密切相关的是，如果忘记“释放”先前分配的内存，就可能造成内存泄漏。如果程序保留对永远不再使用的对象的引用，这些对象将会占用并耗尽内存，这是因为自动化的垃圾收集器无法证明这些对象将不再使用。正如我们先前所说的，如果存在一个对对象的引用，对象就被定义为活动的，因此不能删除。为了确保能回收对象占用的内存，编程人员必须确保该对象不能到达。这通常是通过将对象字段设置为null或者从集合(collection)中移除对象而完成的。但是，注意，当局部变量不再使用时，没有必要将其显式地设置为null。对这些变量的引用将随着方法的退出而自动清除。</p>
				<p>　　概括地说，这就是内存托管语言中的内存泄漏产生的主要原因：保留下来却永远不再使用的对象引用。</p>
				<p>
						<strong>典型泄漏</strong>
				</p>
				<p>　　既然我们知道了在Java中确实有可能发生内存泄漏，就让我们来看一些典型的内存泄漏及其原因。</p>
				<p>
						<strong>全局集合</strong>
				</p>
				<p>　　在大的应用程序中有某种全局的数据储存库是很常见的，例如一个JNDI树或一个会话表。在这些情况下，必须注意管理储存库的大小。必须有某种机制从储存库中移除不再需要的数据。</p>
				<p>　　这可能有多种方法，但是最常见的一种是周期性运行的某种清除任务。该任务将验证储存库中的数据，并移除任何不再需要的数据。</p>
				<p>　　另一种管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零时，该元素就可以从集合中移除了。</p>
				<p>
						<strong>缓存</strong>
				</p>
				<p>　　缓存是一种数据结构，用于快速查找已经执行的操作的结果。因此，如果一个操作执行起来很慢，对于常用的输入数据，就可以将操作的结果缓存，并在下次调用该操作时使用缓存的数据。</p>
				<p>　　缓存通常都是以动态方式实现的，其中新的结果是在执行时添加到缓存中的。典型的算法是：</p>
				<ul>
						<li>检查结果是否在缓存中，如果在，就返回结果。 
</li>
						<li>如果结果不在缓存中，就进行计算。 
</li>
						<li>将计算出来的结果添加到缓存中，以便以后对该操作的调用可以使用。 </li>
				</ul>
				<p>　　该算法的问题（或者说是潜在的内存泄漏）出在最后一步。如果调用该操作时有相当多的不同输入，就将有相当多的结果存储在缓存中。很明显这不是正确的方法。</p>
				<p>　　为了预防这种具有潜在破坏性的设计，程序必须确保对于缓存所使用的内存容量有一个上限。因此，更好的算法是：</p>
				<ul>
						<li>检查结果是否在缓存中，如果在，就返回结果。 
</li>
						<li>如果结果不在缓存中，就进行计算。 
</li>
						<li>如果缓存所占的空间过大，就移除缓存最久的结果。 
</li>
						<li>将计算出来的结果添加到缓存中，以便以后对该操作的调用可以使用。 </li>
				</ul>
				<p>　　通过始终移除缓存最久的结果，我们实际上进行了这样的假设：在将来，比起缓存最久的数据，最近输入的数据更有可能用到。这通常是一个不错的假设。</p>
				<p>　　新算法将确保缓存的容量处于预定义的内存范围之内。确切的范围可能很难计算，因为缓存中的对象在不断变化，而且它们的引用包罗万象。为缓存设置正确的大小是一项非常复杂的任务，需要将所使用的内存容量与检索数据的速度加以平衡。</p>
				<p>　　解决这个问题的另一种方法是使用java.lang.ref.SoftReference类跟踪缓存中的对象。这种方法保证这些引用能够被移除，如果虚拟机的内存用尽而需要更多堆的话。</p>
				<p>
						<strong>ClassLoader</strong>
				</p>
				<p>　　Java ClassLoader结构的使用为内存泄漏提供了许多可乘之机。正是该结构本身的复杂性使ClassLoader在内存泄漏方面存在如此多的问题。ClassLoader的特别之处在于它不仅涉及“常规”的对象引用，还涉及元对象引用，比如：字段、方法和类。这意味着只要有对字段、方法、类或ClassLoader的对象的引用，ClassLoader就会驻留在JVM中。因为ClassLoader本身可以关联许多类及其静态字段，所以就有许多内存被泄漏了。</p>
				<p>
						<strong>确定泄漏的位置</strong>
				</p>
				<p>　　通常发生内存泄漏的第一个迹象是：在应用程序中出现了OutOfMemoryError。这通常发生在您最不愿意它发生的生产环境中，此时几乎不能进行调试。有可能是因为测试环境运行应用程序的方式与生产系统不完全相同，因而导致泄漏只出现在生产中。在这种情况下，需要使用一些开销较低的工具来监控和查找内存泄漏。还需要能够无需重启系统或修改代码就可以将这些工具连接到正在运行的系统上。可能最重要的是，当进行分析时，需要能够断开工具而保持系统不受干扰。</p>
				<p>　　虽然OutOfMemoryError通常都是内存泄漏的信号，但是也有可能应用程序确实正在使用这么多的内存；对于后者，或者必须增加JVM可用的堆的数量，或者对应用程序进行某种更改，使它使用较少的内存。但是，在许多情况下，OutOfMemoryError都是内存泄漏的信号。一种查明方法是不间断地监控GC的活动，确定内存使用量是否随着时间增加。如果确实如此，就可能发生了内存泄漏。</p>
				<p>
						<strong>详细输出</strong>
				</p>
				<p>　　有许多监控垃圾收集器活动的方法。而其中使用最广泛的可能是使用-Xverbose:gc选项启动JVM，并观察输出。</p>[memory ] 10.109-10.235: GC 65536K-&gt;16788K (65536K), 126.000 ms 
<p>　箭头后面的值（本例中是16788K）是垃圾收集所使用的堆的容量。</p><p><strong>控制台</strong></p><p>　　查看连续不断的GC的详细统计信息的输出将是非常乏味的。幸好有这方面的工具。JRockit Management Console可以显示堆使用量的图示。借助于该图，可以很容易地看出堆使用量是否随时间增加。</p><p><img height="245" src="http://dev2dev.bea.com.cn/images/050920/0509200201.jpg" width="342" /></p><p>图1. JRockit Management Console</p><p>　　甚至可以配置该管理控制台，以便如果发生堆使用量过大的情况（或基于其他的事件），控制台能够向您发送电子邮件。这明显使内存泄漏的查看变得更容易了。</p><p><strong>内存泄漏检测工具</strong></p><p>　　还有其他的专门进行内存泄漏检测的工具。JRockit Memory Leak Detector可以用来查看内存泄漏，并可以更深入地查出泄漏的根源。这个强大的工具是紧密集成到JRockit JVM中的，其开销非常小，对虚拟机的堆的访问也很容易。</p><p><strong>专业工具的优点</strong></p><p>　　一旦知道确实发生了内存泄漏，就需要更专业的工具来查明为什么会发生泄漏。JVM自己是不会告诉您的。这些专业工具从JVM获得内存系统信息的方法基本上有两种：JVMTI和字节码技术(byte code instrumentation)。Java虚拟机工具接口(Java Virtual Machine Tools Interface，JVMTI)及其前身Java虚拟机监视程序接口(Java Virtual Machine Profiling Interface，JVMPI)是外部工具与JVM通信并从JVM收集信息的标准化接口。字节码技术是指使用探测器处理字节码以获得工具所需的信息的技术。</p><p>　　对于内存泄漏检测来说，这两种技术有两个缺点，这使它们不太适合用于生产环境。首先，它们在内存占用和性能降低方面的开销不可忽略。有关堆使用量的信息必须以某种方式从JVM导出，并收集到工具中进行处理。这意味着要为工具分配内存。信息的导出也影响了JVM的性能。例如，当收集信息时，垃圾收集器将运行得比较慢。另外一个缺点是需要始终将工具连在JVM上。这是不可能的：将工具连在一个已经启动的JVM上，进行分析，断开工具，并保持JVM运行。</p><p>　　因为JRockit Memory Leak Detector是集成到JVM中的，就没有这两个缺点了。首先，许多处理和分析工作是在JVM内部进行的，所以没有必要转换或重新创建任何数据。处理还可以背负(piggyback)在垃圾收集器本身上而进行，这意味着提高了速度。其次，只要JVM是使用-Xmanagement选项（允许通过远程JMX接口监控和管理JVM）启动的，Memory Leak Detector就可以与运行中的JVM进行连接或断开。当该工具断开时，没有任何东西遗留在JVM中，JVM又将以全速运行代码，正如工具连接之前一样。</p><p><strong>趋势分析</strong></p><p>　　让我们深入地研究一下该工具以及它是如何用来跟踪内存泄漏的。在知道发生内存泄漏之后，第一步是要弄清楚泄漏了什么数据--哪个类的对象引起了泄漏？JRockit Memory Leak Detector是通过在每次垃圾收集时计算每个类的现有对象的数目来实现这一步的。如果特定类的对象数目随时间而增长（“增长率”），就可能发生了内存泄漏。 </p><p><img height="105" src="http://dev2dev.bea.com.cn/images/050920/0509200202.jpg" width="343" /><br />图2. Memory Leak Detector的趋势分析视图</p><p>　　因为泄漏可能像细流一样非常小，所以趋势分析必须运行很长一段时间。在短时间内，可能会发生一些类的局部增长，而之后它们又会跌落。但是趋势分析的开销很小（最大开销也不过是在每次垃圾收集时将数据包由JRockit发送到Memory Leak Detector）。开销不应该成为任何系统的问题——即使是一个全速运行的生产中的系统。</p><p>　　起初数目会跳跃不停，但是一段时间之后它们就会稳定下来，并显示出哪些类的数目在增长。</p><p><strong>找出根本原因</strong></p><p>　　有时候知道是哪些类的对象在泄漏就足以说明问题了。这些类可能只用于代码中的非常有限的部分，对代码进行一次快速检查就可以显示出问题所在。遗憾地是，很有可能只有这类信息还并不够。例如，常见到泄漏出在类java.lang.String的对象上，但是因为字符串在整个程序中都使用，所以这并没有多大帮助。</p><p>　　我们想知道的是，另外还有哪些对象与泄漏对象关联？在本例中是String。为什么泄漏的对象还存在？哪些对象保留了对这些对象的引用？但是能列出的所有保留对String的引用的对象将会非常多，以至于没有什么实际用处。为了限制数据的数量，可以将数据按类分组，以便可以看出其他哪些对象的类与泄漏对象(String)关联。例如，String在Hashtable中是很常见的，因此我们可能会看到与String关联的Hashtable数据项对象。由Hashtable数据项倒推，我们最终可以找到与这些数据项有关的Hashtable对象以及String（如图3所示）。 </p><p><img height="173" src="http://dev2dev.bea.com.cn/images/050920/0509200203.jpg" width="354" /><br />图3. 在工具中看到的类型图的示例视图</p><p><strong>倒推</strong></p><p>　　因为我们仍然是以类的对象而不是单独的对象来看待对象，所以我们不知道是哪个Hashtable在泄漏。如果我们可以弄清楚系统中所有的Hashtable都有多大，我们就可以假定最大的Hashtable就是正在泄漏的那一个（因为随着时间的流逝它会累积泄漏而增长得相当大）。因此，一份有关所有Hashtable对象以及它们引用了多少数据的列表，将会帮助我们指出造成泄漏的确切Hashtabl。 </p><p><img height="85" src="http://dev2dev.bea.com.cn/images/050920/0509200204.jpg" width="342" /><br />图4. 界面：Hashtable对象以及它们所引用数据的数量的列表</p><p>　　对对象引用数据数目的计算开销非常大（需要以该对象作为根遍历引用图），如果必须对许多对象都这么做，将会花很多时间。如果了解一点Hashtable的内部实现原理就可以找到一条捷径。Hashtable的内部有一个Hashtable数据项的数组。该数组随着Hashtable中对象数目的增长而增长。因此，为找出最大的Hashtable，我们只需找出引用Hashtable数据项的最大数组。这样要快很多。 </p><p><img height="87" src="http://dev2dev.bea.com.cn/images/050920/0509200205.jpg" width="354" /><br />图5. 界面：最大的Hashtable数据项数组及其大小的清单</p><p><strong>更进一步</strong></p><p>　　当找到发生泄漏的Hashtable实例时，我们可以看到其他哪些实例在引用该Hashtable，并倒推回去看看是哪个Hashtable在泄漏。</p><p><img height="42" src="http://dev2dev.bea.com.cn/images/050920/0509200206.jpg" width="390" /><br />图 6. 这就是工具中的实例图</p><p>　　例如，该Hashtable可能是由MyServer类型的对象在名为activeSessions的字段中引用的。这种信息通常就足以查找源代码以定位问题所在了。 </p><p><img height="103" src="http://dev2dev.bea.com.cn/images/050920/0509200207.jpg" width="342" /><br />图7. 检查对象以及它对其他对象的引用</p><p><strong>找出分配位置</strong></p><p>　　当跟踪内存泄漏问题时，查看对象分配到哪里是很有用的。只知道它们如何与其他对象相关联（即哪些对象引用了它们）是不够的，关于它们在何处创建的信息也很有用。当然了，您并不想创建应用程序的辅助构件，以打印每次分配的堆栈跟踪(stack trace)。您也不想仅仅为了跟踪内存泄漏而在运行应用程序时将一个分析程序连接到生产环境中。</p><p>　　借助于JRockit Memory Leak Detector，应用程序中的代码可以在分配时进行动态添加，以创建堆栈跟踪。这些堆栈跟踪可以在工具中进行累积和分析。只要不启用就不会因该功能而产生成本，这意味着随时可以进行分配跟踪。当请求分配跟踪时，JRockit 编译器动态插入代码以监控分配，但是只针对所请求的特定类。更好的是，在进行数据分析时，添加的代码全部被移除，代码中没有留下任何会引起应用程序性能降低的更改。 </p><p><img height="104" src="http://dev2dev.bea.com.cn/images/050920/0509200208.jpg" width="358" /><br />图8. 示例程序执行期间String的分配的堆栈跟踪</p><p><strong>结束语</strong></p><p>　　内存泄漏是难以发现的。本文重点介绍了几种避免内存泄漏的最佳实践，包括要始终记住在数据结构中所放置的内容，以及密切监控内存使用量以发现突然的增长。</p><p>　　我们都已经看到了JRockit Memory Leak Detector是如何用于生产中的系统以跟踪内存泄漏的。该工具使用一种三步式的方法来找出泄漏。首先，进行趋势分析，找出是哪个类的对象在泄漏。接下来，看看有哪些其他的类与泄漏的类的对象相关联。最后，进一步研究单个对象，看看它们是如何互相关联的。也有可能对系统中所有对象分配进行动态的堆栈跟踪。这些功能以及该工具紧密集成到JVM中的特性使您可以以一种安全而强大的方式跟踪内存泄漏并进行修复。</p></div>
<img src ="http://www.blogjava.net/dudubird/aggbug/62934.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dudubird/" target="_blank">毛里求斯的化石</a> 2006-08-11 11:10 <a href="http://www.blogjava.net/dudubird/articles/62934.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>