﻿<?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-思想比知识更重要 成长比成功更重要-文章分类-open source</title><link>http://www.blogjava.net/renyangok/category/13032.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:37:38 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:37:38 GMT</pubDate><ttl>60</ttl><item><title>使用sitemesh建立复合视图</title><link>http://www.blogjava.net/renyangok/articles/86381.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Fri, 08 Dec 2006 08:10:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/86381.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/86381.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/86381.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/86381.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/86381.html</trackback:ping><description><![CDATA[
		<a href="http://www.huihoo.com/java/sitemesh/index.html">http://www.huihoo.com/java/sitemesh/index.html</a>
<img src ="http://www.blogjava.net/renyangok/aggbug/86381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-12-08 16:10 <a href="http://www.blogjava.net/renyangok/articles/86381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta项目的commons包</title><link>http://www.blogjava.net/renyangok/articles/74008.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 09 Oct 2006 03:02:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/74008.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/74008.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/74008.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/74008.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/74008.html</trackback:ping><description><![CDATA[
		<h4 class="TextColor1" id="subjcns!F319B9AFFE33A988!201" style="MARGIN-BOTTOM: 0px">commons分为3部分Commons Proper、Commons Sandbox和Commons Dormant<br />Commons Proper：提供了设计良好可重用的java组件，并都经过了广泛、严格的测试。<br />Commons Sandbox：处于实验、测试阶段的组件。<br />Commons Dormant：处于停滞状态，从Sandbox退出的，不活跃的组件，谨慎使用。 
<p>Commons Proper组件：</p><ul><li>Attributes—— 支持源代码级的元数据。 
</li><li>BeanUtils——提供对 Java 反射和自省API的包装，处理javabean的工具。 
</li><li>Betwixt——将JavaBeans与XML相互转换。  
</li><li>Chain——对Chain of Responsibility（责任链）设计模式的实现。使多个对象都有机会处理请求， 从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链，并沿着这条链传递请求，直到有一个对象处理它为止。 
</li><li>CLI——处理命令行的命令的解析。 
</li><li>Codec——包含一些通用的编码解码算法。包括一些语音编码器， Hex, Base64, 以及URL encoder。 
</li><li>Collections——扩展和增加标准的 Java Collection框架。 
</li><li>Configuration——操作各种格式的配置文件。Properties文件 /XML文件 /JNDI /JDBC 数据源 /System properties /Applet parameters / Servlet parameters 
</li><li>Daemon——创建类似unix守护线程的java代码，可以安全地执行一些后台操作，线程不被某个应用程序控制，而是由操作系统控制 类似windows的service，可以设置一个服务依赖于另一个服务，一个服务关闭前必须先执行另一个服务。 
</li><li>DBCP——一个数据库连接池 
</li><li>DbUtils——一个JDBC的工具类，比如可以将ResultSets生成javabean。 
</li><li>Digester——基于规则的XML文档解析,主要用于XML到Java对象的映射. 
</li><li>Discovery——提供工具来定位资源 (包括类) ，通过使用各种模式来映射服务/引用名称和资源名称。 
</li><li>EL——JSP 2.0引入的表达式 
</li><li>Email——处理e-mail 
</li><li>FileUpload——web应用中的文件上传组件 
</li><li>HttpClient——使用HTTP协议的客户端开发框架 
</li><li>IO——帮助进行IO功能开发 
</li><li>Jelly——Jelly能够把XML转换成可执行代码,所以Jelly是一个基于XML与Java的脚本和处理引擎。 Jelly借鉴了JSP定指标签，Velocity, Cocoon和Xdoclet中的脚本引擎的许多优点。Jelly可以用在命令行，Ant或者Servlet之中。 
</li><li>Jexl——Jexl是一个表达式语言，通过借鉴来自于Velocity的经验扩展了JSTL定义的表达式语言。 
</li><li>JXPath——使用XPath语法操作javabean的工具。 
</li><li>Lang——提供对java.lang包的扩展。  
</li><li>Launcher——跨平台的java程序的启动 
</li><li>Logging——提供的是一个日志(Log)接口(interface)，同时兼顾轻量级和不依赖于具体的日志实现工具。 它提供给中间件/日志工具开发者一个简单的日志操作抽象，允许程序开发人员使用不同的具体日志实现工具。用户被假定已熟悉某种日志实现工具的更高级别的细节。JCL提供的接口，对其它一些日志工具，包括Log4J, Avalon LogKit, and JDK 1.4等，进行了简单的包装，此接口更接近于Log4J和LogKit的实现. 
</li><li>Math——Math 是一个轻量的，自包含的数学和统计组件，解决了许多非常通用但没有及时出现在Java标准语言中的实践问题. 
</li><li>Modeler—— 支持兼容JMX规范的MBeans开发。 
</li><li>Net——集合了网络工具和协议工具的实现 
</li><li>Pool——Commons-Pool 提供了通用对象池接口，一个用于创建模块化对象池的工具包，以及通常的对象池实现。 
</li><li>Primitives——对java原始类型的支持。 
</li><li>SCXML——处理SCXML 
</li><li>Transaction——事务处理，实现了多层次锁、事务集合、事务文件的访问。  
</li><li>Validator——提供了一个简单的，可扩展的框架来在一个XML文件中定义校验器 (校验方法)和校验规则。支持校验规则的和错误消息的国际化。 
</li><li>VFS——访问各种文件系统，可以是本地文件、HTTP服务器上的文件、zip中的文件。 </li></ul><p>Commons Sandbox组件：</p><ul><li>Compress——处理压缩文件如tar, zip 和 bzip2 格式。 
</li><li>CSV——处理CSV文件 
</li><li>Exec——安全地处理外部进程 
</li><li>Finder——实现类似UNIX find命令的功能 
</li><li>I18n——处理软件的I18n功能 
</li><li>Id——生成id号功能 
</li><li>Javaflow——捕捉程序运行状态 
</li><li>JCI——java编译接口 
</li><li>OpenPGP——处理加密方法OpenPGP.  
</li><li>Pipeline——处理类似工作队列的管道工具 
</li><li>Proxy——生成动态代理</li></ul></h4>
		<h4 class="TextColor1" style="MARGIN-BOTTOM: 0px">－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－org.apache.commons.beanutils.PropertyUtils;<br />copyProperties(a,b);//把相同类型b的属性赋值给a<br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</h4>
		<h4 class="TextColor1" style="MARGIN-BOTTOM: 0px">转载：org.apache.commons包</h4>
		<div id="msgcns!F319B9AFFE33A988!201">
				<div>原文请见：<a href="http://junglesong.yculblog.com/post.976376.html"><font color="#495828">http://junglesong.yculblog.com/post.976376.html</font></a></div>
				<div>
						<font color="#495828">
						</font> </div>
				<div>在org.apache.commons包中提供了的一系列能简化一些编程过程中常见问题的共通函数和类，使程序员能把主要精力集中在<br />构架，业务实现和优化而不是具体实现及验证上，一言以蔽之，它能使我们避免重复的发明车轮。<br /><br />org.apache.commons包的下载页面在:<br /><a href="http://jakarta.apache.org/site/downloads/downloads_commons-lang.cgi"><font color="#5f9ea0">http://jakarta.apache.org/site/downloads/downloads_commons-lang.cgi</font></a><br />其中源码大家可以借鉴一下，我觉得很有参考价值，尤其是有些函数在不用正则表达式下取得的效果。<br /><br />取得commons-lang-2.1.jar后加入自己工程的lib目录就可以了.如果用户不允许使用commons，那末打开其源码把具体函数加入自己的代码也可以，当然需要尊重人家的知识产权。<br /><br />以下代码经过测试,测试环境(WinXp+Eclipse3.1+JDK1.5+commons-lang-2.1)，我在有些地方修改了一下。<br /><br /><br />Jakarta Commons Cookbook—01—Manipulating Text 
<p>Commons之字符串操作<br />要利用Jakarta Commons来进行字符串操作,首先需要加载需要用到的包:<br />import org.apache.commons.lang.StringUtils;<br />import org.apache.commons.lang.WordUtils;</p><p>以下是StringUtils的各项用法<br /><strong>1.空字符串检查</strong><br />使用函数: StringUtils.isBlank(testString)<br />函数介绍: 当testString为空,长度为零或者仅由空白字符(whitespace)组成时,返回True;否则返回False<br />例程:<br />    String test = "";<br />    String test2 = "\n\n\t";<br />    String test3 = null;<br />    String test4 = "Test";</p><p>    System.out.println( "test blank? " + StringUtils.isBlank( test ) );<br />    System.out.println( "test2 blank? " + StringUtils.isBlank( test2 ) );<br />    System.out.println( "test3 blank? " + StringUtils.isBlank( test3 ) );<br />    System.out.println( "test4 blank? " + StringUtils.isBlank( test4 ) );<br />输出如下:<br />test blank? true<br />test2 blank? true<br />test3 blank? true<br />test4 blank? False<br />函数StringUtils.isNotBlank(testString)的功能与StringUtils.isBlank(testString)相反.</p><p><br /><strong>2.清除空白字符<br /></strong>使用函数: StringUtils.trimToNull(testString)<br />函数介绍:清除掉testString首尾的空白字符,如果仅testString全由空白字符<br />(whitespace)组成则返回null<br />例程:<br />    String test1 = "\t";<br />    String test2 = "  A  Test  ";<br />    String test3 = null;</p><p>    System.out.println( "test1 trimToNull: " + StringUtils.trimToNull( test1 ) );<br />    System.out.println( "test2 trimToNull: " + StringUtils.trimToNull( test2 ) );<br />    System.out.println( "test3 trimToNull: " + StringUtils.trimToNull( test3 ) );</p><p>输出如下:<br />test1 trimToNull: null<br />test2 trimToNull: A  Test<br />test3 trimToNull: null</p><p>注意：函数StringUtils.trim(testString)与<br />StringUtils.trimToNull(testString)功能类似，但testString由空白字符<br />(whitespace)组成时返回零长度字符串。</p><p><br /><strong>3.取得字符串的缩写</strong><br />使用函数: StringUtils.abbreviate(testString,width)和StringUtils.abbreviate(testString,offset，width)<br />函数介绍:在给定的width内取得testString的缩写,当testString的长度小于width则返回原字符串.<br />例程:<br />    String test = "This is a test of the abbreviation.";<br />    String test2 = "Test";</p><p>    System.out.println( StringUtils.abbreviate( test, 15 ) );<br />    System.out.println( StringUtils.abbreviate( test, 5,15 ) );<br />    System.out.println( StringUtils.abbreviate( test2, 10 ) );<br />输出如下:<br />This is a te...<br />...is a test...<br />Test</p><p><strong>4.劈分字符串</strong><br />使用函数: StringUtils.split(testString,splitChars,arrayLength)<br />函数介绍:splitChars中可以包含一系列的字符串来劈分testString,并可以设定得<br />到数组的长度.注意设定长度arrayLength和劈分字符串间有抵触关系,建议一般情况下<br />不要设定长度.<br />例程:<br />    String input = "A b,c.d|e";<br />    String input2 = "Pharmacy, basketball funky";<br />    </p><p>    String[] array1 = StringUtils.split( input, " ,.|");<br />    String[] array2 = StringUtils.split( input2, " ,", 2 );</p><p><br />    System.out.println( ArrayUtils.toString( array1 ) );<br />    System.out.println( ArrayUtils.toString( array2 ) );<br />输出如下:<br />{A,b,c,d,e}<br />{Pharmacy,basketball funky}</p><p><strong>5.查找嵌套字符串</strong><br />使用函数:StringUtils.substringBetween(testString,header,tail)<br />函数介绍：在testString中取得header和tail之间的字符串。不存在则返回空<br />例程：<br />    String htmlContent = "ABC1234ABC4567";<br />    System.out.println(StringUtils.substringBetween(htmlContent, "1234", "4567"));<br />    System.out.println(StringUtils.substringBetween(htmlContent, "12345", "4567"));<br />输出如下：<br />    ABC<br />    null</p><p><br /><strong>6.去除尾部换行符</strong><br />使用函数:StringUtils.chomp(testString)<br />函数介绍:去除testString尾部的换行符<br />例程:<br />    String input = "Hello\n";<br />    System.out.println( StringUtils.chomp( input ));<br />    String input2 = "Another test\r\n";<br />    System.out.println( StringUtils.chomp( input2 ));<br />输出如下:<br />    Hello<br />    Another test</p><p><br /><strong>7.重复字符串</strong><br />使用函数:StringUtils.repeat(repeatString,count)<br />函数介绍:得到将repeatString重复count次后的字符串<br />例程:<br />    System.out.println( StringUtils.repeat( "*", 10));<br />    System.out.println( StringUtils.repeat( "China ", 5));<br />输出如下:<br />    **********<br />    China China China China China </p><p>其他函数:StringUtils.center( testString, count,repeatString );<br />函数介绍:把testString插入将repeatString重复多次后的字符串中间,得到字符串<br />的总长为count<br />例程:<br />    System.out.println( StringUtils.center( "China", 11,"*"));<br />输出如下:<br />    ***China***</p><p><br /><strong>8.颠倒字符串</strong><br />使用函数:StringUtils.reverse(testString)<br />函数介绍:得到testString中字符颠倒后的字符串<br />例程:<br />    System.out.println( StringUtils.reverse("ABCDE"));<br />输出如下:<br />    EDCBA</p><p><strong>9.判断字符串内容的类型<br /></strong>函数介绍:<br />StringUtils.isNumeric( testString ) :如果testString全由数字组成返回True<br />StringUtils.isAlpha( testString ) :如果testString全由字母组成返回True<br />StringUtils.isAlphanumeric( testString ) :如果testString全由数字或数字组<br />成返回True<br />StringUtils.isAlphaspace( testString )  :如果testString全由字母或空格组<br />成返回True</p><p>例程:<br />    String state = "Virginia";<br />    System.out.println( "Is state number? " + StringUtils.isNumeric(<br />state ) );<br />    System.out.println( "Is state alpha? " + StringUtils.isAlpha( state )<br />);<br />    System.out.println( "Is state alphanumeric? " +StringUtils.isAlphanumeric( state ) );<br />    System.out.println( "Is state alphaspace? " + StringUtils.isAlphaSpace( state ) );<br />输出如下:<br />    Is state number? false<br />    Is state alpha? true<br />    Is state alphanumeric? true<br />    Is state alphaspace? true</p><p><strong>10.取得某字符串在另一字符串中出现的次数<br /></strong>使用函数:StringUtils.countMatches(testString,seqString)<br />函数介绍:取得seqString在testString中出现的次数,未发现则返回零<br />例程:<br />    System.out.println(StringUtils.countMatches( "Chinese People", "e"<br />));<br />输出:<br />    4</p><p><strong>11.部分截取字符串</strong><br />使用函数:<br />StringUtils.substringBetween(testString,fromString,toString ):取得两字符<br />之间的字符串<br />StringUtils.substringAfter( ):取得指定字符串后的字符串<br />StringUtils.substringBefore( )：取得指定字符串之前的字符串<br />StringUtils.substringBeforeLast( )：取得最后一个指定字符串之前的字符串<br />StringUtils.substringAfterLast( )：取得最后一个指定字符串之后的字符串</p><p>函数介绍：上面应该都讲明白了吧。<br />例程：<br />    String formatted = " 25 * (30,40) [50,60] | 30";<br />    System.out.print("N0: " + StringUtils.substringBeforeLast( formatted, "*" ) );<br />    System.out.print(", N1: " + StringUtils.substringBetween( formatted, "(", "," ) );<br />    System.out.print(", N2: " + StringUtils.substringBetween( formatted, ",", ")" ) );<br />    System.out.print(", N3: " + StringUtils.substringBetween( formatted, "[", "," ) );<br />    System.out.print(", N4: " + StringUtils.substringBetween( formatted, ",", "]" ) );<br />    System.out.print(", N5: " + StringUtils.substringAfterLast( formatted, "|" ) );<br />输出如下：<br />    N0:  25 , N1: 30, N2: 40, N3: 50, N4: 40) [50,60, N5:  30</p></div>
		</div>
<img src ="http://www.blogjava.net/renyangok/aggbug/74008.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-10-09 11:02 <a href="http://www.blogjava.net/renyangok/articles/74008.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JfreeChart学习总结</title><link>http://www.blogjava.net/renyangok/articles/63942.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Wed, 16 Aug 2006 08:53:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/63942.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/63942.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/63942.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/63942.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/63942.html</trackback:ping><description><![CDATA[
		<p>
				<u>
						<font color="#800080">
								<a href="/ltc603/archive/2006/08/16/63834.html">http://www.blogjava.net/ltc603/archive/2006/08/16/63834.html</a>
						</font>
				</u>
				<a class="singleposttitle" id="viewpost1_TitleUrl" href="/ltc603/archive/2006/08/16/63834.html">
						<font color="#223355">
						</font>
				</a>
		</p>
<img src ="http://www.blogjava.net/renyangok/aggbug/63942.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-08-16 16:53 <a href="http://www.blogjava.net/renyangok/articles/63942.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Java＋POI 读写Excel文档&amp;向Excel中插入图片</title><link>http://www.blogjava.net/renyangok/articles/63889.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Wed, 16 Aug 2006 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/63889.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/63889.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/63889.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/63889.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/63889.html</trackback:ping><description><![CDATA[
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">一．<span lang="EN-US">POI</span>简介<span lang="EN-US"><?xml:namespace prefix = o /?><o:p></o:p></span></span>
				</strong>
		</p>
		<p>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">Jakarta POI</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">是<span lang="EN-US">apache</span>的子项目，目标是处理<span lang="EN-US">ole2</span>对象。它提供了一组操纵<span lang="EN-US">Windows</span>文档的<span lang="EN-US">Java API<o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; TEXT-INDENT: 21pt; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">目前比较成熟的是<span lang="EN-US">HSSF</span>接口，处理<span lang="EN-US">MS Excel</span>（<span lang="EN-US">97-2002</span>）对象。它不象我们仅仅是用<span lang="EN-US">csv</span>生成的没有格式的可以由<span lang="EN-US">Excel</span>转换的东西，而是真正的<span lang="EN-US">Excel</span>对象，你可以控制一些属性如<span lang="EN-US">sheet,cell</span>等等。<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">二．<span lang="EN-US">HSSF</span>概况<span lang="EN-US"><o:p></o:p></span></span>
				</strong>
		</p>
		<p style="BACKGROUND: white 0% 50%; TEXT-INDENT: 21pt; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">HSSF</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">是<span lang="EN-US">Horrible SpreadSheet Format</span>的缩写，也即“讨厌的电子表格格式”。 也许<span lang="EN-US">HSSF</span>的名字有点滑稽，就本质而言它是一个非常严肃、正规的<span lang="EN-US">API</span>。通过<span lang="EN-US">HSSF</span>，你可以用纯<span lang="EN-US">Java</span>代码来读取、写入、修改<span lang="EN-US">Excel</span>文件。<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; TEXT-INDENT: 21pt; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">HSSF</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">为读取操作提供了两类<span lang="EN-US">API</span>：<span lang="EN-US">usermodel</span>和<span lang="EN-US">eventusermodel</span>，即“用户模型”和“事件<span lang="EN-US">-</span>用户模型”。前者很好理解，后者比较抽象，但操作效率要高得多。</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">三．开始编码<span lang="EN-US"><o:p></o:p></span></span>
				</strong>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">1</span>
				</strong>
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">．</span>
				</strong>
				<strong>
						<span style="FONT-SIZE: 14pt; FONT-FAMILY: 楷体_GB2312">准备工作<span lang="EN-US" style="COLOR: black"><o:p></o:p></span></span>
				</strong>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">要求<span lang="EN-US">:JDK 1.4+POI</span>开发包<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">可以到</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<a href="http://www.apache.org/dyn/closer.cgi/jakarta/poi/" target="_blank">
										<span style="COLOR: black">http://www.apache.org/dyn/closer.cgi/jakarta/poi/</span>
								</a>
						</span>
				</b>
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">最新的<span lang="EN-US">POI</span>工具包<span lang="EN-US"><o:p></o:p></span></span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">2</span>
				</strong>
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">．</span>
				</strong>
				<span class="tpccontent1">
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">EXCEL</span>
						</b>
				</span>
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">结构</span>
						</b>
				</span>
				<span class="tpccontent1">
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
										<o:p>
										</o:p>
								</span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">HSSFWorkbook excell</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">文档对象介绍<span lang="EN-US"><br />HSSFSheet excell</span>的表单<span lang="EN-US"><br />HSSFRow excell</span>的行<span lang="EN-US"><br />HSSFCell excell</span>的格子单元<span lang="EN-US"><br />HSSFFont excell</span>字体<span lang="EN-US"><br />HSSFName </span>名称<span lang="EN-US"><br />HSSFDataFormat </span>日期格式<span lang="EN-US"><br /></span>在<span lang="EN-US">poi1.7</span>中才有以下<span lang="EN-US">2</span>项：<span lang="EN-US"><br />HSSFHeader sheet</span>头<span lang="EN-US"><br />HSSFFooter sheet</span>尾<span lang="EN-US"><br /></span>和这个样式<span lang="EN-US"><br />HSSFCellStyle cell</span>样式<span lang="EN-US"><br /></span>辅助操作包括<span lang="EN-US"><br />HSSFDateUtil </span>日期<span lang="EN-US"><br />HSSFPrintSetup </span>打印<span lang="EN-US"><br />HSSFErrorConstants </span>错误信息表</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">3</span>
				</strong>
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">．具体用法实例</span>
				</strong>
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">（采用</span>
						</b>
				</span>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">usermodel</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">）</span>
				</b>
				<span class="tpccontent1">
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
										<o:p>
										</o:p>
								</span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">如何读<span lang="EN-US">Excel<o:p></o:p></span></span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">读取<span lang="EN-US">Excel</span>文件时，首先生成一个<span lang="EN-US">POIFSFileSystem</span>对象，由<span lang="EN-US">POIFSFileSystem</span>对象构造一个<span lang="EN-US">HSSFWorkbook</span>，该<span lang="EN-US">HSSFWorkbook</span>对象就代表了<span lang="EN-US">Excel</span>文档。下面代码读取上面生成的<span lang="EN-US">Excel</span>文件写入的消息字串： </span>
						</b>
				</span>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<br />
								<span class="tpccontent1">
										<span>try{<br />   POIFSFileSystem fs=new POIFSFileSystem(new FileInputStream("d:/workbook.xls")); <br />   HSSFWorkbook wb = new HSSFWorkbook(fs); <br />   HSSFSheet sheet = wb.getSheetAt(0); <br />   HSSFRow row = sheet.getRow(0); <br />   HSSFCell cell = row.getCell((short) 0); <br />   String msg = cell.getStringCellValue(); <br />   System.out.println(msg);<br />  }catch(Exception e){<br />   e.printStackTrace();<br />  }</span>
								</span>
						</span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">如何写<span lang="EN-US">excel</span>，<span lang="EN-US"><o:p></o:p></span></span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">将<span lang="EN-US">excel</span>的第一个表单第一行的第一个单元格的值写成“<span lang="EN-US">a test</span>”。<span lang="EN-US"><o:p></o:p></span></span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream("workbook.xls"));<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>HSSFWorkbook wb = new HSSFWorkbook(fs);<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>HSSFSheet sheet = wb.getSheetAt(0);<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>HSSFRow row = sheet.getRow(0);<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>HSSFCell cell = row.getCell((short)0);<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>cell.setCellValue("a test");<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>// Write the output to a file<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>FileOutputStream fileOut = new FileOutputStream("workbook.xls");<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<span>    </span>wb.write(fileOut);<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; TEXT-INDENT: 28.5pt; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">fileOut.close();<o:p></o:p></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">4</span>
				</strong>
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">．</span>
				</strong>
				<span class="tpccontent1">
						<b>
								<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">可参考文档</span>
						</b>
				</span>
				<span class="tpccontent1">
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
										<o:p>
										</o:p>
								</span>
						</b>
				</span>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">POI</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">主页：<span lang="EN-US"><a href="http://jakarta.apache.org/poi/"><span style="COLOR: black">http://jakarta.apache.org/poi/</span></a></span>，<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">初学者如何快速上手使用<span lang="EN-US">POI HSSF<o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">
								<a href="http://jakarta.apache.org/poi/hssf/quick-guide.html">
										<span style="COLOR: black">http://jakarta.apache.org/poi/hssf/quick-guide.html</span>
								</a>
						</span>
				</b>
				<b>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">。<span lang="EN-US"><o:p></o:p></span></span>
				</b>
		</p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">里面有很多例子代码，可以很方便上手。<span lang="EN-US"><o:p></o:p></span></span>
						<br />
						<br />5、中文乱码问题<br /><br /></strong> //把List expItems,写到EXCEL文件中<br />  FileOutputStream fileOut = new FileOutputStream(filePath);<br />  HSSFWorkbook wb = new HSSFWorkbook();// HSSFWorkbook<br />  HSSFSheet sheet = wb.createSheet();// <br /><font style="BACKGROUND-COLOR: #ff1493">  wb.setSheetName(0,“实验项目列表－－中文测试“,HSSFWorkbook.ENCODING_UTF_16);</font><br />  HSSFRow row = sheet.createRow((short) 0);<br />  HSSFCell cell;<br />  Iterator iter = expItems.iterator();<br />  int i = 0;<br />  while (iter.hasNext()) {<br />   cell = row.createCell((short) i);<br /><font style="BACKGROUND-COLOR: #ff1493">   cell.setEncoding(HSSFCell.ENCODING_UTF_16);</font><br />   cell.setCellValue(iter.next().toString());<br />   i++;<br />  }<br />  wb.write(fileOut);<br />  fileOut.close();<br /> }<br /></p>
		<p style="BACKGROUND: white 0% 50%; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">四．使用心得<span lang="EN-US"><o:p></o:p></span></span>
				</strong>
		</p>
		<p style="BACKGROUND: white 0% 50%; TEXT-INDENT: 21pt; moz-background-clip: initial; moz-background-origin: initial; moz-background-inline-policy: initial">
				<strong>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">POI HSSF</span>
						<span style="FONT-SIZE: 14pt; COLOR: black; FONT-FAMILY: 楷体_GB2312">的<span lang="EN-US">usermodel</span>包把<span lang="EN-US">Excel</span>文件映射成我们熟悉的结构，诸如<span lang="EN-US">Workbook</span>、<span lang="EN-US">Sheet</span>、<span lang="EN-US">Row</span>、<span lang="EN-US">Cell</span>等，它把整个结构以一组对象的形式保存在内存之中，便于理解，操作方便，基本上能够满足我们的要求，所以说这个一个不错的选择。</span>
						<br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br /></strong>前面已经讲过利用POI读写Excel，下面是一个用POI向Excel中插入图片的例子。<br /><br /><span class="postbody">官方文档： <br />Images are part of the drawing support. To add an image just call createPicture() on the drawing patriarch. At the time of writing the following types are supported: <br />PNG <br />JPG <br />DIB <br />It is not currently possible to read existing images and it should be noted that any existing drawings may be erased once you add a image to a sheet. <br /><br />// Create the drawing patriarch. This is the top level container for <br />// all shapes. This will clear out any existing shapes for that sheet. </span><br /><br /><span class="postbody">通过HSSFPatriarch类createPicture方法的在指定的wb中的sheet创建图片,它接受二个参数，第一个是HSSFClientAnchor，设定图片的大小。<br /><br /></span>package com.poi.hssf.test;<br /><br />import java.io.FileOutputStream;<br />import java.io.File;<br />import java.io.ByteArrayOutputStream;<br />import java.io.IOException;<br /><br />import java.awt.image.BufferedImage;<br />import javax.imageio.*;<br /><br />import org.apache.poi.hssf.usermodel.HSSFWorkbook;<br />import org.apache.poi.hssf.usermodel.HSSFSheet;<br />import org.apache.poi.hssf.usermodel.HSSFPatriarch;<br />import org.apache.poi.hssf.usermodel.HSSFClientAnchor;;<br /><br />public class TestPOI { <br /><br />    public static void main(String[] args) { <br />            FileOutputStream fileOut = null; <br />            BufferedImage bufferImg =null; <br />            BufferedImage bufferImg1 = null; <br />            try{ <br />                <br />          //先把读进来的图片放到一个ByteArrayOutputStream中，以便产生ByteArray <br />          ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); <br />          ByteArrayOutputStream byteArrayOut1 = new ByteArrayOutputStream(); <br />          bufferImg = ImageIO.read(new File("d:/PieChart.jpg")); <br />          bufferImg1 = ImageIO.read(new File("d:/fruitBarChart.jpg")); <br />          ImageIO.write(bufferImg,"jpg",byteArrayOut); <br />          ImageIO.write(bufferImg1,"jpg",byteArrayOut1); <br />          <br />        //创建一个工作薄 <br />        HSSFWorkbook wb = new HSSFWorkbook(); <br />        HSSFSheet sheet1 = wb.createSheet("new sheet"); <br />        //HSSFRow row = sheet1.createRow(2); <br />        HSSFPatriarch patriarch = sheet1.createDrawingPatriarch(); <br />        HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,512,255,(short) 1,1,(short)10,20); <br />        HSSFClientAnchor anchor1 = new HSSFClientAnchor(0,0,512,255,(short) 2,30,(short)10,60); <br />        anchor1.setAnchorType(2);<br />        //插入图片<br />        patriarch.createPicture(anchor , wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG)); <br />        patriarch.createPicture(anchor1 , wb.addPicture(byteArrayOut1.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG)); <br />        <br />            fileOut = new FileOutputStream("d:/workbook.xls"); <br />            //写入excel文件<br />            wb.write(fileOut); <br />            fileOut.close(); <br />        <br />            }catch(IOException io){ <br />                    io.printStackTrace(); <br />                    System.out.println("io erorr :  "+ io.getMessage()); <br />            } finally <br />            { <br />                if (fileOut != null) <br />                {<br />                           <br />                    try { <br />                              fileOut.close(); <br />                         } <br />                    catch (IOException e)<br />                    { <br />                            // TODO Auto-generated catch block <br />                            e.printStackTrace(); <br />                     } <br />                } <br />            }<br />    }<br />}<br /></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/63889.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-08-16 13:52 <a href="http://www.blogjava.net/renyangok/articles/63889.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4J 最佳实践之全能配置文件 </title><link>http://www.blogjava.net/renyangok/articles/63855.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Wed, 16 Aug 2006 03:38:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/63855.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/63855.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/63855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/63855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/63855.html</trackback:ping><description><![CDATA[下面给出得Log4J配置文件实现了输出到控制台，文件，回滚文件，发送日志邮件，输出到数据库日志表，自定义标签等全套功能。<br /><br />log4j.rootLogger=DEBUG,CONSOLE,A1,im<br />#DEBUG,CONSOLE,FILE,ROLLING_FILE,MAIL,DATABASE<br /><br />log4j.addivity.org.apache=true<br /><br /><br />###################<br /># Console Appender<br />###################<br />log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender<br />log4j.appender.Threshold=DEBUG<br />log4j.appender.CONSOLE.Target=System.out<br />log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout<br />log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br />#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n<br /><br /><br />#####################<br /># File Appender<br />#####################<br />log4j.appender.FILE=org.apache.log4j.FileAppender<br />log4j.appender.FILE.File=file.log<br />log4j.appender.FILE.Append=false<br />log4j.appender.FILE.layout=org.apache.log4j.PatternLayout<br />log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br /># Use this layout for LogFactor 5 analysis<br /><br /><br /><br />########################<br /># Rolling File<br />########################<br />log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender<br />log4j.appender.ROLLING_FILE.Threshold=ERROR<br />log4j.appender.ROLLING_FILE.File=rolling.log<br />log4j.appender.ROLLING_FILE.Append=true<br />log4j.appender.ROLLING_FILE.MaxFileSize=10KB<br />log4j.appender.ROLLING_FILE.MaxBackupIndex=1<br />log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout<br />log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br /><br /><br />####################<br /># Socket Appender<br />####################<br />log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender<br />log4j.appender.SOCKET.RemoteHost=localhost<br />log4j.appender.SOCKET.Port=5001<br />log4j.appender.SOCKET.LocationInfo=true<br /># Set up for Log Facter 5<br />log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout<br />log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n<br /><br /><br />########################<br /># Log Factor 5 Appender<br />########################<br />log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender<br />log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000<br /><br /><br />########################<br /># SMTP Appender<br />#######################<br />log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender<br />log4j.appender.MAIL.Threshold=FATAL<br />log4j.appender.MAIL.BufferSize=10<br />log4j.appender.MAIL.From=chenyl@hollycrm.com<br />log4j.appender.MAIL.SMTPHost=mail.hollycrm.com<br />log4j.appender.MAIL.Subject=Log4J Message<br />log4j.appender.MAIL.To=chenyl@hollycrm.com<br />log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout<br />log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br /><br /><br />########################<br /># JDBC Appender<br />#######################<br />log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender<br />log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test<br />log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver<br />log4j.appender.DATABASE.user=root<br />log4j.appender.DATABASE.password=<br />log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')<br />log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout<br />log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br /><br /><br />log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender<br />log4j.appender.A1.File=SampleMessages.log4j<br />log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'<br />log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout<br /><br />###################<br />#自定义Appender<br />###################<br />log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender<br /><br />log4j.appender.im.host = mail.cybercorlin.net<br />log4j.appender.im.username = username<br />log4j.appender.im.password = password<br />log4j.appender.im.recipient = corlin@cybercorlin.net<br /><br />log4j.appender.im.layout=org.apache.log4j.PatternLayout<br />log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br /><img src ="http://www.blogjava.net/renyangok/aggbug/63855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-08-16 11:38 <a href="http://www.blogjava.net/renyangok/articles/63855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于java使用FCKeditor</title><link>http://www.blogjava.net/renyangok/articles/58573.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 17 Jul 2006 07:20:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58573.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58573.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58573.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58573.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58573.html</trackback:ping><description><![CDATA[
		<div class="summary">
				<div class="right">
						<div class="help">
								<p>1.下载 <br />FCKeditor.java 2.3 (FCKeditot for java) <br />FCKeditor 2.2 (FCKeditor基本文件) </p>
								<p>2.建立项目:tomcat/webapps/FCKeditor </p>
								<p>3.FCKeditor.java 2.3解压后，把其中的web目录下的WEB-INF目录copy到FCKeditor下(里面有commons-fileupload.jar, FCKeditor-2.3.jar,web.xml等几个文件), 把其中的src目录下的FCKeditor.tld文件copy到FCKeitor/WEB-INF/下 </p>
						</div>
				</div>
		</div>
		<p>
				<br />
		</p>
		<p>4.修改web.xml: <br />把SimpleUploader中的配置属性enabled定义为true(开启文件上传功能） <br />添加标签定义: <br />&lt;taglib&gt; <br />&lt;taglib-uri&gt;/FCKeditor&lt;/taglib-uri&gt; <br />&lt;taglib-location&gt;/WEB-INF/FCKeditor.tld&lt;/taglib-location&gt; <br />&lt;/taglib&gt; </p>
		<p>5.解压FCKeditor2.2后，把目录/editor和fckconfig.js, fckeditor.js, fckstyles.xml, fcktemplates.xml四个文件copy到/FCKeditor下 <br />删除目录/editor/_source, <br />删除/editor/filemanager/browser/default/connectors/下的所有文件 <br />删除/editor/filemanager/upload/下的所有文件 <br />删除/editor/lang/下的除了fcklanguagemanager.js, en.js, zh.js, zh-cn.js四个文件的所有文件 </p>
		<p>6.打开/FCKeditor/fckconfig.js <br />修改 FCKConfig.DefaultLanguage = 'zh-cn' ; <br />把FCKConfig.LinkBrowserURL等的值替换成以下内容： <br />FCKConfig.LinkBrowserURL =<br />    FCKConfig.BasePath + "filemanager/browser/default/browser.html?Connector=connectors/jsp/connector" ; <br /><br />FCKConfig.ImageBrowserURL =<br />    FCKConfig.BasePath + "filemanager/browser/default/browser.html?Type=Image&amp;Connector=connectors/jsp/connector" ;<br /><br />FCKConfig.FlashBrowserURL =<br />    FCKConfig.BasePath + "filemanager/browser/default/browser.html?Type=Flash&amp;Connector=connectors/jsp/connector" ;<br /><br />FCKConfig.LinkUploadURL = FCKConfig.BasePath + 'filemanager/upload/simpleuploader?Type=File' ; <br />FCKConfig.FlashUploadURL = FCKConfig.BasePath + 'filemanager/upload/simpleuploader?Type=Flash' ; <br />FCKConfig.ImageUploadURL = FCKConfig.BasePath + 'filemanager/upload/simpleuploader?Type=Image' ; </p>
		<p>7.添加文件 /FCKeditor/test.jsp: <br />&lt;%@ page language="java" import="com.fredck.FCKeditor.*" %&gt; <br />&lt;%@ taglib uri="/FCKeditor" prefix="FCK" %&gt; <br />&lt;script type="text/javascript" src="/FCKeditor/fckeditor.js"&gt;&lt;/script&gt; </p>
		<p>&lt;%-- <br />三种方法调用FCKeditor <br />1.FCKeditor自定义标签 (必须加头文件 &lt;%@ taglib uri="/FCKeditor" prefix="FCK" %&gt; ) <br />2.script脚本语言调用 (必须引用 脚本文件 &lt;script type="text/javascript" src="/FCKeditor/fckeditor.js"&gt;&lt;/script&gt; ) <br />3.FCKeditor API 调用 (必须加头文件 &lt;%@ page language="java" import="com.fredck.FCKeditor.*" %&gt; ) <br />--%&gt; <br />&lt;%-- <br />&lt;form action="show.jsp" method="post" target="_blank"&gt; <br />&lt;FCK:editor id="content" basePath="/FCKeditor/" width="700" height="500" skinPath="/FCKeditor/editor/skins/silver/" <br />   toolbarSet = "Default" &gt; <br />input <br />&lt;/FCK:editor&gt; <br />&lt;input type="submit" value="Submit"&gt; <br />&lt;/form&gt; <br />--%&gt; </p>
		<p>&lt;form action="show.jsp" method="post" target="_blank"&gt; <br />&lt;table border="0" width="700"&gt;&lt;tr&gt;&lt;td&gt; <br />&lt;textarea id="content" name="content" style="WIDTH: 100%; HEIGHT: 400px"&gt;input&lt;/textarea&gt; <br />&lt;script type="text/javascript"&gt; <br />var oFCKeditor = new FCKeditor('content') ; <br />oFCKeditor.BasePath = "/FCKeditor/" ; <br />oFCKeditor.Height = 400; <br />oFCKeditor.ToolbarSet = "Default" ; <br />oFCKeditor.ReplaceTextarea(); <br />&lt;/script&gt; <br />&lt;input type="submit" value="Submit"&gt; <br />&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; <br />&lt;/form&gt; </p>
		<p>&lt;%-- <br />&lt;form action="show.jsp" method="post" target="_blank"&gt; <br />&lt;% <br />FCKeditor oFCKeditor ; <br />oFCKeditor = new FCKeditor( request, "content" ) ; <br />oFCKeditor.setBasePath( "/FCKeditor/" ) ; <br />oFCKeditor.setValue( "input" ); <br />out.println( oFCKeditor.create() ) ; <br />%&gt; <br />&lt;br&gt; <br />&lt;input type="submit" value="Submit"&gt; <br />&lt;/form&gt; <br />--%&gt; </p>
		<p>
				<br />添加文件/FCKeditor/show.jsp: <br />&lt;% <br />String content = request.getParameter("content"); <br />out.print(content); <br />%&gt; </p>
		<p>8.浏览 <a href="http://localhost:8080/FCKeditor/test.jsp">http://localhost:8080/FCKeditor/test.jsp </a><br />ok! </p>
		<p>9.上传遇到错误: internal server error 500, <br />直接引用servlet(com.fredck.FCKeditor.connector.ConnectorServlet)也遇到错误: "Provider org.apache.xalan.processor.TransformerFactoryImpl not found", <br />拷贝xalan.jar到lib目录就可以了 </p>
<img src ="http://www.blogjava.net/renyangok/aggbug/58573.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-17 15:20 <a href="http://www.blogjava.net/renyangok/articles/58573.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>laoer说天乙社区</title><link>http://www.blogjava.net/renyangok/articles/58092.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Fri, 14 Jul 2006 00:47:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58092.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58092.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58092.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58092.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58092.html</trackback:ping><description><![CDATA[
		<p>  <br />做一个好的社区论坛一直是我的理想，BBS-CS从1.0到现在的5.0用了2年时间，5.0在技术上、性能上都已经基本稳定，届此想对BBS-CS的开发思想、技术做一个说明。 </p>
		<p>在2000年的时候，我的个人网站“爱情工作室”就是使用我自己的写的论坛，当时是用PHP，功能上比较简单，主要是为了网站使用，后来我想把社区论坛单独拿出来，并且爱情工作室网站也只剩下了社区这一部分，所以就开始用PHP按照网易社区结构写了BBS-CS PHP 1.0的版本，后来这个版本一直没有更新，但JSP版BBS-CS 1.0到3.0的数据结构都是从PHP版本发展来的，2000年底我开始用JAVA，2001年就写了BBS-CS1.0，后来出了2.0，1.0、2.0的安装都不是很方便，并且SQL都是在JSP中，结构不好，2002年我写了BBS-CS3.0，此时数据库操作已经用JavaBean来封装，但是3.0的性能非常不好，2003年初我写了4.0，4.0的结构已经发生了完全的变化，主要是适应多种数据库和数据库访问均衡处理，性能大大增强，并且BBS-CS定名为“天乙社区”，今年下半年我写了5.0，5.0采用了Struts的框架，国际化内核，同时支持集群运行，全文检索等等。 </p>
		<p>有人可能会拿BBS-CS和Jive来比较，觉得BBS-CS是小儿科，但我想BBS-CS的设计模式虽然没有Jive那么复杂，但是在国际化、实用性、性能等方面并不差。 </p>
		<p>一、数据库设计 <br />BBS-CS从4.0开始，数据库结构发生了根本的变化，主要是对数据表作了负载均衡的处理，即一个功能不是使用一张表，而是使用多张同样结构的表，比如存放帖子的表有20张，这样做的目的是为了将数据库的查询压力分散到不同表中，其实道理很简单，如果一张表中存放100万条记录，和100张表，每个表存放1万条记录，查询效率是完全不一样的。具体程序中，比如一个版区的帖子往那个表中插，是由算法来实现的，算法会保证某个版区的帖子只会往某一个表中插入。 </p>
		<p>二、分页处理 <br />BBS-CS4.0和5.0都是支持多数据库的，现在支持的数据库有Mysql、Oracle和SQL Server，在分页处理上确实要花一些功夫，以前我看过很多关于分页的技术资料，处理分页的方法主要是有几个：1、用JDBC的本身特性，将数据全部取出，然后根据页码，每页记录数，对查询出的数据集的数据滚动，这个方法比较简单、通用，但是性能极差，如果一个百万级的数据表，将耗费巨大的系统资源，甚至宕机；2、和第一种比较类似，但不是查出所有数据，只查出数据的主键，对主键滚动，然后根据主键再次查找相对应的数据，产生集合，这种方法也是EJB中实体Bean查询数据的方法，但依然存在性能问题，因为数据过多的时候主键数据集也很大，而来用主键插找数据的是后又进行了多次数据库的执行操作，性能降低。在多种分页方法比较之后，BBS-CS还是决定采用数据自身特有的SQL语句来进行分页，比如Mysql使用limit，Oracle使用rownum，SQL Server使用Top，分页类是一个抽象类，每种数据库的分页实现方法都去继承这个抽象类，然后用一个工厂方法根据系统配置文件来产生分页类的实例，采用这样的分页方法，能都达到最佳的分页查询效率。 </p>
		<p>三、系统配置文件 <br />BBS-CS5.0的系统配置文件用了一个XML文件，在4.0的时候，系统的配置文件是采用properties文件来解决，后来我觉得properties的文件还是有很大的局限性，比如，不方便进行有数据库结构的数据进行配置，后来觉得XML文件是一个绝佳的方案，难怪现在很多产品的配置文件都是XML的:)，对于XML文件的解析，BBS-CS采用了jdom，jdom就是java+dom（详细资料<a href="http://www.jdom.org">http://www.jdom.org</a>），一个很方便的处理XML的软件包，在BBS-CS种对jdom的运用也不复杂，主要是用来解析bbscs.xml这个配置文件。系统解析bbscs.xml文件后，将这些系统信息保存在静态变量中，以供系统其他程序随时调用。 </p>
		<p>四、国际化与资源文件 <br />JAVA本身就是国际化的内部采用了Unicode的编码格式，而Struts的框架，更方便了国际化的应用，Struts会根据浏览器的Locale，自动调取相应的properties资源文件，在BBS-CS就是定义的app.peoperties文件，BBS-CS只定义了中文的资源包，即app_zh_CN.properties文件，当然只要将这个文件翻译成日文、韩文等等其他国家文字，即可实现BBS-CS多语言浏览。当然只有浏览多语言是不行，数据的保存也必须是通用的格式，BBS-CS采用了UTF-8的编码格式的保存数据，以解决多语言的问题，关于Unicode、UTF-8编码格式的资料、原理大家可以在网上查找资料，我在这里不多做讲解了。 </p>
		<p>五、编码问题 <br />在（四）中讲了国际化问题，但是如果不作处理，对中文显示处理都会有问题，要对app_zh_CN.propertie进行native2ascii的转换，这个命令是在jdk/bin下的，之后我们要做一个Servlet的过滤器，对所有的request对象进行编码的转换，com.laoer.bbscs.servlet.EncodingFilter就是BBS-CS的过滤器，它对request的编码格式进行了处理，定义为了UTF-8的编码格式。以前网上在看到过的一些文章上说，采用Servlet过滤器会有性能的下降，在我使用的感觉上来说，问题倒不是很大。 </p>
		<p>六、集群与Session处理 <br />BBS-CS5.0设计的时候考虑到了集群的应用，因为随着系统访问量和数据的不断增长，单台服务器是很难支撑的，所以要求系统能够用多台服务器来运行，跨服务器的Session就是一个很大的问题，大家都知道Session是生存与一个应用中的，跨应用，Session必然不能共享，现在JSP容器，包括Weblogic、Resin、Tomcat都可以进行集群应用，但是配制起来可能比较复杂，所以BBS-CS实现了自己的集群运用方案。实现的原理比较简单，主要是涉及了网络编程，在JAVA中，对象只要implements了java.io.Serializable这个接口，即可实现串行化，便可以在网络中传输，BBS-CS就是把需要在网络中传输的Session对象进行串行化，在多个服务器之间进行通讯，以达到服务器之间的Session同步，同时对于几台服务器的访问是负载均衡的。 <br />Session实现，BBS-CS在单服务器配制下是采用了应用的Session，而在机群方式下，是建立了自己的Session列表，Session是一个静态的HashTable，每个用户在登陆的时候会产生一个随机的sid，这个sid就是HashTable的key，而value则是一个HasMap，保存需要的对象。系统在运行期间会根据配置文件的Session超时时间定时对超时的Session进行清理。 </p>
		<p>七、静态变量与线程运用 <br />为了减少对数据库的访问，系统很多地方使用了静态变量来储存数据，比如，版区列表和信息是系统需要频繁访问的，如果每次都从数据库中读取，消耗是很大的，BBS-CS采用的方法是，一次性将数据库读出，放在一个静态的列表里（HashTable），以后再访问则从静态列表中取，而不是从数据库中取，如果版区信息发生变化，只要刷新这个静态变量就行了。 <br />通常在B/S结构下，系统的定时操作是比较困难的，因为B/S结构的软件是浏览器事件驱动的模型，而不是服务器事件驱动，在Unix/Linux下，通常是写一个脚本，然后用Crontab来跑，在win下可能就要用VB/VC/Delphi来写一个定时程序了。BBS-CS必须要做到跨品台和通用性，而线程和Sevlet提供很好的方法，一个web应用，可以在启动的时候按顺序的执行Servlet程序（在web.xml文件中定义），在Servlet中就可以启动一个线程，这个线程定时执行、休眠，便可以达到定时运行程序的目的，在BBS-CS中，清除超时Session、游客等等都是采用了线程定时执行的方式。</p>
<img src ="http://www.blogjava.net/renyangok/aggbug/58092.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-14 08:47 <a href="http://www.blogjava.net/renyangok/articles/58092.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[未读]简单的用lucene搜索的应用程序</title><link>http://www.blogjava.net/renyangok/articles/58089.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Fri, 14 Jul 2006 00:45:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58089.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58089.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58089.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58089.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58089.html</trackback:ping><description><![CDATA[
		<p>假设我们的电脑的目录中含有很多文本文档，我们需要查找哪些文档含有某个关键词。为了实现这种功能，我们首先利用 Lucene
对这个目录中的文档建立索引，然后在建立好的索引中搜索我们所要查找的文档。通过这个例子读者会对如何利用 Lucene
构建自己的搜索应用程序有个比较清楚的认识。 </p>
		<p>建立索引 </p>
		<p>为了对文档进行索引，Lucene 提供了五个基础的类，他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途： </p>
		<p>Document </p>
		<p>Document
是用来描述文档的，这里的文档可以指一个 HTML 页面，一封电子邮件，或者是一个文本文件。一个 Document 对象由多个 Field
对象组成的。可以把一个 Document 对象想象成数据库中的一个记录，而每个 Field 对象就是记录的一个字段。 </p>
		<p>Field </p>
		<p>Field 对象是用来描述一个文档的某个属性的，比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。 </p>
		<p>Analyzer </p>
		<p>在
一个文档被索引之前，首先需要对文档内容进行分词处理，这部分工作就是由 Analyzer 来做的。Analyzer
类是一个抽象类，它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给
IndexWriter 来建立索引。 </p>
		<p>IndexWriter </p>
		<p>IndexWriter 是 Lucene 用来创建索引的一个核心的类，他的作用是把一个个的 Document 对象加到索引中来。 </p>
		<p>Directory </p>
		<p>这个类代表了 Lucene 的索引的存储的位置，这是一个抽象类，它目前有两个实现，第一个是 FSDirectory，它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory，它表示一个存储在内存当中的索引的位置。 </p>
		<p>熟悉了建立索引所需要的这些类后，我们就开始对某个目录下面的文本文件建立索引了，清单1给出了对某个目录下的文本文件建立索引的源代码。 </p>
		<p>
				<br />清单 1. 对文本文件建立索引 </p>
		<p>package TestLucene; </p>
		<p>import java.io.File; <br />import java.io.FileReader; <br />import java.io.Reader; <br />import java.util.Date; </p>
		<p>import org.apache.lucene.analysis.Analyzer; <br />import org.apache.lucene.analysis.standard.StandardAnalyzer; <br />import org.apache.lucene.document.Document; <br />import org.apache.lucene.document.Field; <br />import org.apache.lucene.index.IndexWriter; </p>
		<p>
				<br />/** <br />* This class demonstrate the process of creating index with Lucene <br />* for text files <br />*/ <br />public class TxtFileIndexer { <br />public static void main(String[] args) throws Exception{ <br />//indexDir is the directory that hosts Lucene's index files <br />File indexDir = new File("D:\\luceneIndex"); <br />//dataDir is the directory that hosts the text files that to be indexed <br />File dataDir = new File("D:\\luceneData"); <br />Analyzer luceneAnalyzer = new StandardAnalyzer(); <br />File[] dataFiles = dataDir.listFiles(); <br />IndexWriter indexWriter = new IndexWriter(indexDir,luceneAnalyzer,true); <br />long startTime = new Date().getTime(); <br />for(int i = 0; i &lt; dataFiles.length; i++){ <br />if(dataFiles[i].isFile() &amp;&amp; dataFiles[i].getName().endsWith(".txt")){ <br />System.out.println( <br />"Indexing file " + dataFiles[i].getCanonicalPath()); <br />Document document = new Document(); <br />Reader txtReader = new FileReader(dataFiles[i]); <br />document.add( <br />Field.Text("path",dataFiles[i].getCanonicalPath())); <br />document.add(Field.Text("contents",txtReader)); <br />indexWriter.addDocument(document); <br />} <br />} <br />indexWriter.optimize(); <br />indexWriter.close(); <br />long endTime = new Date().getTime(); </p>
		<p>System.out.println("It takes " + (endTime - startTime) <br />+ " milliseconds to create index for <br />the files in directory " <br />+ dataDir.getPath()); <br />} <br />} </p>
		<p>在
清单1中，我们注意到类 IndexWriter 的构造函数需要三个参数，第一个参数指定了所创建的索引要存放的位置，他可以是一个 File
对象，也可以是一个 FSDirectory 对象或者 RAMDirectory 对象。第二个参数指定了 Analyzer
类的一个实现，也就是指定这个索引是用哪个分词器对文挡内容进行分词。第三个参数是一个布尔型的变量，如果为 true
的话就代表创建一个新的索引，为 false
的话就代表在原来索引的基础上进行操作。接着程序遍历了目录下面的所有文本文档，并为每一个文本文档创建了一个 Document
对象。然后把文本文档的两个属性：路径和内容加入到了两个 Field 对象中，接着在把这两个 Field 对象加入到 Document
对象中，最后把这个文档用 IndexWriter 类的 add
方法加入到索引中去。这样我们便完成了索引的创建。接下来我们进入在建立好的索引上进行搜索的部分。 </p>
		<p> </p>
		<p>搜索文档 </p>
		<p>利
用Lucene进行搜索就像建立索引一样也是非常方便的。在上面一部分中，我们已经为一个目录下的文本文档建立好了索引，现在我们就要在这个索引上进行搜
索以找到包含某个关键词或短语的文档。Lucene提供了几个基础的类来完成这个过程，它们分别是呢IndexSearcher, Term,
Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。 </p>
		<p>Query </p>
		<p>这是一个抽象类，他有多个实现，比如TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成Lucene能够识别的Query。 </p>
		<p>Term </p>
		<p>Term
是搜索的基本单位，一个Term对象有两个String类型的域组成。生成一个Term对象可以有如下一条语句来完成：Term term = new
Term(“fieldName”,”queryWord”);
其中第一个参数代表了要在文档的哪一个Field上进行查找，第二个参数代表了要查询的关键词。 </p>
		<p>TermQuery </p>
		<p>TermQuery
是抽象类Query的一个子类，它同时也是Lucene支持的最为基本的一个查询类。生成一个TermQuery对象由如下语句完成：
TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”));
它的构造函数只接受一个参数，那就是一个Term对象。 </p>
		<p>IndexSearcher </p>
		<p>IndexSearcher是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引，所以可以有多个IndexSearcher的实例在一个索引上进行操作。 </p>
		<p>Hits </p>
		<p>Hits是用来保存搜索的结果的。 </p>
		<p>介绍完这些搜索所必须的类之后，我们就开始在之前所建立的索引上进行搜索了，清单2给出了完成搜索功能所需要的代码。 </p>
		<p>
				<br />清单2 ：在建立好的索引上进行搜索 </p>
		<p>package TestLucene; </p>
		<p>import java.io.File; </p>
		<p>import org.apache.lucene.document.Document; <br />import org.apache.lucene.index.Term; <br />import org.apache.lucene.search.Hits; <br />import org.apache.lucene.search.IndexSearcher; <br />import org.apache.lucene.search.TermQuery; <br />import org.apache.lucene.store.FSDirectory; </p>
		<p>/** <br />* This class is used to demonstrate the <br />* process of searching on an existing <br />* Lucene index <br />* <br />*/ <br />public class TxtFileSearcher { <br />public static void main(String[] args) throws Exception{ <br />String queryStr = "lucene"; <br />//This is the directory that hosts the Lucene index <br />File indexDir = new File("D:\\luceneIndex"); <br />FSDirectory directory = FSDirectory.getDirectory(indexDir,false); <br />IndexSearcher searcher = new IndexSearcher(directory); <br />if(!indexDir.exists()){ <br />System.out.println("The Lucene index is not exist"); <br />return; <br />} <br />Term term = new Term("contents",queryStr.toLowerCase()); <br />TermQuery luceneQuery = new TermQuery(term); <br />Hits hits = searcher.search(luceneQuery); <br />for(int i = 0; i &lt; hits.length(); i++){ <br />Document document = hits.doc(i); <br />System.out.println("File: " + document.get("path")); <br />} <br />} <br />} </p>
		<p>在
清单2中，类IndexSearcher的构造函数接受一个类型为Directory的对象，Directory是一个抽象类，它目前有两个子类：
FSDirctory和RAMDirectory.
我们的程序中传入了一个FSDirctory对象作为其参数，代表了一个存储在磁盘上的索引的位置。构造函数执行完成后，代表了这个
IndexSearcher以只读的方式打开了一个索引。然后我们程序构造了一个Term对象，通过这个Term对象，我们指定了要在文档的内容中搜索包
含关键词”lucene”的文档。接着利用这个Term对象构造出TermQuery对象并把这个TermQuery对象传入到
IndexSearcher的search方法中进行查询，返回的结果保存在Hits对象中。最后我们用了一个循环语句把搜索到的文档的路径都打印了出
来。好了，我们的搜索应用程序已经开发完毕，怎么样，利用Lucene开发搜索应用程序是不是很简单。 <br /> <br /></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/58089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-14 08:45 <a href="http://www.blogjava.net/renyangok/articles/58089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Java的全文索引引擎Lucene（未读）</title><link>http://www.blogjava.net/renyangok/articles/54346.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Wed, 21 Jun 2006 12:22:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/54346.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/54346.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/54346.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/54346.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/54346.html</trackback:ping><description><![CDATA[
		<p>参考车东的《在应用中加入全文检索功能 ——基于Java的全文索引引擎Lucene简介》 </p>
		<p>方法 切词 索引 存储 用途 <br />Field.Text(String name, String value) Yes Yes Yes 切分词索引并存储，比如：标题，内容字段 <br />Field.Text(String name, Reader value) Yes Yes No 切分词索引不存储，比如：META信息， <br />不用于返回显示，但需要进行检索内容 <br />Field.Keyword(String name, String value) No Yes Yes 不切分索引并存储，比如：日期字段 <br />Field.UnIndexed(String name, String value) No No Yes 不索引，只存储，比如：文件路径 <br />Field.UnStored(String name, String value) Yes Yes No 只全文索引，不存储 </p>
		<p>好好看看这篇文章，很不错。 </p>
		<p>----------------------------------------------------------------------------------------<br />（李宇翻译，来自Lucene的帮助文档） </p>
		<p>绪论 </p>
		<p>Lucene提供了方便您创建自建查询的API，也通过QueryParser提供了强大的查询语言。 </p>
		<p>本文讲述Lucene的查询语句解析器支持的语法，Lucene的查询语句解析器是使用JavaCC工具生成的词法解析器，它将查询字串解析为Lucene Query对象。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />项（Term） </p>
		<p>一条搜索语句被拆分为一些项（term）和操作符（operator）。项有两种类型：单独项和短语。 </p>
		<p>单独项就是一个单独的单词，例如"test" ， "hello"。 </p>
		<p>短语是一组被双引号包围的单词，例如"hello dolly"。 </p>
		<p>多个项可以用布尔操作符连接起来形成复杂的查询语句（接下来您就会看到）。 </p>
		<p>注意：Analyzer建立索引时使用的解析器和解析单独项和短语时的解析器相同，因此选择一个不会受查询语句干扰的Analyzer非常重要。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />域（Field） </p>
		<p>Lucene支持域。您可以指定在某一个域中搜索，或者就使用默认域。域名及默认域是具体索引器实现决定的。 </p>
		<p>您可以这样搜索域：域名+":"+搜索的项名。 </p>
		<p>举个例子，假设某一个Lucene索引包含两个域，title和text，text是默认域。如果您想查找标题为"The Right Way"且含有"don't go this way"的文章，您可以输入： </p>
		<p>title:"The Right Way" AND text:go </p>
		<p>或者 </p>
		<p>title:"Do it right" AND right </p>
		<p>因为text是默认域，所以这个域名可以不行。 </p>
		<p>注意：域名只对紧接于其后的项生效，所以 </p>
		<p>title:Do it right </p>
		<p>只有"Do"属于title域。"it"和"right"仍将在默认域中搜索（这里是text域）。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />项修饰符（Term Modifiers） </p>
		<p>Lucene支持项修饰符以支持更宽范围的搜索选项。 </p>
		<p>用通配符搜索 </p>
		<p>Lucene支持单个与多个字符的通配搜索。 </p>
		<p>使用符号"?"表示单个任意字符的通配。 </p>
		<p>使用符号"*"表示多个任意字符的通配。 </p>
		<p>单个任意字符匹配的是所有可能单个字符。例如，搜索"text或者"test"，可以这样： </p>
		<p>te?t </p>
		<p>多个任意字符匹配的是0个及更多个可能字符。例如，搜索test, tests 或者 tester，可以这样： </p>
		<p>test* </p>
		<p>您也可以在字符窜中间使用多个任意字符通配符。 </p>
		<p>te*t </p>
		<p>注意：您不能在搜索的项开始使用*或者?符号。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />模糊查询 </p>
		<p>Lucene支持基于Levenshtein Distance与Edit Distance算法的模糊搜索。要使用模糊搜索只需要在单独项的最后加上符号"~"。例如搜索拼写类似于"roam"的项这样写： </p>
		<p>roam~ </p>
		<p>这次搜索将找到形如foam和roams的单词。 </p>
		<p>注意：使用模糊查询将自动得到增量因子（boost factor）为0.2的搜索结果. </p>
		<p> </p>
		<p> </p>
		<p>
				<br />邻近搜索(Proximity Searches) </p>
		<p>Lucene还支持查找相隔一定距离的单词。邻近搜索是在短语最后加上符号"~"。例如在文档中搜索相隔10个单词的"apache"和"jakarta"，这样写： </p>
		<p>"jakarta apache"~10 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />Boosting a Term </p>
		<p>Lucene
provides the relevance level of matching documents based on the terms
found. To boost a term use the caret, "^", symbol with a boost factor
(a number) at the end of the term you are searching. The higher the
boost factor, the more relevant the term will be. </p>
		<p>Lucene可以设置在搜索时匹配项的相似度。在项的最后加上符号"^"紧接一个数字（增量值），表示搜索时的相似度。增量值越高，搜索到的项相关度越好。 </p>
		<p>Boosting
allows you to control the relevance of a document by boosting its term.
For example, if you are searching for jakarta apache and you want the
term "jakarta" to be more relevant boost it using the ^ symbol along
with the boost factor next to the term. You would type: </p>
		<p>通过增量一个项可以控制搜索文档时的相关度。例如如果您要搜索jakarta apache，同时您想让"jakarta"的相关度更加好，那么在其后加上"^"符号和增量值，也就是您输入： </p>
		<p> </p>
		<p>jakarta^4 apache </p>
		<p>This will make documents with the term jakarta appear more relevant. You can also boost Phrase Terms as in the example: </p>
		<p>这将使得生成的doucment尽可能与jakarta相关度高。您也可以增量短语，象以下这个例子一样： </p>
		<p>"jakarta apache"^4 "jakarta lucene" </p>
		<p>By default, the boost factor is 1. Although, the boost factor must be positive, it can be less than 1 (i.e. .2) </p>
		<p>默认情况下，增量值是1。增量值也可以小于1（例如0.2），但必须是有效的。 </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br />布尔操作符 </p>
		<p>布尔操作符可将项通过逻辑操作连接起来。Lucene支持AND, "+", OR, NOT 和 "-"这些操作符。（注意：布尔操作符必须全部大写） </p>
		<p>OR </p>
		<p>OR操作符是默认的连接操作符。这意味着如果两个项之间没有布尔操作符，就是使用OR操作符。OR操作符连接两个项，意味着查找含有任意项的文档。这与集合并运算相同。符号||可以代替符号OR。 </p>
		<p>搜索含有"jakarta apache" 或者 "jakarta"的文档，可以使用这样的查询： </p>
		<p>"jakarta apache" jakarta </p>
		<p>或者 </p>
		<p>"jakarta apache" OR jakarta </p>
		<p> </p>
		<p> </p>
		<p>
				<br />AND </p>
		<p>AND操作符匹配的是两项同时出现的文档。这个与集合交操作相等。符号&amp;&amp;可以代替符号AND。 </p>
		<p>搜索同时含有"jakarta apache" 与 "jakarta lucene"的文档，使用查询： </p>
		<p>"jakarta apache" AND "jakarta lucene" </p>
		<p> </p>
		<p> </p>
		<p>
				<br />+ </p>
		<p>"+"操作符或者称为存在操作符，要求符号"+"后的项必须在文档相应的域中存在。 </p>
		<p>搜索必须含有"jakarta"，可能含有"lucene"的文档，使用查询： </p>
		<p>+jakarta apache </p>
		<p> </p>
		<p> </p>
		<p>
				<br />NOT </p>
		<p>NOT操作符排除那些含有NOT符号后面项的文档。这和集合的差运算相同。符号！可以代替符号NOT。 </p>
		<p>搜索含有"jakarta apache"，但是不含有"jakarta lucene"的文档，使用查询： </p>
		<p>"jakarta apache" NOT "jakarta lucene" </p>
		<p>注意：NOT操作符不能单独与项使用构成查询。例如，以下的查询查不到任何结果： </p>
		<p>NOT "jakarta apache" </p>
		<p> </p>
		<p> </p>
		<p>
				<br />- </p>
		<p>"-"操作符或者禁止操作符排除含有"-"后面的相似项的文档。 </p>
		<p>搜索含有"jakarta apache"，但不是"jakarta lucene"，使用查询： </p>
		<p>"jakarta apache" -"jakarta lucene" </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br />分组（Grouping） </p>
		<p>Lucene支持使用圆括号来组合字句形成子查询。这对于想控制查询布尔逻辑的人十分有用。 </p>
		<p>搜索含有"jakarta"或者"apache"，同时含有"website"的文档，使用查询： </p>
		<p>(jakarta OR apache) AND website </p>
		<p>这样就消除了歧义，保证website必须存在，jakarta和apache中之一也存在。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />转义特殊字符（Escaping Special Characters） </p>
		<p>Lucene支持转义特殊字符，因为特殊字符是查询语法用到的。现在，特殊字符包括 </p>
		<p>+ - &amp;&amp; || ! ( ) { } [ ] ^ " ~ * ? : \ </p>
		<p>转义特殊字符只需在字符前加上符号\,例如搜索(1+1):2，使用查询 </p>
		<p>\(1\+1\)\:2 </p>
		<p>
				<br />---------------------------------------<br />索引文件格式 </p>
		<p>本文定义了Lucene（版本1.3）用到的索引文件的格式。 </p>
		<p>Jakarta
Lucene是用Java写成的，同时有很多团体正在默默的用其他的程序语言来改写它。如果这些新的版本想和Jakarta
Lucene兼容，就需要一个与具体语言无关的Lucene索引文件格式。本文正是试图提供一个完整的与语言无关的Jakarta Lucene
1.3索引文件格式的规格定义。 </p>
		<p>随着Lucene不断发展，本文也应该更新。不同语言写成的Lucene实现版本应当尽力遵守文件格式，也必须产生本文的新版本。 </p>
		<p>本文同时提供兼容性批注，描述文件格式上与前一版本不同的地方。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />定义 </p>
		<p>Lucene中最基础的概念是索引（index），文档（document），域（field）和项（term）。 </p>
		<p>索引包含了一个文档的序列。 </p>
		<p>· 文档是一些域的序列。 </p>
		<p>· 域是一些项的序列。 </p>
		<p>· 项就是一个字串。 </p>
		<p>存在于不同域中的同一个字串被认为是不同的项。因此项实际是用一对字串表示的，第一个字串是域名，第二个是域中的字串。 </p>
		<p>倒排索引 </p>
		<p>为了使得基于项的搜索更有效率，索引中项是静态存储的。Lucene的索引属于索引方式中的倒排索引，因为对于一个项这种索引可以列出包含它的文档。这刚好是文档与项自然联系的倒置。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />域的类型 </p>
		<p>Lucene中，域的文本可能以逐字的非倒排的方式存储在索引中。而倒排过的域称为被索引过了。域也可能同时被存储和被索引。 </p>
		<p>域的文本可能被分解许多项目而被索引，或者就被用作一个项目而被索引。大多数的域是被分解过的，但是有些时候某些标识符域被当做一个项目索引是很有用的。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />段（Segment） </p>
		<p>Lucene索引可能由多个子索引组成，这些子索引成为段。每一段都是完整独立的索引，能被搜索。索引是这样作成的： </p>
		<p>1. 为新加入的文档创建新段。 </p>
		<p>2. 合并已经存在的段。 </p>
		<p>搜索时需要涉及到多个段和/或者多个索引，每一个索引又可能由一些段组成。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />文档号（Document Number） </p>
		<p>内部的来说，Lucene用一个整形（interger）的文档号来指示文档。第一个被加入到索引中的文档就是0号，顺序加入的文档将得到一个由前一个号码递增而来的号码。 </p>
		<p>注意文档号是可能改变的，所以在Lucene外部存储这些号码时必须小心。特别的，号码的改变的情况如下： </p>
		<p>·
只有段内的号码是相同的，不同段之间不同，因而在一个比段广泛的上下文环境中使用这些号码时，就必须改变它们。标准的技术是根据每一段号码多少为每一段分
配一个段号。将段内文档号转换到段外时，加上段号。将某段外的文档号转换到段内时，根据每段中可能的转换后号码范围来判断文档属于那一段，并减调这一段的
段号。例如有两个含5个文档的段合并，那么第一段的段号就是0，第二段段号5。第二段中的第三个文档，在段外的号码就是8。 </p>
		<p>· 文档删除后，连续的号码就出现了间断。这可以通过合并索引来解决，段合并时删除的文档相应也删掉了，新合并而成的段并没有号码间断。 </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br />绪论 </p>
		<p>索引段维护着以下的信息： </p>
		<p>· 域集合。包含了索引中用到的所有的域。 </p>
		<p>· 域值存储表。每一个文档都含有一个“属性－值”对的列表，属性即为域名。这个列表用来存储文档的一些附加信息，如标题，url或者访问数据库的一个ID。在搜索时存储域的集合可以被返回。这个表以文档号标识。 </p>
		<p>· 项字典。这个字典含有所有文档的所有域中使用过的的项，同时含有使用过它的文档的文档号，以及指向使用频数信息和位置信息的指针。 </p>
		<p>· 项频数信息。对于项字典中的每个项，这些信息包含含有这个项的文档的总数，以及每个文档中使用的次数。 </p>
		<p>· 项位置信息。对于项字典中的每个项，都存有在每个文档中出现的各个位置。 </p>
		<p>·
Normalization factors. For each field in each document, a value is
stored that is multiplied into the score for hits on that field.
标准化因子。对于文档中的每一个域，存有一个值，用来以后乘以这个这个域的命中数（hits）。 </p>
		<p>· 被删除的文档信息。这是一个可选文件，用来表明那些文档已经删除了。 </p>
		<p>接下来的各部分部分详细描述这些信息。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />文件的命名（File Naming） </p>
		<p>同属于一个段的文件拥有相同的文件名，不同的扩展名。扩展名由以下讨论的各种文件格式确定。 </p>
		<p>一般来说，一个索引存放一个目录，其所有段都存放在这个目录里，尽管我们不要求您这样做。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />基本数据类型（Primitive Types） </p>
		<p>Byte </p>
		<p>最基本的数据类型就是字节（byte，8位）。文件就是按字节顺序访问的。其它的一些数据类型也定义为字节的序列，文件的格式具有字节意义上的独立性。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />UInt32 </p>
		<p>32位无符号整数，由四个字节组成，高位优先。 </p>
		<p>UInt32 --&gt; &lt;Byte&gt;4 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />Uint64 </p>
		<p>64位无符号整数，由八字节组成，高位优先。 </p>
		<p>UInt64 --&gt; &lt;Byte&gt;8 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />VInt </p>
		<p>可变长的正整数类型，每字节的最高位表明还剩多少字节。每字节的低七位表明整数的值。因此单字节的值从0到127，两字节值从128到16,383，等等。 </p>
		<p>VInt 编码示例 </p>
		<p>Value <br />First byte <br />Second byte <br />Third byte </p>
		<p>0 <br />00000000 </p>
		<p> </p>
		<p>1 <br />00000001 </p>
		<p> </p>
		<p>2 <br />00000010 </p>
		<p> </p>
		<p>... </p>
		<p> </p>
		<p>
				<br />127 <br />01111111 </p>
		<p> </p>
		<p>128 <br />10000000 <br />00000001 </p>
		<p>
				<br />129 <br />10000001 <br />00000001 </p>
		<p>
				<br />130 <br />10000010 <br />00000001 </p>
		<p>
				<br />... </p>
		<p> </p>
		<p>
				<br />16,383 <br />11111111 <br />01111111 </p>
		<p>
				<br />16,384 <br />10000000 <br />10000000 <br />00000001 </p>
		<p>16,385 <br />10000001 <br />10000000 <br />00000001 </p>
		<p>... </p>
		<p> </p>
		<p> </p>
		<p>这种编码提供了一种在高效率解码时压缩数据的方法。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />Chars </p>
		<p>Lucene输出UNICODE字符序列，使用标准UTF-8编码。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />String </p>
		<p>Lucene输出由VINT和字符串组成的字串，VINT表示字串长，字符串紧接其后。 </p>
		<p>String --&gt; VInt, Chars </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br />索引包含的文件（Per-Index Files） </p>
		<p>这部分介绍每个索引包含的文件。 </p>
		<p>Segments文件 </p>
		<p>索引中活动的段存储在Segments文件中。每个索引只能含有一个这样的文件，名为"segments".这个文件依次列出每个段的名字和每个段的大小。 </p>
		<p>Segments --&gt; SegCount, &lt;SegName, SegSize&gt;SegCount </p>
		<p>SegCount, SegSize --&gt; UInt32 </p>
		<p>SegName --&gt; String </p>
		<p>SegName表示该segment的名字，同时作为索引其他文件的前缀。 </p>
		<p>SegSize是段索引中含有的文档数。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />Lock文件 </p>
		<p>有一些文件用来表示另一个进程在使用索引。 </p>
		<p>·
如果存在"commit.lock"文件，表示有进程在写"segments"文件和删除无用的段索引文件，或者表示有进程在读"segments"文件
和打开某些段的文件。在一个进程在读取"segments"文件段信息后，还没来得及打开所有该段的文件前，这个Lock文件可以防止另一个进程删除这些
文件。 </p>
		<p>· 如果存在"index.lock"文件，表示有进程在向索引中加入文档，或者是从索引中删除文档。这个文件防止很多文件同时修改一个索引。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />Deleteable文件 </p>
		<p>名为"deletetable"的文件包含了索引不再使用的文件的名字，这些文件可能并没有被实际的删除。这种情况只存在与Win32平台下，因为Win32下文件仍打开时并不能删除。 </p>
		<p>Deleteable --&gt; DelableCount, &lt;DelableName&gt;DelableCount </p>
		<p>DelableCount --&gt; UInt32 </p>
		<p>DelableName --&gt; String </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br />段包含的文件（Per-Segment Files） </p>
		<p>剩下的文件是每段中包含的文件，因此由后缀来区分。 </p>
		<p>域（Field） </p>
		<p>
				<br />域集合信息（Field Info） </p>
		<p>所有域名都存储在这个文件的域集合信息中，这个文件以后缀.fnm结尾。 </p>
		<p>FieldInfos (.fnm) --&gt; FieldsCount, &lt;FieldName, FieldBits&gt;FieldsCount </p>
		<p>FieldsCount --&gt; VInt </p>
		<p>FieldName --&gt; String </p>
		<p>FieldBits --&gt; Byte </p>
		<p>目前情况下，FieldBits只有使用低位，对于已索引的域值为1，对未索引的域值为0。 </p>
		<p>文件中的域根据它们的次序编号。因此域0是文件中的第一个域，域1是接下来的，等等。这个和文档号的编号方式相同。 </p>
		<p>
				<br />域值存储表（Stored Fields） </p>
		<p>域值存储表使用两个文件表示： </p>
		<p>1. 域索引（.fdx文件）。 </p>
		<p>如下，对于每个文档这个文件包含指向域值的指针： </p>
		<p>FieldIndex (.fdx) --&gt; &lt;FieldValuesPosition&gt;SegSize </p>
		<p>FieldValuesPosition --&gt; Uint64 </p>
		<p>FieldValuesPosition
指示的是某一文档的某域的域值在域值文件中的位置。因为域值文件含有定长的数据信息，因而很容易随机访问。在域值文件中，文档n的域值信息就存在n*8位
置处（The position of document n's field data is the Uint64 at n*8 in this
file.）。 </p>
		<p>2. 域值（.fdt文件）。 </p>
		<p>如下，每个文档的域值信息包含： </p>
		<p>FieldData (.fdt) --&gt; &lt;DocFieldData&gt;SegSize </p>
		<p>DocFieldData --&gt; FieldCount, &lt;FieldNum, Bits, Value&gt;FieldCount </p>
		<p>FieldCount --&gt; VInt </p>
		<p>FieldNum --&gt; VInt </p>
		<p>Bits --&gt; Byte </p>
		<p>Value --&gt; String </p>
		<p>目前情况下，Bits只有低位被使用，值为1表示域名被分解过，值为0表示未分解过。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />项字典（Term Dictionary） </p>
		<p>项字典用以下两个文件表示： </p>
		<p>1. 项信息（.tis文件）。 </p>
		<p>TermInfoFile (.tis)--&gt; TermCount, TermInfos </p>
		<p>TermCount --&gt; UInt32 </p>
		<p>TermInfos --&gt; &lt;TermInfo&gt;TermCount </p>
		<p>TermInfo --&gt; &lt;Term, DocFreq, FreqDelta, ProxDelta&gt; </p>
		<p>Term --&gt; &lt;PrefixLength, Suffix, FieldNum&gt; </p>
		<p>Suffix --&gt; String </p>
		<p>PrefixLength, DocFreq, FreqDelta, ProxDelta <br />--&gt; VInt </p>
		<p>项信息按项排序。项信息排序时先按项所属的域的文字顺序排序，然后按照项的字串的文字顺序排序。 </p>
		<p>项的字前缀往往是共同的，与字的后缀组成字。PrefixLength变量就是表示与前一项相同的前缀的字数。因此，如果前一个项的字是"bone"，后一个是"boy"的话，PrefixLength值为2，Suffix值为"y"。 </p>
		<p>FieldNum指明了项属于的域号，而域名存储在.fdt文件中。 </p>
		<p>DocFreg表示的是含有该项的文档的数量。 </p>
		<p>FreqDelta指明了项所属TermFreq变量在.frq文件中的位置。详细的说，就是指相对于前一个项的数据的位置偏移量（或者是0，表示文件中第一个项）。 </p>
		<p>ProxDelta指明了项所属的TermPosition变量在.prx文件中的位置。详细的说，就是指相对于前一个项的数据的位置偏移量（或者是0，表示文件中第一个项）。 </p>
		<p>2. 项信息索引（.tii文件）。 </p>
		<p>每个项信息索引文件包含.tis文件中的128个条目，依照条目在.tis文件中的顺序。这样设计是为了一次将索引信息读入内存能，然后使用它来随机的访问.tis文件。 </p>
		<p>这个文件的结构和.tis文件非常类似，只在每个条目记录上增加了一个变量IndexDelta。 </p>
		<p>TermInfoIndex (.tii)--&gt; IndexTermCount, TermIndices </p>
		<p>IndexTermCount --&gt; UInt32 </p>
		<p>TermIndices --&gt; &lt;TermInfo, IndexDelta&gt;IndexTermCount </p>
		<p>IndexDelta --&gt; VInt </p>
		<p>IndexDelta表示该项的TermInfo变量值在.tis文件中的位置。详细的讲，就是指相对于前一个条目的偏移量（或者是0，对于文件中第一个项）。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />项频数（Frequencies） </p>
		<p>.frq文件包含每一项的文档的列表，还有该项在对应文档中出现的频数。 </p>
		<p>FreqFile (.frq) --&gt; &lt;TermFreqs&gt;TermCount </p>
		<p>TermFreqs --&gt; &lt;TermFreq&gt;DocFreq </p>
		<p>TermFreq --&gt; DocDelta, Freq? </p>
		<p>DocDelta,Freq --&gt; VInt </p>
		<p>TermFreqs序列按照项来排序（依据于.tis文件中的项，即项是隐含存在的）。 </p>
		<p>TermFreq元组按照文档号升序排列。 </p>
		<p>DocDelta
决定了文档号和频数。详细的说，DocDelta/2表示相对于前一文档号的偏移量（或者是0，表示这是TermFreqs里面的第一项）。当
DocDelta是奇数时表示在该文档中频数为1，当DocDelta是偶数时，另一个VInt（Freq）就表示在该文档中出现的频数。 </p>
		<p>例如，假设某一项在文档7中出现一次，在文档11中出现了3次，在TermFreqs中就存在如下的VInts序列： </p>
		<p>15, 22, 3 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />项位置（Position） </p>
		<p>.prx文件包含了某文档中某项出现的位置信息的列表。 </p>
		<p>ProxFile (.prx) --&gt; &lt;TermPositions&gt;TermCount </p>
		<p>TermPositions --&gt; &lt;Positions&gt;DocFreq </p>
		<p>Positions --&gt; &lt;PositionDelta&gt;Freq </p>
		<p>PositionDelta --&gt; VInt </p>
		<p>TermPositions按照项来排序（依据于.tis文件中的项，即项是隐含存在的）。 </p>
		<p>Positions元组按照文档号升序排列。 </p>
		<p>PositionDelta是相对于前一个出现位置的偏移位置（或者为0，表示这是第一次在这个文档中出现）。 </p>
		<p>例如，假设某一项在某文档第4项出现，在另一个文档中第5项和第9项出现，将存在如下的VInt序列： </p>
		<p>4, 5, 4 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />标准化因子（Normalization Factor） </p>
		<p>.nrm文件包含了每个文档的标准化因子，标准化因子用来以后乘以这个这个域的命中数。 </p>
		<p>Norms (.nrm) --&gt; &lt;Byte&gt;SegSize </p>
		<p>每个字节记录一个浮点数。位0-2包含了3位的尾数部分，位3-8包含了5位的指数部分。 </p>
		<p>按如下规则可将这些字节转换为IEEE标准单精度浮点数： </p>
		<p>1. 如果该字节是0，就是浮点0； </p>
		<p>2. 否则，设置新浮点数的标志位为0； </p>
		<p>3. 将字节中的指数加上48后作为新的浮点数的指数； </p>
		<p>4. 将字节中的尾数映射到新浮点数尾数的高3位；并且 </p>
		<p>5. 设置新浮点数尾数的低21位为0。 </p>
		<p> </p>
		<p> </p>
		<p>
				<br />被删除的文档（Deleted Document） </p>
		<p>.del文件是可选的，只有在某段中存在删除操作后才存在： </p>
		<p>Deletions (.del) --&gt; ByteCount,BitCount,Bits </p>
		<p>ByteSize,BitCount --&gt; Uint32 </p>
		<p>Bits --&gt; &lt;Byte&gt;ByteCount </p>
		<p>ByteCount表示的是Bits列表中Byte的数量。典型的，它等于（SegSize/8）+1。 </p>
		<p>BitCount表示Bits列表中多少个已经被设置过了。 </p>
		<p>Bits列表包含了一些位（bit），顺序表示一个文档。当对应于文档号的位被设置了，就标志着这个文档已经被删除了。位的顺序是从低到高。因此，如果Bits包含两个字节，0x00和0x02，那么表示文档9已经删除了。 </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p> </p>
		<p>
				<br />局限性（Limitations） </p>
		<p>在以上的文件格式中，好几处都有限制项和文档的最大个数为32位数的极限，即接近于40亿。今天看来，这不会造成问题，但是，长远的看，可能造成问题。因此，这些极限应该或者换为UInt64类型的值，或者更好的，换为VInt类型的值（VInt值没有上限）。 </p>
		<p>有两处地方的代码要求必须是定长的值，他们是： </p>
		<p>1. FieldValuesPosition变量（存储于域索引文件中，.fdx文件）。它已经是一个UInt64型，所以不会有问题。 </p>
		<p>2.
TermCount变量（存储于项信息文件中，.tis文件）。这是最后输出到文件中的，但是最先被读取，因此是存储于文件的最前端
。索引代码先在这里写入一个0值，然后在其他文件输出完毕后覆盖这个值。所以无论它存储在什么地方，它都必须是一个定长的值，它应该被变成UInt64
型。 </p>
		<p>除此之外，所有的UInt值都可以换成VInt型以去掉限制。</p>
<img src ="http://www.blogjava.net/renyangok/aggbug/54346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-06-21 20:22 <a href="http://www.blogjava.net/renyangok/articles/54346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SmartUpload上传下载及文件名和文件内容中文问题</title><link>http://www.blogjava.net/renyangok/articles/51362.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Thu, 08 Jun 2006 07:17:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/51362.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/51362.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/51362.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/51362.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/51362.html</trackback:ping><description><![CDATA[
		<p>（共两篇文章，以－－－分隔）<br />一、安装篇 </p>
		<p>　　jspSmartUpload是由<a href="http://www.jspsmart.com">www.jspsmart.com</a>网站开发的一个可免费使用的全功能的文件上传下载组件，适于嵌入执行上传下载操作的JSP文件中。该组件有以下几个特点： </p>
		<p>1、使用简单。在JSP文件中仅仅书写三五行JAVA代码就可以搞定文件的上传或下载，方便。 </p>
		<p>2、能全程控制上传。利用jspSmartUpload组件提供的对象及其操作方法，可以获得全部上传文件的信息（包括文件名，大小，类型，扩展名，文件数据等），方便存取。 </p>
		<p>3、能对上传的文件在大小、类型等方面做出限制。如此可以滤掉不符合要求的文件。 </p>
		<p>4、下载灵活。仅写两行代码，就能把Web服务器变成文件服务器。不管文件在Web服务器的目录下或在其它任何目录下，都可以利用jspSmartUpload进行下载。 </p>
		<p>5、能将文件上传到数据库中，也能将数据库中的数据下载下来。这种功能针对的是MYSQL数据库，因为不具有通用性，所以本文不准备举例介绍这种用法。 </p>
		<p>　　jspSmartUpload组件可以从<a href="http://www.jspsmart.com">www.jspsmart.com</a>网站上自由下载，压缩包的名字是jspSmartUpload.zip。下载后，用WinZip或WinRAR将其解压到Tomcat的webapps目录下（本文以Tomcat服务器为例进行介绍）。解压后，将webapps/jspsmartupload目录下的子目录Web-inf名字改为全大写的WEB-INF，这样一改jspSmartUpload类才能使用。因为Tomcat对文件名大小写敏感，它要求Web应用程序相关的类所在目录为WEB-INF，且必须是大写。接着重新启动Tomcat，这样就可以在JSP文件中使用jspSmartUpload组件了。 </p>
		<p>　　注意，按上述方法安装后，只有webapps/jspsmartupload目录下的程序可以使用jspSmartUpload组件，如果想让Tomcat服务器的所有Web应用程序都能用它，必须做如下工作： </p>
		<p>1．进入命令行状态，将目录切换到Tomcat的webapps/jspsmartupload/WEB-INF目录下。 </p>
		<p>2．运行JAR打包命令：jar cvf jspSmartUpload.jar com </p>
		<p>（也可以打开资源管理器，切换到当前目录，用WinZip将com目录下的所有文件压缩成jspSmartUpload.zip，然后将jspSmartUpload.zip换名为jspSmartUpload.jar文件即可。） </p>
		<p>3．将jspSmartUpload.jar拷贝到Tomcat的shared/lib目录下。 </p>
		<p>二、相关类说明篇 </p>
		<p>㈠ File类 </p>
		<p>　　这个类包装了一个上传文件的所有信息。通过它，可以得到上传文件的文件名、文件大小、扩展名、文件数据等信息。 </p>
		<p>　　File类主要提供以下方法： </p>
		<p>1、saveAs作用：将文件换名另存。 </p>
		<p>原型： </p>
		<p>public void saveAs(java.lang.String destFilePathName) </p>
		<p>或 </p>
		<p>public void saveAs(java.lang.String destFilePathName, int optionSaveAs) </p>
		<p>其中，destFilePathName是另存的文件名，optionSaveAs是另存的选项，该选项有三个值，分别是SAVEAS_PHYSICAL,SAVEAS_VIRTUAL，SAVEAS_AUTO。SAVEAS_PHYSICAL表明以操作系统的根目录为文件根目录另存文件，SAVEAS_VIRTUAL表明以Web应用程序的根目录为文件根目录另存文件，SAVEAS_AUTO则表示让组件决定，当Web应用程序的根目录存在另存文件的目录时，它会选择SAVEAS_VIRTUAL，否则会选择SAVEAS_PHYSICAL。 </p>
		<p>例如，saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)执行后若Web服务器安装在C盘，则另存的文件名实际是c:\upload\sample.zip。而saveAs("/upload/sample.zip",SAVEAS_VIRTUAL)执行后若Web应用程序的根目录是webapps/jspsmartupload，则另存的文件名实际是webapps/jspsmartupload/upload/sample.zip。saveAs("/upload/sample.zip",SAVEAS_AUTO)执行时若Web应用程序根目录下存在upload目录，则其效果同saveAs("/upload/sample.zip",SAVEAS_VIRTUAL)，否则同saveAs("/upload/sample.zip",SAVEAS_PHYSICAL)。 </p>
		<p>建议：对于Web程序的开发来说，最好使用SAVEAS_VIRTUAL，以便移植。 </p>
		<p>2、isMissing </p>
		<p>作用：这个方法用于判断用户是否选择了文件，也即对应的表单项是否有值。选择了文件时，它返回false。未选文件时，它返回true。 </p>
		<p>原型：public boolean isMissing() </p>
		<p>3、getFieldName </p>
		<p>作用：取HTML表单中对应于此上传文件的表单项的名字。 </p>
		<p>原型：public String getFieldName() </p>
		<p>4、getFileName </p>
		<p>作用：取文件名（不含目录信息） </p>
		<p>原型：public String getFileName() </p>
		<p>5、getFilePathName </p>
		<p>作用：取文件全名（带目录） </p>
		<p>原型：public String getFilePathName </p>
		<p>6、getFileExt </p>
		<p>作用：取文件扩展名（后缀） </p>
		<p>原型：public String getFileExt() </p>
		<p>7、getSize </p>
		<p>作用：取文件长度（以字节计） </p>
		<p>原型：public int getSize() </p>
		<p>8、getBinaryData </p>
		<p>作用：取文件数据中指定位移处的一个字节，用于检测文件等处理。 </p>
		<p>原型：public byte getBinaryData(int index)。其中，index表示位移，其值在0到getSize()-1之间。 </p>
		<p>㈡ Files类 </p>
		<p>　　这个类表示所有上传文件的集合，通过它可以得到上传文件的数目、大小等信息。有以下方法： </p>
		<p>1、getCount </p>
		<p>作用：取得上传文件的数目。 </p>
		<p>原型：public int getCount() </p>
		<p>2、getFile </p>
		<p>作用：取得指定位移处的文件对象File（这是com.jspsmart.upload.File，不是java.io.File，注意区分）。 </p>
		<p>原型：public File getFile(int index)。其中，index为指定位移，其值在0到getCount()-1之间。 </p>
		<p>3、getSize </p>
		<p>作用：取得上传文件的总长度，可用于限制一次性上传的数据量大小。 </p>
		<p>原型：public long getSize() </p>
		<p>4、getCollection </p>
		<p>作用：将所有上传文件对象以Collection的形式返回，以便其它应用程序引用，浏览上传文件信息。 </p>
		<p>原型：public Collection getCollection() </p>
		<p>5、getEnumeration </p>
		<p>作用：将所有上传文件对象以Enumeration（枚举）的形式返回，以便其它应用程序浏览上传文件信息。 </p>
		<p>原型：public Enumeration getEnumeration() </p>
		<p>㈢ Request类 </p>
		<p>　　这个类的功能等同于JSP内置的对象request。只所以提供这个类，是因为对于文件上传表单，通过request对象无法获得表单项的值，必须通过jspSmartUpload组件提供的Request对象来获取。该类提供如下方法： </p>
		<p>1、getParameter </p>
		<p>作用：获取指定参数之值。当参数不存在时，返回值为null。 </p>
		<p>原型：public String getParameter(String name)。其中，name为参数的名字。 </p>
		<p>2、getParameterValues </p>
		<p>作用：当一个参数可以有多个值时，用此方法来取其值。它返回的是一个字符串数组。当参数不存在时，返回值为null。 </p>
		<p>原型：public String[] getParameterValues(String name)。其中，name为参数的名字。 </p>
		<p>3、getParameterNames </p>
		<p>作用：取得Request对象中所有参数的名字，用于遍历所有参数。它返回的是一个枚举型的对象。 </p>
		<p>原型：public Enumeration getParameterNames() </p>
		<p>㈣ SmartUpload类这个类完成上传下载工作。 </p>
		<p>A．上传与下载共用的方法： </p>
		<p>只有一个：initialize。 </p>
		<p>作用：执行上传下载的初始化工作，必须第一个执行。 </p>
		<p>原型：有多个，主要使用下面这个： </p>
		<p>public final void initialize(javax.servlet.jsp.PageContext pageContext) </p>
		<p>其中，pageContext为JSP页面内置对象（页面上下文）。 </p>
		<p>B．上传文件使用的方法： </p>
		<p>1、upload </p>
		<p>作用：上传文件数据。对于上传操作，第一步执行initialize方法，第二步就要执行这个方法。 </p>
		<p>原型：public void upload() </p>
		<p>2、save </p>
		<p>作用：将全部上传文件保存到指定目录下，并返回保存的文件个数。 </p>
		<p>原型：public int save(String destPathName) </p>
		<p>和public int save(String destPathName,int option) </p>
		<p>其中，destPathName为文件保存目录，option为保存选项，它有三个值，分别是SAVE_PHYSICAL,SAVE_VIRTUAL和SAVE_AUTO。（同File类的saveAs方法的选项之值类似）SAVE_PHYSICAL指示组件将文件保存到以操作系统根目录为文件根目录的目录下，SAVE_VIRTUAL指示组件将文件保存到以Web应用程序根目录为文件根目录的目录下，而SAVE_AUTO则表示由组件自动选择。 </p>
		<p>注：save(destPathName)作用等同于save(destPathName,SAVE_AUTO)。 </p>
		<p>3、getSize </p>
		<p>作用：取上传文件数据的总长度 </p>
		<p>原型：public int getSize() </p>
		<p>4、getFiles </p>
		<p>作用：取全部上传文件，以Files对象形式返回，可以利用Files类的操作方法来获得上传文件的数目等信息。 </p>
		<p>原型：public Files getFiles() </p>
		<p>5、getRequest </p>
		<p>作用：取得Request对象，以便由此对象获得上传表单参数之值。 </p>
		<p>原型：public Request getRequest() </p>
		<p>6、setAllowedFilesList </p>
		<p>作用：设定允许上传带有指定扩展名的文件，当上传过程中有文件名不允许时，组件将抛出异常。 </p>
		<p>原型：public void setAllowedFilesList(String allowedFilesList) </p>
		<p>其中，allowedFilesList为允许上传的文件扩展名列表，各个扩展名之间以逗号分隔。如果想允许上传那些没有扩展名的文件，可以用两个逗号表示。例如：setAllowedFilesList("doc,txt,,")将允许上传带doc和txt扩展名的文件以及没有扩展名的文件。 </p>
		<p>7、setDeniedFilesList </p>
		<p>作用：用于限制上传那些带有指定扩展名的文件。若有文件扩展名被限制，则上传时组件将抛出异常。 </p>
		<p>原型：public void setDeniedFilesList(String deniedFilesList) </p>
		<p>其中，deniedFilesList为禁止上传的文件扩展名列表，各个扩展名之间以逗号分隔。如果想禁止上传那些没有扩展名的文件，可以用两个逗号来表示。例如：setDeniedFilesList("exe,bat,,")将禁止上传带exe和bat扩展名的文件以及没有扩展名的文件。 </p>
		<p>8、setMaxFileSize </p>
		<p>作用：设定每个文件允许上传的最大长度。 </p>
		<p>原型：public void setMaxFileSize(long maxFileSize) </p>
		<p>其中，maxFileSize为为每个文件允许上传的最大长度，当文件超出此长度时，将不被上传。 </p>
		<p>9、setTotalMaxFileSize </p>
		<p>作用：设定允许上传的文件的总长度，用于限制一次性上传的数据量大小。 </p>
		<p>原型：public void setTotalMaxFileSize(long totalMaxFileSize) </p>
		<p>其中，totalMaxFileSize为允许上传的文件的总长度。 </p>
		<p>C．下载文件常用的方法 </p>
		<p>1、setContentDisposition </p>
		<p>作用：将数据追加到MIME文件头的CONTENT-DISPOSITION域。jspSmartUpload组件会在返回下载的信息时自动填写MIME文件头的CONTENT-DISPOSITION域，如果用户需要添加额外信息，请用此方法。 </p>
		<p>原型：public void setContentDisposition(String contentDisposition) </p>
		<p>其中，contentDisposition为要添加的数据。如果contentDisposition为null，则组件将自动添加"attachment;"，以表明将下载的文件作为附件，结果是IE浏览器将会提示另存文件，而不是自动打开这个文件（IE浏览器一般根据下载的文件扩展名决定执行什么操作，扩展名为doc的将用word程序打开，扩展名为pdf的将用acrobat程序打开，等等）。 </p>
		<p>2、downloadFile </p>
		<p>作用：下载文件。 </p>
		<p>原型：共有以下三个原型可用，第一个最常用，后两个用于特殊情况下的文件下载（如更改内容类型，更改另存的文件名）。 </p>
		<p>① public void downloadFile(String sourceFilePathName) </p>
		<p>其中，sourceFilePathName为要下载的文件名（带目录的文件全名） </p>
		<p>② public void downloadFile(String sourceFilePathName,String contentType) </p>
		<p>其中，sourceFilePathName为要下载的文件名（带目录的文件全名）,contentType为内容类型（MIME格式的文件类型信息，可被浏览器识别）。 </p>
		<p>③ public void downloadFile(String sourceFilePathName,String contentType,String destFileName) </p>
		<p>其中，sourceFilePathName为要下载的文件名（带目录的文件全名）,contentType为内容类型（MIME格式的文件类型信息，可被浏览器识别）,destFileName为下载后默认的另存文件名。 </p>
		<p>三、文件上传篇 </p>
		<p>㈠ 表单要求 </p>
		<p>对于上传文件的FORM表单，有两个要求： </p>
		<p>1、METHOD应用POST，即METHOD="POST"。 </p>
		<p>2、增加属性：ENCTYPE="multipart/form-data" </p>
		<p>下面是一个用于上传文件的FORM表单的例子： </p>
		<p>&lt;FORM METHOD="POST" ENCTYPE="multipart/form-data" <br />ACTION="/jspSmartUpload/upload.jsp"&gt;<br />&lt;INPUT TYPE="FILE" NAME="MYFILE"&gt;<br />&lt;INPUT TYPE="SUBMIT"&gt;<br />&lt;/FORM&gt; </p>
		<p>
				<br />㈡ 上传的例子 </p>
		<p>1、上传页面upload.html </p>
		<p>本页面提供表单，让用户选择要上传的文件，点击"上传"按钮执行上传操作。 </p>
		<p>页面源码如下： </p>
		<p>&lt;!--<br />    文件名：upload.html<br /> 作  者：纵横软件制作中心雨亦奇(<a href="mailto:zhsoft88@sohu.com">zhsoft88@sohu.com</a>)<br />--&gt;<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;文件上传&lt;/title&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;/head&gt;</p>
		<p>&lt;body&gt;<br />&lt;p&gt;&amp;nbsp;&lt;/p&gt;<br />&lt;p align="center"&gt;上传文件选择&lt;/p&gt;<br />&lt;FORM METHOD="POST" ACTION="jsp/do_upload.jsp"<br />ENCTYPE="multipart/form-data"&gt;<br />&lt;input type="hidden" name="TEST" value="good"&gt;<br />  &lt;table width="75%" border="1" align="center"&gt;<br />    &lt;tr&gt; <br />      &lt;td&gt;&lt;div align="center"&gt;1、 <br />          &lt;input type="FILE" name="FILE1" size="30"&gt;<br />        &lt;/div&gt;&lt;/td&gt;<br />    &lt;/tr&gt;<br />    &lt;tr&gt; <br />      &lt;td&gt;&lt;div align="center"&gt;2、 <br />          &lt;input type="FILE" name="FILE2" size="30"&gt;<br />        &lt;/div&gt;&lt;/td&gt;<br />    &lt;/tr&gt;<br />    &lt;tr&gt; <br />      &lt;td&gt;&lt;div align="center"&gt;3、 <br />          &lt;input type="FILE" name="FILE3" size="30"&gt;<br />        &lt;/div&gt;&lt;/td&gt;<br />    &lt;/tr&gt;<br />    &lt;tr&gt; <br />      &lt;td&gt;&lt;div align="center"&gt;4、 <br />          &lt;input type="FILE" name="FILE4" size="30"&gt;<br />        &lt;/div&gt;&lt;/td&gt;<br />    &lt;/tr&gt;<br />    &lt;tr&gt; <br />      &lt;td&gt;&lt;div align="center"&gt;<br />          &lt;input type="submit" name="Submit" value="上传它！"&gt;<br />        &lt;/div&gt;&lt;/td&gt;<br />    &lt;/tr&gt;<br />  &lt;/table&gt;<br />&lt;/FORM&gt;<br />&lt;/body&gt;<br />&lt;/html&gt; </p>
		<p>
				<br />2、上传处理页面do_upload.jsp </p>
		<p>本页面执行文件上传操作。页面源码中详细介绍了上传方法的用法，在此不赘述了。 </p>
		<p>页面源码如下： </p>
		<p>&lt;%--<br /> 文件名：do_upload.jsp<br /> 作  者：纵横软件制作中心雨亦奇(<a href="mailto:zhsoft88@sohu.com">zhsoft88@sohu.com</a>)<br />--%&gt;<br />&lt;%@ page contentType="text/html; charset=gb2312" language="java" <br />import="java.util.*,com.jspsmart.upload.*" errorPage="" %&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;文件上传处理页面&lt;/title&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;/head&gt;</p>
		<p>&lt;body&gt;<br />&lt;%<br /> // 新建一个SmartUpload对象<br /> SmartUpload su = new SmartUpload();<br /> // 上传初始化<br /> su.initialize(pageContext);<br /> // 设定上传限制<br /> // 1.限制每个上传文件的最大长度。<br /> // su.setMaxFileSize(10000);<br /> // 2.限制总上传数据的长度。<br /> // su.setTotalMaxFileSize(20000);<br /> // 3.设定允许上传的文件（通过扩展名限制）,仅允许doc,txt文件。<br /> // su.setAllowedFilesList("doc,txt");<br /> // 4.设定禁止上传的文件（通过扩展名限制）,禁止上传带有exe,bat,<br /> jsp,htm,html扩展名的文件和没有扩展名的文件。<br /> // su.setDeniedFilesList("exe,bat,jsp,htm,html,,");<br /> // 上传文件<br /> su.upload();<br /> // 将上传文件全部保存到指定目录<br /> int count = su.save("/upload");<br /> out.println(count+"个文件上传成功！&lt;br&gt;");<br /> <br /> // 利用Request对象获取参数之值<br /> out.println("TEST="+su.getRequest().getParameter("TEST")<br /> +"&lt;BR&gt;&lt;BR&gt;");</p>
		<p> // 逐一提取上传文件信息，同时可保存文件。<br /> for (int i=0;i&lt;su.getFiles().getCount();i++)<br /> {<br />  com.jspsmart.upload.File file = su.getFiles().getFile(i);<br />  <br />  // 若文件不存在则继续<br />  if (file.isMissing()) continue;</p>
		<p>  // 显示当前文件信息<br />  out.println("&lt;TABLE BORDER=1&gt;");<br />  out.println("&lt;TR&gt;&lt;TD&gt;表单项名（FieldName）&lt;/TD&gt;&lt;TD&gt;"<br />  + file.getFieldName() + "&lt;/TD&gt;&lt;/TR&gt;");<br />  out.println("&lt;TR&gt;&lt;TD&gt;文件长度（Size）&lt;/TD&gt;&lt;TD&gt;" + <br />  file.getSize() + "&lt;/TD&gt;&lt;/TR&gt;");<br />  out.println("&lt;TR&gt;&lt;TD&gt;文件名（FileName）&lt;/TD&gt;&lt;TD&gt;" <br />  + file.getFileName() + "&lt;/TD&gt;&lt;/TR&gt;");<br />  out.println("&lt;TR&gt;&lt;TD&gt;文件扩展名（FileExt）&lt;/TD&gt;&lt;TD&gt;" <br />  + file.getFileExt() + "&lt;/TD&gt;&lt;/TR&gt;");<br />  out.println("&lt;TR&gt;&lt;TD&gt;文件全名（FilePathName）&lt;/TD&gt;&lt;TD&gt;"<br />  + file.getFilePathName() + "&lt;/TD&gt;&lt;/TR&gt;");<br />  out.println("&lt;/TABLE&gt;&lt;BR&gt;");</p>
		<p>  // 将文件另存<br />  // file.saveAs("/upload/" + myFile.getFileName());<br />  // 另存到以WEB应用程序的根目录为文件根目录的目录下<br />  // file.saveAs("/upload/" + myFile.getFileName(), <br />  su.SAVE_VIRTUAL);<br />  // 另存到操作系统的根目录为文件根目录的目录下<br />  // file.saveAs("c:\\temp\\" + myFile.getFileName(), <br />  su.SAVE_PHYSICAL);</p>
		<p> }<br />%&gt;<br />&lt;/body&gt;<br />&lt;/html&gt; </p>
		<p>
				<br />四、文件下载篇 </p>
		<p>1、下载链接页面download.html </p>
		<p>页面源码如下： </p>
		<p>&lt;!--<br />  文件名：download.html<br /> 作  者：纵横软件制作中心雨亦奇(<a href="mailto:zhsoft88@sohu.com">zhsoft88@sohu.com</a>)<br />--&gt;<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;下载&lt;/title&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;/head&gt;<br />&lt;body&gt;<br />&lt;a href="jsp/do_download.jsp"&gt;点击下载&lt;/a&gt;<br />&lt;/body&gt;<br />&lt;/html&gt; </p>
		<p>
				<br />2、下载处理页面do_download.jsp do_download.jsp展示了如何利用jspSmartUpload组件来下载文件，从下面的源码中就可以看到，下载何其简单。 </p>
		<p>源码如下： </p>
		<p>&lt;%@ page contentType="text/html;charset=gb2312" <br />import="com.jspsmart.upload.*" %&gt;&lt;%<br />  // 新建一个SmartUpload对象<br /> SmartUpload su = new SmartUpload();<br />  // 初始化<br /> su.initialize(pageContext);<br />  // 设定contentDisposition为null以禁止浏览器自动打开文件，<br />  //保证点击链接后是下载文件。若不设定，则下载的文件扩展名为<br />  //doc时，浏览器将自动用word打开它。扩展名为pdf时，<br />  //浏览器将用acrobat打开。<br /> su.setContentDisposition(null);<br />  // 下载文件<br /> su.downloadFile("/upload/如何赚取我的第一桶金.doc");<br />%&gt; </p>
		<p>
				<br />注意，执行下载的页面，在Java脚本范围外（即&lt;% ... %&gt;之外），不要包含HTML代码、空格、回车或换行等字符，有的话将不能正确下载。不信的话，可以在上述源码中%&gt;&lt;%之间加入一个换行符，再下载一下，保证出错。因为它影响了返回给浏览器的数据流，导致解析出错。 </p>
		<p>3、如何下载中文文件 </p>
		<p>jspSmartUpload虽然能下载文件，但对中文支持不足。若下载的文件名中有汉字，则浏览器在提示另存的文件名时，显示的是一堆乱码，很扫人兴。上面的例子就是这样。（这个问题也是众多下载组件所存在的问题，很少有人解决，搜索不到相关资料，可叹！） </p>
		<p>为了给jspSmartUpload组件增加下载中文文件的支持，我对该组件进行了研究，发现对返回给浏览器的另存文件名进行UTF-8编码后，浏览器便能正确显示中文名字了。这是一个令人高兴的发现。于是我对jspSmartUpload组件的SmartUpload类做了升级处理，增加了toUtf8String这个方法，改动部分源码如下： </p>
		<p>public void downloadFile(String s, String s1, String s2, int i)<br /> throws ServletException, IOException, SmartUploadException<br />    {<br /> if(s == null)<br />     throw new IllegalArgumentException("File '" + s +<br />     "' not found (1040).");<br /> if(s.equals(""))<br />     throw new IllegalArgumentException("File '" + s +<br />     "' not found (1040).");<br /> if(!isVirtual(s) &amp;&amp; m_denyPhysicalPath)<br />     throw new SecurityException("Physical path is<br />     denied (1035).");<br /> if(isVirtual(s))<br />     s = m_application.getRealPath(s);<br /> java.io.File file = new java.io.File(s);<br /> FileInputStream fileinputstream = new FileInputStream(file);<br /> long l = file.length();<br /> boolean flag = false;<br /> int k = 0;<br /> byte abyte0[] = new byte[i];<br /> if(s1 == null)<br />     m_response.setContentType("application/x-msdownload");<br /> else<br /> if(s1.length() == 0)<br />     m_response.setContentType("application/x-msdownload");<br /> else<br />     m_response.setContentType(s1);<br /> m_response.setContentLength((int)l);<br /> m_contentDisposition = m_contentDisposition != null ?<br /> m_contentDisposition : "attachment;";<br /> if(s2 == null)<br />     m_response.setHeader("Content-Disposition", <br />     m_contentDisposition + " filename=" + <br />     toUtf8String(getFileName(s)));<br /> else<br /> if(s2.length() == 0)<br />     m_response.setHeader("Content-Disposition", <br />     m_contentDisposition);<br /> else<br />     m_response.setHeader("Content-Disposition", <br />     m_contentDisposition + " filename=" + toUtf8String(s2));<br /> while((long)k &lt; l)<br /> {<br />     int j = fileinputstream.read(abyte0, 0, i);<br />     k += j;<br />     m_response.getOutputStream().write(abyte0, 0, j);<br /> }<br /> fileinputstream.close();<br />    }</p>
		<p>    /**<br />     * 将文件名中的汉字转为UTF8编码的串,以便下载时能正确显示另存的文件名.<br />     * 纵横软件制作中心雨亦奇2003.08.01<br />     * @param s 原文件名<br />     * @return 重新编码后的文件名<br />     */<br />    public static String toUtf8String(String s) {<br /> StringBuffer sb = new StringBuffer();<br /> for (int i=0;i&lt;s.length();i++) {<br />     char c = s.charAt(i);<br />     if (c &gt;= 0 &amp;&amp; c &lt;= 255) {<br />  sb.append(c);<br />     } else {<br />  byte[] b;<br />  try {<br />      b = Character.toString(c).getBytes("utf-8");<br />  } catch (Exception ex) {<br />      System.out.println(ex);<br />      b = new byte[0];<br />  }<br />  for (int j = 0; j &lt; b.length; j++) {<br />      int k = b[j];<br />      if (k &lt; 0) k += 256;<br />      sb.append("%" + Integer.toHexString(k).<br />      toUpperCase());<br />  }<br />     }<br /> }<br /> return sb.toString();<br />    } </p>
		<p>
				<br />注意源码中粗体部分，原jspSmartUpload组件对返回的文件未作任何处理，现在做了编码的转换工作，将文件名转换为UTF-8形式的编码形式。UTF-8编码对英文未作任何处理，对中文则需要转换为%XX的形式。toUtf8String方法中，直接利用Java语言提供的编码转换方法获得汉字字符的UTF-8编码，之后将其转换为%XX的形式。 </p>
		<p>将源码编译后打包成jspSmartUpload.jar，拷贝到Tomcat的shared/lib目录下（可为所有WEB应用程序所共享），然后重启Tomcat服务器就可以正常下载含有中文名字的文件了。另，toUtf8String方法也可用于转换含有中文的超级链接，以保证链接的有效，因为有的WEB服务器不支持中文链接。 </p>
		<p>小结：jspSmartUpload组件是应用JSP进行B/S程序开发过程中经常使用的上传下载组件，它使用简单，方便。现在我又为其加上了下载中文名字的文件的支持，真个是如虎添翼，必将赢得更多开发者的青睐。 </p>
		<p>---------------------------------------------------------------------------------------------------------------------------</p>
		<p>题目：彻底解决中文名文件下载和下载文件内容乱码问题</p>
		<p>之前,写过一个Download.jsp文件,可以解决下载文件乱码问题(诸如:DOC,XSL文件等等).<br />后来发现,遇到中文名的文件的时候,文件下载将会报错~~~~<br />今天,通过改写原Download.jsp文件已经彻底解决了这个问题~<br />现在,把一整套的文件上传下载的方法给贴出来~~~以便大家借鉴!~!~!~!~!  <br />作者:古埃及法老<br />-----------------------------------------------------<br />测试环境:WEBLOGIC 8.1,WIN XP SP4,IE 6.0 <br />-----------------------------------------------------<br />文件上传: <br />-----------------------------------------<br />准备工作:导入著名的SmartUpload.jar组件包<br />upload.jsp文件<br />-----------------------------------------------------<br />&lt;%@ page contentType="text/html; charset=gb2312" %&gt;<br />&lt;%<br /> request.setCharacterEncoding("gb2312"); // 这句话很重要，否则遇到中文就出错~<br />%&gt;<br />&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;上传&lt;/TITLE&gt;<br />&lt;META content="text/html; charset=gb2312" http-equiv=Content-Type&gt;<br />&lt;/HEAD&gt;<br />&lt;BODY leftMargin=0 topMargin=0&gt;<br />&lt;table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0" bgcolor="#DEE7EF"&gt;<br />  &lt;tr&gt;<br />    &lt;td align="center"&gt; <br />      &lt;FORM action="upload_ok.jsp" method=post name="Upload" enctype="multipart/form-data"&gt;<br />        &lt;br&gt;<br />        请输入附件文件的所在路径&lt;FONT color=red&gt; * &lt;/FONT&gt;为必填项目&lt;br&gt;<br />        &lt;br&gt;<br />        &lt;TABLE width="317" border=0 cellPadding=0&gt;<br />          &lt;TBODY&gt;<br />            &lt;TR&gt; <br />              &lt;TD align=right vAlign=center nowrap&gt;附件路径：&lt;/TD&gt;<br />              &lt;TD&gt;&lt;input type="file" name="file" style="border: 1px #FFFFFF solid;background:#efefef" &gt; &lt;FONT color=red&gt;*&lt;/FONT&gt;&lt;/TD&gt;<br />            &lt;/TR&gt;<br />            &lt;TR align="center"&gt; <br />              &lt;TD height=60 colspan="2" vAlign=center nowrap&gt; &lt;INPUT style="height:22px" name=B1 type=submit value=" 确 定 " &gt;<br />&lt;INPUT style="height:22px" name=B2 type=reset value=" 取 消 " &gt; <br />              &lt;/TD&gt;<br />            &lt;/TR&gt;<br />          &lt;/TBODY&gt;<br />        &lt;/TABLE&gt;<br />      &lt;/FORM&gt; <br />&lt;/td&gt;<br />  &lt;/tr&gt;<br />&lt;/table&gt;<br />&lt;/BODY&gt;&lt;/HTML&gt;<br />-----------------------------------------------------<br />upload_ok.jsp文件<br />-----------------------------------------------------<br />&lt;%@ page contentType="text/html;charset=gb2312" %&gt;<br />&lt;%@ page import="com.jspsmart.upload.*" %&gt;<br />&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;上传成功!&lt;/TITLE&gt;<br />&lt;META content="text/html; charset=gb2312" http-equiv=Content-Type&gt;<br />&lt;/HEAD&gt;<br />&lt;BODY leftMargin=0 topMargin=0&gt;<br />&lt;jsp:useBean id="mySmartUpload" scope="page" class="com.jspsmart.upload.SmartUpload" /&gt;<br />&lt;table width="80%"  border="0" cellpadding="0" cellspacing="0" bgcolor="#DEE7EF"&gt;<br />  &lt;tr&gt;<br />    &lt;td align="center"&gt; <br />&lt;% <br /> int count=0;<br /> String fileName = null;<br /> mySmartUpload.initialize(pageContext); <br /> mySmartUpload.upload();<br /> com.jspsmart.upload.File myFile = mySmartUpload.getFiles().getFile(0);<br /> if (!myFile.isMissing()) {<br />  //String ext=myFile.getFileExt();//得到后缀   <br />  fileName = myFile.getFileName();<br />            myFile.saveAs("/files/" + fileName);//你要存放文件所在文件夹的相对路径<br />     out.println("文件:&lt;b&gt;"+fileName+"&lt;/b&gt;上传成功!&lt;br&gt;文件大小:" + myFile.getSize() + "kb&lt;BR&gt;");<br />     }<br />%&gt;<br />&lt;/BODY&gt;&lt;/HTML&gt;<br />---------------------------------------------------</p>
		<p>文件下载: <br />-----------------------------------------<br />文件的超连接写法范例:<br />&lt;% String fname ="中文测试.xsl"; //假设你的文件名是:中文测试.xsl<br />%&gt;<br />&lt;A target="_blank" href="Download.jsp?filename=&lt;%=fname%&gt;"&gt;下 载&lt;/A&gt;<br />文件的超连接写法范例-2 重新用utf-8对文件名编码:<br />&lt;%@ page contentType="text/html;charset=gb2312" session="true"%&gt;<br />&lt;%  String name=java.net.URLEncoder.encode("世界文化.doc","UTF-8"));%&gt;  &lt;a href="c:\&lt;%=name%&gt;"&gt;世界文化.doc&lt;/a&gt;</p>
		<p>Download.jsp文件<br />---------------------------------------------------<br />&lt;%<br />  java.io.BufferedInputStream bis=null;<br />  java.io.BufferedOutputStream  bos=null;<br />try{<br /> String filename=request.getParameter("filename");<br />             filename=new String(filename.getBytes("iso8859-1"),"gb2312");<br /> response.setContentType("application/x-msdownload");<br /> response.setHeader("Content-disposition","attachment; filename="+new String(filename.getBytes("gb2312"),"iso8859-1"));<br /> bis =new java.io.BufferedInputStream(new java.io.FileInputStream(config.getServletContext().getRealPath("files/" + filename)));<br /> bos=new java.io.BufferedOutputStream(response.getOutputStream()); <br /> byte[] buff = new byte[2048];<br /> int bytesRead;<br /> while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {<br />  bos.write(buff,0,bytesRead);<br /> }<br />}<br />catch(Exception e){<br /> e.printStackTrace();<br />}<br />finally {<br /> if (bis != null)bis.close();<br /> if (bos != null)bos.close();<br />}<br />%&gt; </p>
		<p> </p>
<img src ="http://www.blogjava.net/renyangok/aggbug/51362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-06-08 15:17 <a href="http://www.blogjava.net/renyangok/articles/51362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>