﻿<?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-没有姚明高,没有华仔帅</title><link>http://www.blogjava.net/yes1983/</link><description>努力啊,奋斗!</description><language>zh-cn</language><lastBuildDate>Tue, 12 May 2026 22:58:26 GMT</lastBuildDate><pubDate>Tue, 12 May 2026 22:58:26 GMT</pubDate><ttl>60</ttl><item><title>定制Eclipse的Content assist(代码补全),比如空格键不上屏</title><link>http://www.blogjava.net/yes1983/archive/2010/12/15/Eclipse.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Wed, 15 Dec 2010 04:15:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2010/12/15/Eclipse.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/340768.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2010/12/15/Eclipse.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/340768.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/340768.html</trackback:ping><description><![CDATA[以前只知道alt+/调出assist,后来发现可以所有字母都激活content assist(方法百度上都有,就不在这写了).用起来果然很爽.但是eclipse还是有些默认的设置不是很好,比如空格键和=号会把第一行的内容自动上屏,其实很多时候我就是想输一个空格或=号而已.这个在设置里面没办法设置.幸好eclipse是有插件机制的,可以通过修改插件的源码,然后导出成插件,再替换掉原来的插件来处理<br />
1.先找到相关的插件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开Plug-ins View找到插件org.eclipse.jface.text,右键点击,选择import as Source Project,导入完成后,在你的workspace就可以看到这个project了<br />
2.修改代码<br />
&nbsp;&nbsp;&nbsp;&nbsp; 在<font style="background-color: #cce8cf">src/org/eclipse/jface/text/contentassist/CompletionProposalPopup.java</font>文件中,找到这样一行代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char triggers = t.getTriggerCharacter();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(contains(triggers,key))<br />
&nbsp;&nbsp;&nbsp; 在那行if判断里面,eclipse会判断key(就是你按下的键)是否在triggers中,如果是,那就触发下面的第一行提示上屏的代码.所以我们要做的就是把空格和=号排除就可以了:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(key!='='&amp;&amp;key!=0x20&amp;&amp;contains(triggers,key))<br />
<br />
3.把修改好的org.eclipse.jface.text导出<br />
&nbsp;&nbsp;&nbsp; 右键点击你的workspace里的org.eclipse.jface.text,选择export--&gt;Deployable plugins and fragments, next,destination 选择archive file,然后finish.你就可以在zip文件里看到生成好的jar&nbsp;,用它替换掉eclipse/plugins里面的同名jar包,就可以了 
<img src ="http://www.blogjava.net/yes1983/aggbug/340768.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2010-12-15 12:15 <a href="http://www.blogjava.net/yes1983/archive/2010/12/15/Eclipse.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visio的Web程序模板</title><link>http://www.blogjava.net/yes1983/archive/2010/07/28/327355.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Wed, 28 Jul 2010 10:27:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2010/07/28/327355.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/327355.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2010/07/28/327355.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/327355.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/327355.html</trackback:ping><description><![CDATA[Visio的图标很多,但是用来设计web程序的基本没有,在网上找到了这个,觉得还蛮好用的,共享一下<a href="/Files/yes1983/GUUUI_Web_Prototyping_Tool_3.zip"><br />
/Files/yes1983/GUUUI_Web_Prototyping_Tool_3.zip</a>
<img src ="http://www.blogjava.net/yes1983/aggbug/327355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2010-07-28 18:27 <a href="http://www.blogjava.net/yes1983/archive/2010/07/28/327355.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse RCP中多线程Job使用[转帖]</title><link>http://www.blogjava.net/yes1983/archive/2010/07/01/325014.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Thu, 01 Jul 2010 13:28:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2010/07/01/325014.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/325014.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2010/07/01/325014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/325014.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/325014.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文分析了Eclipse中多线程程序的实现，讨论了在Eclipse客户端程序开发中应用多线程的方法和要注意的问题，同时也讨论了多线程程序的一些调试和问题解决的方法。 <br>&nbsp;&nbsp;<a href='http://www.blogjava.net/yes1983/archive/2010/07/01/325014.html'>阅读全文</a><img src ="http://www.blogjava.net/yes1983/aggbug/325014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2010-07-01 21:28 <a href="http://www.blogjava.net/yes1983/archive/2010/07/01/325014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Common table expression,Nested Table expression, Temporary table(转载)</title><link>http://www.blogjava.net/yes1983/archive/2010/04/14/318271.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Wed, 14 Apr 2010 08:53:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2010/04/14/318271.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/318271.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2010/04/14/318271.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/318271.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/318271.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">转载自<font style="background-color: #cce8cf">http://blog.csdn.net/shangboerds/archive/2010/01/27/5260783.aspx</font><br />
CTE:<br />
说起WITH 语句，除了那些第一次听说WITH语句的人，大部分人都觉得它是用来做递归查询的。其实那只是它的一个用途而已，它的本名正如我们标题写的那样，叫做：公共表表达式（Common Table Expression），从字面理解，大家觉得它是用来干嘛的呢？其实，它是用来定义临时集合的。啊？VALUES语句不是用来定义临时集合的吗？怎么WITH语句也用来定义临时集合呢？它们有什么区别呢？</font></p>
<p><font style="background-color: #cce8cf">VALUES语句是用明确的值来定义临时集合的，如下：</font></p>
<p><font style="background-color: #cce8cf">VALUES (1,2), (1,3),(2,1)&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">WITH语句是用查询(也就是select语句)来定义临时集合的，从这个角度讲，有点像视图，不过不是视图，大家千万别误解。如下：</font></p>
<p><font style="background-color: #cce8cf">CREATE TABLE USER (<br />
&nbsp; <br />
NAME VARCHAR(20) NOT NULL,---姓名<br />
&nbsp; <br />
SEX INTEGER,---性别（1、男&nbsp;&nbsp; 2、女）<br />
&nbsp; <br />
BIRTHDAY DATE---生日<br />
&nbsp; <br />
);&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">WITH TEST(NAME_TEST, BDAY_TEST) AS&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
SELECT NAME,BIRTHDAY FROM USER--语句1&nbsp;&nbsp; <br />
)&nbsp;&nbsp; <br />
SELECT NAME_TEST FROM TEST WHERE BDAY_TEST='1949-10-1';--语句2&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">下面我们来解释一下，首先语句1执行，它会产生一个有两列（NAME,BIRTHDAY）的结果集；接着，我们将这个结果集命名为test，并且将列名重命名为NAME_TEST, BDAY_TEST；最后我们执行语句2，从这个临时集合中找到生日是1949-10-1，也就是共和国的同龄人。</font></p>
<p><font style="background-color: #cce8cf">怎么样？如果你感觉不好理解，请仔细的分析一下上面的语句。下面我们举个VALUES语句和WITH语句结合使用的例子，如下：</font></p>
<p><font style="background-color: #cce8cf">WITH TEST(NAME_TEST, BDAY_TEST) AS<br />
&nbsp; <br />
(<br />
&nbsp; <br />
VALUES ('张三','1997-7-1'),('李四','1949-10-1')<br />
&nbsp; <br />
)<br />
&nbsp; <br />
SELECT NAME_TEST FROM TEST WHERE BDAY_TEST='1949-10-1'&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">从上面的介绍和WITH语句不为大多数人所熟悉可以猜测，WITH语句是为复杂的查询为设计的，的确是这样的，下面我们举个复杂的例子，想提高技术的朋友可千万不能错过。考虑下面的情况：</font></p>
<p><font style="background-color: #cce8cf">CREATE TABLE USER&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
NAME VARCHAR(20) NOT NULL,--姓名&nbsp;&nbsp; <br />
DEGREE INTEGER NOT NULL,--学历(1、专科 2、本科 3、硕士 4、博士)&nbsp;&nbsp; <br />
STARTWORKDATE date NOT NULL,--入职时间&nbsp;&nbsp; <br />
SALARY1 FLOAT NOT NULL,--基本工资&nbsp;&nbsp; <br />
SALARY2 FLOAT NOT NULL--奖金&nbsp;&nbsp; <br />
);&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">假设现在让你查询一下那些 1、学历是硕士或博士&nbsp; 2、学历相同，入职年份也相同，但是工资（基本工资+奖金）却比相同条件员工的平均工资低的员工。（哈哈，可能是要涨工资），不知道你听明白问题没有？该怎么查询呢？我们是这样想的：</font></p>
<p><font style="background-color: #cce8cf">1、查询学历是硕士或博士的那些员工得到结果集1，如下：</font></p>
<p><font style="background-color: #cce8cf">SELECT NAME,DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, SALARY1+SALARY2 AS SALARY FROM USER WHERE DEGREE IN (3,4)；&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">2、根据学历和入职年份分组，求平均工资 得到结果集2，如下：</font></p>
<p><font style="background-color: #cce8cf">SELECT DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, AVG(SALARY1+SALARY2) AS AVG_SALARY&nbsp;&nbsp;&nbsp; <br />
FROM USER WHERE DEGREE IN (3,4)&nbsp;&nbsp; <br />
GROUP BY DEGREE,YEAR(STARTWORKDATE)&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">3、以学历和入职年份为条件 联合两个结果集，查找工资&lt;平均工资 的员工，以下是完整的SQL：</font></p>
<p><font style="background-color: #cce8cf">WITH TEMP1(NAME,DEGREE,WORDDATE,SALARY) AS&nbsp;&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
SELECT NAME,DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, SALARY1+SALARY2 AS SALARY FROM USER WHERE DEGREE IN (3,4)&nbsp;&nbsp; <br />
),&nbsp;&nbsp; <br />
TEMP2 (DEGREE,WORDDATE,AVG_SALARY) AS&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
SELECT DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, AVG(SALARY1+SALARY2) AS AVG_SALARY&nbsp;&nbsp;&nbsp; <br />
FROM USER WHERE DEGREE IN (3,4)&nbsp;&nbsp; <br />
GROUP BY DEGREE,YEAR(STARTWORKDATE)&nbsp;&nbsp; <br />
)&nbsp;&nbsp; <br />
SELECT NAME FROM TEMP1, TEMP2 WHERE&nbsp;&nbsp;&nbsp; <br />
TEMP1.DEGREE=TEMP2.DEGREE&nbsp;&nbsp;&nbsp; <br />
AND TEMP1.WORDDATE=TEMP2.WORDDATE&nbsp;&nbsp;&nbsp; <br />
AND SALARY&lt;AVG_SALARY;&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">查询结果完全正确，但我们还有改善的空间，在查询结果集2的时候，我们是从user表中取得数据的。其实此时结果集1已经查询出来了，我们完全可以从结果集1中通过分组得到结果集2，而不用从uer表中得到结果集2，比较上面和下面的语句你就可以知道我说的是什么意思了！</font></p>
<p><font style="background-color: #cce8cf">WITH TEMP1(NAME,DEGREE,WORDDATE,SALARY) AS&nbsp;&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
SELECT NAME,DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, SALARY1+SALARY2 AS SALARY FROM USER WHERE DEGREE IN (3,4)&nbsp;&nbsp; <br />
),&nbsp;&nbsp; <br />
TEMP2 (DEGREE,WORDDATE,AVG_SALARY) AS&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
SELECT DEGREE,WORDDATE, AVG(SALARY) AS AVG_SALARY&nbsp;&nbsp;&nbsp; <br />
FROM TEMP1&nbsp;&nbsp; <br />
GROUP BY DEGREE,WORDDATE&nbsp;&nbsp; <br />
)&nbsp;&nbsp; <br />
SELECT NAME FROM TEMP1, TEMP2 WHERE&nbsp;&nbsp;&nbsp; <br />
TEMP1.DEGREE=TEMP2.DEGREE&nbsp;&nbsp;&nbsp; <br />
AND TEMP1.WORDDATE=TEMP2.WORDDATE&nbsp;&nbsp;&nbsp; <br />
AND SALARY&lt;AVG_SALARY;&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">可能有些朋友会说，我不用WITH语句也可以查出来，的确是这样，如下：</font></p>
<p><font style="background-color: #cce8cf">SELECT U.NAME FROM USER AS U,<br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT DEGREE,YEAR(STARTWORKDATE) AS WORDDATE, AVG(SALARY1+SALARY2) AS AVG_SALARY <br />
&nbsp; <br />
FROM USER WHERE DEGREE IN (3,4)<br />
&nbsp; <br />
GROUP BY DEGREE,YEAR(STARTWORKDATE)<br />
&nbsp; <br />
) AS G<br />
&nbsp; <br />
WHERE U.DEGREE=G.DEGREE<br />
&nbsp; <br />
AND YEAR(U.STARTWORKDATE)=G.WORDDATE<br />
&nbsp; <br />
AND (SALARY1+SALARY2)&lt;G.AVG_SALARY;&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">那使用WITH 和不使用 WITH，这两种写法有什么区别呢？一般情况下这两种写法在性能上不会有太大差异，但是，</font></p>
<p><font style="background-color: #cce8cf">1、当USER表的记录很多</font></p>
<p><font style="background-color: #cce8cf">2、硕士或博士（DEGREE IN (3,4)）在USER表中的比例很少</font></p>
<p><font style="background-color: #cce8cf">当满足以上条件时，这两种写法在性能的差异将会显现出来，为什么呢？因为不使用WITH写法的语句访问了2次USER表，如果DEGREE 字段又没有索引，性能差异将会非常明显。</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; 当你看到这时，如果很好的理解了上面的内容，我相信你会对WITH语句有了一定的体会。然而WITH语句能做的还不止这些，下面给大家介绍一下，如何用WITH语句做递归查询。递归查询的一个典型的例子是对树状结构的表进行查询，考虑如下的情况：</font></p>
<p><font style="background-color: #cce8cf">论坛首页&nbsp;&nbsp; <br />
--数据库开发&nbsp;&nbsp; <br />
----DB2&nbsp;&nbsp; <br />
------DB2 文章1&nbsp;&nbsp; <br />
--------DB2 文章1 的评论1&nbsp;&nbsp; <br />
--------DB2 文章1 的评论2&nbsp;&nbsp; <br />
------DB2 文章2&nbsp;&nbsp; <br />
----Oracle&nbsp;&nbsp; <br />
--Java技术&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">以上是一个论坛的典型例子，下面我们新建一个表来存储以上信息。</font></p>
<p><font style="background-color: #cce8cf">CREATE TABLE BBS&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
PARENTID INTEGER NOT NULL,&nbsp;&nbsp; <br />
ID INTEGER NOT NULL,&nbsp;&nbsp; <br />
NAME VARCHAR(200) NOT NULL---板块、文章、评论等。&nbsp;&nbsp; <br />
);&nbsp;&nbsp; <br />
insert into bbs (PARENTID,ID,NAME) values&nbsp;&nbsp;&nbsp; <br />
(0,0,'论坛首页'),&nbsp;&nbsp; <br />
(0,1,'数据库开发'),&nbsp;&nbsp; <br />
(1,11,'DB2'),&nbsp;&nbsp; <br />
(11,111,'DB2 文章1'),&nbsp;&nbsp; <br />
(111,1111,'DB2 文章1 的评论1'),&nbsp;&nbsp; <br />
(111,1112,'DB2 文章1 的评论2'),&nbsp;&nbsp; <br />
(11,112,'DB2 文章2'),&nbsp;&nbsp; <br />
(1,12,'Oracle'),&nbsp;&nbsp; <br />
(0,2,'Java技术');&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">现在万事兼备了，我们开始查询吧。假设现在让你查询一下&#8216;DB2 文章1&#8217;的所有评论，有人说，这还不简单，如下这样就可以了。</font></p>
<p><font style="background-color: #cce8cf">SELECT * FROM BBS WHERE PARENTID=(SELECT ID FROM BBS WHERE NAME='DB2');&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">答案完全正确。那么，现在让你查询一下DB2的所有文章及评论，怎么办？传统的方法就很难查询了，这时候递归查询就派上用场了，如下：</font></p>
<p><font style="background-color: #cce8cf">WITH TEMP(PARENTID,ID,NAME) AS&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
SELECT PARENTID,ID,NAME FROM BBS WHERE NAME='DB2'---语句1&nbsp;&nbsp; <br />
UNION ALL---语句2&nbsp;&nbsp; <br />
SELECT B.PARENTID,B.ID,B.NAME FROM BBS AS B, TEMP AS T WHERE B.PARENTID=T.ID---语句3&nbsp;&nbsp; <br />
)&nbsp;&nbsp; <br />
SELECT NAME FROM TEMP;---语句4&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">运行后，我们发现，结果完全正确，那它到底是怎么运行的呢？下面我们详细讲解一下。</font></p>
<p><font style="background-color: #cce8cf">1、首先，语句1将会执行，它只执行一次，作为循环的起点。得到结果集：DB2</font></p>
<p><font style="background-color: #cce8cf">2、接着，将循环执行语句3，这里我们有必要详细介绍一下。</font></p>
<p><font style="background-color: #cce8cf">首先语句3的意图是什么呢？说白了，它就是查找语句1产生结果集（DB2）的下一级，那么在目录树中DB2的下一级是什么呢？是&#8216;DB2 文章1&#8217;和&#8216;DB2 文章2&#8217;，并且把查询到的结果集作为下一次循环的起点，然后查询它们的下一级，直到没有下一级为止。</font></p>
<p><font style="background-color: #cce8cf">怎么样？还没明白？哈哈，不要紧，我们一步一步来：</font></p>
<font style="background-color: #cce8cf">
<p><br />
首先，语句1产生结果集：DB2，作为循环的起点，把它和BBS表关联来查找它的下一级，查询后的结果为：&#8216;DB2 文章1&#8217;和&#8216;DB2 文章2&#8217;</p>
<p>接着，把上次的查询结果（也就是&#8216;DB2 文章1&#8217;和&#8216;DB2 文章2&#8217;）和BBS表关联来查找它们的下一级，查询后的结果为：&#8216;DB2 文章1 的评论1&#8217; 和 &#8216;DB2 文章1 的评论2&#8217;。</p>
<p>然后，在把上次的查询结果（也就是&#8216;DB2 文章1 的评论1&#8217; 和 &#8216;DB2 文章1 的评论2&#8217;）和BBS表关联来查找它们的下一级，此时，没有结果返回，循环结束。</p>
<p>3、第三，将执行语句2，将所有的结果集放在一起，最终得到temp结果集。</p>
<p>4、最后，我们通过语句4 从temp临时集合中得到我们期望的查询结果。</p>
<p>怎么样，这回理解了吧，如果还没有理解，那么我也无能为力了。需要特别提醒的是</p>
<p>1、一定要注意语句3的关联条件，否则很容易就写成死循环了。</p>
<p>2、语句2必须是UNION ALL</p>
<p>最后请大家猜想一下，把语句1的where子句去掉，将会产生什么样的结果呢？</p>
<p>NTE:<br />
<br />
</p>
<p><font style="background-color: #cce8cf">SELECT * FROM &lt;TABLE-NAME&gt;;&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">看到上面的语句了吗？这是我们在熟悉不过的一条语句，我们中的大多人学习SQL正是从这条语句开始的。所以大多数人认为FROM语句后只能接一个表或视图（或者压根就没多想），有这种想法的人我非常能理解，因为我曾经也是这其中的一员。其实FROM后面可以接任何集合（表）。说到这，关于集合和表，我特别想多少几句。SQL的理论基础是数学中的集合理论，所以SQL关注的就是如何对集合进行操作，基于以上原因，我特别喜欢名词 集合，而不喜欢说表。不过，大家如果不习惯，也可以把集合和表当一个意思来理解，因为我们不是搞理论研究工作的，没必要深究他们之间的细微差别。说了这么多，我们还是赶快来看个例子吧。</font></p>
<p><font style="background-color: #cce8cf">---建表<br />
&nbsp; <br />
CREATE TABLE USER&nbsp; <br />
&nbsp; <br />
(&nbsp; <br />
&nbsp; <br />
NAME VARCHAR(20) NOT NULL,---姓名&nbsp; <br />
&nbsp; <br />
BIRTHDAY DATE---生日&nbsp; <br />
&nbsp; <br />
); <br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
---例子1<br />
&nbsp; <br />
SELECT * FROM <br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT * FROM USER<br />
&nbsp; <br />
) AS TEMP1;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
---例子2<br />
&nbsp; <br />
SELECT NAME,BIRTHDAY FROM <br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT NAME,BIRTHDAY FROM USER<br />
&nbsp; <br />
) AS TEMP1;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
---例子3<br />
&nbsp; <br />
SELECT TEMP1.NAME,TEMP1.BIRTHDAY FROM <br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT NAME,BIRTHDAY FROM USER<br />
&nbsp; <br />
) AS TEMP1;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
---例子4<br />
&nbsp; <br />
SELECT N,B FROM <br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT NAME,BIRTHDAY FROM USER<br />
&nbsp; <br />
) AS TEMP1(N,B);<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
&nbsp;<br />
&nbsp; <br />
---例子5<br />
&nbsp; <br />
SELECT AAA.A,AAA.B,XXX.X,XXX.Y FROM <br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT NAME,BIRTHDAY FROM USER<br />
&nbsp; <br />
) AS AAA(A,B),--集合1<br />
&nbsp; <br />
(<br />
&nbsp; <br />
SELECT NAME,BIRTHDAY FROM USER<br />
&nbsp; <br />
) AS XXX(X,Y)--集合2<br />
&nbsp; <br />
WHERE AAA.A=XXX.X AND AAA.B=XXX.Y--关联两个集合&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">看到上面的例子5了吗？我们可以给临时集合命名，还可以给重命名临时集合的列名，还可以关联两个临时集合，总之，操作临时集合和操作表没有区别。</font></p>
Temporary table<br />
<p><font style="background-color: #cce8cf">临时表（TEMPORARY TABLE）通常应用在需要定义临时集合的场合。但是，在大部分需要临时集合的时候，我们根本就不需要定义临时表。当我们在一条SQL语句中只使用一次临时集合时，我们可以使用嵌套表表达式来定义临时集合；当我们在一条SQL语句中需要多次使用同一临时集合时，我们可以使用公共表表达式；只有当我们在一个工作单元中的多条SQL语句中使用同一临时集合时，我们才需要定义临时表。</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp; 可以通过以下三种方式定义临时表：</font></p>
<p><font style="background-color: #cce8cf">方法1：&nbsp;&nbsp; <br />
DECLARE GLOBAL TEMPORARY TABLE SESSION.EMP&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; NAME VARCHAR(10),---姓名&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; DEPT SMALLINT,---部门&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; SALARY DEC(7,2)---工资&nbsp;&nbsp; <br />
)&nbsp;&nbsp; <br />
ON COMMIT DELETE ROWS;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
方法2：&nbsp;&nbsp; <br />
DECLARE GLOBAL TEMPORARY TABLE session.emp&nbsp;&nbsp; <br />
LIKE staff INCLUDING COLUMN DEFAULTS&nbsp;&nbsp; <br />
WITH REPLACE&nbsp;&nbsp; <br />
ON COMMIT PRESERVE ROWS;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
方法3：&nbsp;&nbsp; <br />
DECLARE GLOBAL TEMPORARY TABLE session.emp AS&nbsp;&nbsp; <br />
(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; SELECT * FROM staff WHERE &lt;condition&gt;&nbsp;&nbsp; <br />
)&nbsp;&nbsp; <br />
DEFINITION ONLY&nbsp;&nbsp; <br />
WITH REPLACE;&nbsp;&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; 定义了临时表后，我们可以像使用普通表一样使用临时表。临时表只对定义它的用户有效，不同用户可以在同一时间定义同名的临时表，他们之间互不影响。临时表的生命周期是SESSION，当SESSION关闭时，临时表将自动删除，这也是临时表的模式名只能为SESSION的原因。此外，我们还可以给临时表定义索引。更多细节请参考DB2 信息中心。</font></p>
<br />
</font>
<img src ="http://www.blogjava.net/yes1983/aggbug/318271.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2010-04-14 16:53 <a href="http://www.blogjava.net/yes1983/archive/2010/04/14/318271.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Eclipse中去掉多余的UI组件的几个方法</title><link>http://www.blogjava.net/yes1983/archive/2009/07/26/Eclipse_extension_Activities_remove.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Sun, 26 Jul 2009 07:59:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2009/07/26/Eclipse_extension_Activities_remove.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/288445.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2009/07/26/Eclipse_extension_Activities_remove.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/288445.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/288445.html</trackback:ping><description><![CDATA[<font style="background-color: #cce8cf">Eclipse的扩展机制是其一个重要特色,但随着Eclipse功能越做越强,插件越来越多,你会发现GUI上的图标越来越多,Menu,toolbar,context menu都被占满了,其实很多item并不是我们需要的,但是contribute这些item的插件我们是需要的,那怎么去掉它们扩展的那些菜单项呢?<br />
1.在Plugin.xml中定制<br />
&nbsp;&nbsp; 这是最简单的办法,很多时候我们自己想写代码来去掉一些菜单项,但效果并不好.所以能在Plugin.xml中定制的,我们就&nbsp;尽量写在plugin.xml里面.下面举一个右键菜单的例子:<br />
&nbsp;&nbsp; 扩展右键菜单需要扩展org.eclipse.ui.popupMenus扩展点,我们一般都在它下面new一个action,但这个action扩展之后不管在&nbsp; 任何界面都会出现,如果我们想在某些条件下隐藏掉它该怎么办?仔细观察下org.eclipse.ui.popupMenus扩展点,其实我们还可以新建objectContribution扩展<br />
&nbsp;&nbsp; &lt;extension<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point="org.eclipse.ui.popupMenus"&gt;<br />
&nbsp;&nbsp; &lt;objectContribution<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id="my.example.objectContribution"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nameFilter="*example*"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectClass="java.io.File"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="my.example.MyAction"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id="my.example.MyAction"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label="Exe"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; menubarPath="additional"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/action&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/objectContribution&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/extension&gt;<br />
&nbsp;&nbsp;&nbsp; objectContribution里面也包含一个action,但这个action在popupmenu里出现是有条件的:我们给它定义了一个nameFilter,&nbsp;只有当selection()的path中包含了"example"才会显示,否则这个action是不会出现在&nbsp;popupmenu里的.这里的selection假设选中的是一个File,如果选中的是你自己写的类,那namefilter会在你的类的toString方法里面找keyword.<br />
2.使用Eclipse的Activities扩展<br />
&nbsp; plugin.xml并不能解决所有问题,当我们实在没有办法在plugin.xml中限制某些extension的出现的时候,可以考虑使用Eclipse的Activities.Activities的官方定义大家可以google一下eclipse的help.我个人的理解就是它可以和perspective一样控制UI的显示,但是Perspective设计的太易于扩展了,假如Plugin A在perspective上扩展了一个UI,那么Plugin B在每次进入这个perspective的时候就一定可以看得见它,而且在Eclipse的扩展机制下,Plugin B是没有权利去删了Plugin A的contribution的(Eclipse的ExtensionRegistry倒是提供了一个removeExtension方法,但运行的时候会报错).在这样的情况下,Activities的价值就体现出来了,你只要给它一个Extension的id,它就可以帮你把这个Extension disable掉.例如:<br />
&lt;extension<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point="org.eclipse.ui.activities"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id="my.example.activity"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="WizardActivity"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activity&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activityPatternBinding<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; activityId="my.example.activity"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pattern="my\.example/mywizard"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activityPatternBinding&gt;<br />
&nbsp;&lt;/extension&gt;<br />
&nbsp;比较重要的是activityPatternBinding中的pattern属性,它是由plugin id + "/" + local-id组成.比如在插件my.example中扩展了&nbsp;org.eclipse.ui.newWizards,id是mywizard,那么上面这个activityPatternBinding就会disable掉my.example的mywizard扩展,你在&nbsp;GUI中就看不见这个wizard了.pattern是支持正则表达式的,所以如果有"."的话需要用转义字符\.注意,这里的disable的意思并不是说我把mywizard这个扩展删掉了,而是屏蔽了它,mywizard仍然在&nbsp;ExtensionRegistry中.<br />
3.用代码来动态控制UI<br />
&nbsp;方法2只是隐藏掉一些扩展,但是有一些需求并不是简单的隐藏就可以了,我最近碰到的一个需求就是:有一个flag,只有当flag==1的时候扩展是可见的,否则是不可见的,需要disable这个扩展.这时就必须要加一些代码才能实现了,还是以方法2中的mywizard为例:<br />
&nbsp;IWorkbenchActivitySupport workbenchActivitySupport = PlatformUI.getWorkbench().getActivitySupport(); <br />
&nbsp;&nbsp;IActivityManager activityManager = workbenchActivitySupport.getActivityManager();<br />
&nbsp;&nbsp;Set enabledActivityIds = new HashSet(activityManager.getEnabledActivityIds()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(flag==1)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; if (enabledActivityIds.add("my.example.activity")) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workbenchActivitySupport.setEnabledActivityIds(enabledActivityIds);&nbsp; <br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(enabledActivityIds.remove("my.example.activity"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workbenchActivitySupport.setEnabledActivityIds(enabledActivityIds);<br />
&nbsp;&nbsp;}<br />
&nbsp;Activities可以是enable或者disable的,当你在plugin.xml中定义好了一个Activity,缺省它是disable的,就是说activityPatternBinding&nbsp;匹配的扩展是会被disable的,但你也可以把Activities设成enable的(在plugin.xml或者用代码都可以设置),它匹配的扩展是可以正常使用的.<br />
&nbsp;在上面的code sample中,我们通过activityManager.getEnabledActivityIds()得到所有enable的Activities.如果flag==1,那my.example.activity&nbsp;也应该被加入到enable Activities中,这样mywizard就可以显示在界面上,反之,就要在enable Activities中remove掉my.example.activity,它就变成<br />
&nbsp;disable,会把mywizard隐藏.</font>
<img src ="http://www.blogjava.net/yes1983/aggbug/288445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2009-07-26 15:59 <a href="http://www.blogjava.net/yes1983/archive/2009/07/26/Eclipse_extension_Activities_remove.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DB2学习笔记</title><link>http://www.blogjava.net/yes1983/archive/2009/06/17/282922.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Wed, 17 Jun 2009 14:02:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2009/06/17/282922.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/282922.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2009/06/17/282922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/282922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/282922.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Access Path<br>  1.并不是用index就一定快.有时候一个表只有很少的records,那么你直接scan这个表,比你先读index,再访问表要快.<br>  2.不过大多数情况下还是用index快一些(要不然这个技术就没有意义了).DB2中index的应用需要两个前提条件:<br>&nbsp;&nbsp;<a href='http://www.blogjava.net/yes1983/archive/2009/06/17/282922.html'>阅读全文</a><img src ="http://www.blogjava.net/yes1983/aggbug/282922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2009-06-17 22:02 <a href="http://www.blogjava.net/yes1983/archive/2009/06/17/282922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TreeViewer的setselection方法不能选中树的子节点?</title><link>http://www.blogjava.net/yes1983/archive/2009/05/11/270018.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Mon, 11 May 2009 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2009/05/11/270018.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/270018.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2009/05/11/270018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/270018.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/270018.html</trackback:ping><description><![CDATA[TreeViewer的setSelection方法使用后，会在树上选中并展开方法参数中对应的节点.但是有时候你发现它只能选中第一级节点,下面的子节点没有办法选中.其实这个方法是没有问题的,它的大概实现算法是:先找到某一个子节点,然后找到它的父节点,把父节点展开,然后又找父节点的父节点,做同样的操作,直到根节点为止,这样你才能看到选中的子节点.所以父节点如果为null,那肯定你是看不到子节点了.而我们很多人在实现ITreeContentProvide的接口的时候,是不实现getParent方法的,因为只要实现了getChildren方法就可以看见一棵树了.包括陈刚的&lt;Eclipse从入门到精通&gt;也是这样.所以在实现treeViewer的时候,最好还是实现getparent方法.其实也不麻烦,在添加一个child的时候,加一句setparent(this)就可以了
<img src ="http://www.blogjava.net/yes1983/aggbug/270018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2009-05-11 11:27 <a href="http://www.blogjava.net/yes1983/archive/2009/05/11/270018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java操作文本文件的方法详解(转载)</title><link>http://www.blogjava.net/yes1983/archive/2009/02/17/255126.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Tue, 17 Feb 2009 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2009/02/17/255126.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/255126.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2009/02/17/255126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/255126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/255126.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">最初java是不支持对文本文件的处理的，为了弥补这个缺憾而引入了Reader和Writer两个类，这两个类都是抽象类，Writer中 write(char[] ch,int off,int<br />
length)，flush()和close()方法为抽象方法，Reader中read(char[] ch,int off,int length)和close()方法是抽象方法。子类应该分别实现他们。<br />
　　当我们读写文本文件的时候，采用Reader是非常方便的，比如FileReader，InputStreamReader和BufferedReader。其中最重要的类是InputStreamReader，<br />
它是字节转换为字符的桥梁。你可以在构造器重指定编码的方式，如果不指定的话将采用底层操作系统的默认编码方式，例如GBK等。当使用FileReader读取文件<br />
的时候。<br />
FileReader fr = new FileReader("ming.txt");<br />
int ch = 0;<br />
while((ch = fr.read())!=-1 )<br />
{<br />
System.out.print((char)ch); <br />
}<br />
其中read()方法返回的是读取得下个字符。当然你也可以使用read(char[] ch,int off,int length)这和处理二进制文件的时候类似，不多说了。如果使用<br />
InputStreamReader来读取文件的时候<br />
while((ch = isr.read())!=-1)<br />
{<br />
System.out.print((char)ch); <br />
}<br />
这和FileReader并没有什么区别，事实上在FileReader中的方法都是从InputStreamReader中继承过来的。read()方法是比较好费时间的，如果为了提高效率<br />
我们可以使用BufferedReader对Reader进行包装，这样可以提高读取得速度，我们可以一行一行的读取文本，使用readLine()方法。<br />
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));<br />
String data = null;<br />
while((data = br.readLine())!=null)<br />
{<br />
System.out.println(data); <br />
}<br />
当你明白了如何用Reader来读取文本文件的时候那么用Writer写文件同样非常简单。有一点需要注意，当你写文件的时候，为了提高效率，写入的数据会先<br />
放入缓冲区，然后写入文件。因此有时候你需要主动调用flush()方法。与上面对应的写文件的方法为：<br />
FileWriter fw = new FileWriter("hello.txt");<br />
String s = "hello world";<br />
fw.write(s,0,s.length());<br />
fw.flush();<br />
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hello2.txt"));<br />
osw.write(s,0,s.length());<br />
osw.flush();<br />
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("hello3.txt")),true);<br />
pw.println(s);<br />
不要忘记用完后关闭流！下面是个小例子，帮助新手理解。其实有的时候java的IO系统是需要我们多记记的，不然哪天就生疏了。</font></p>
<p><font style="background-color: #cce8cf">import java.io.*;<br />
public class TestFile2<br />
{<br />
public static void main(String[] args) throws IOException<br />
{<br />
FileReader fr = new FileReader("ming.txt");<br />
char[] buffer = new char[1024];<br />
int ch = 0;<br />
while((ch = fr.read())!=-1 )<br />
{<br />
System.out.print((char)ch); <br />
}<br />
　　InputStreamReader isr = new InputStreamReader(new FileInputStream("ming.txt"));<br />
while((ch = isr.read())!=-1)<br />
{<br />
System.out.print((char)ch); <br />
}<br />
　　BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));<br />
String data = null;<br />
while((data = br.readLine())!=null)<br />
{<br />
System.out.println(data); <br />
}<br />
　　FileWriter fw = new FileWriter("hello.txt");<br />
String s = "hello world";<br />
fw.write(s,0,s.length());<br />
fw.flush();<br />
　　OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hello2.txt"));<br />
osw.write(s,0,s.length());<br />
osw.flush();<br />
　　PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("hello3.txt")),true);<br />
pw.println(s);</font></p>
<p><font style="background-color: #cce8cf">　　fr.close();<br />
isr.close();<br />
br.close();<br />
fw.close();<br />
osw.close();<br />
pw.close();<br />
} <br />
}</font></p>
<p><font style="background-color: #cce8cf">java中多种方式读文件<br />
一、多种方式读文件内容。<br />
1、按字节读取文件内容<br />
2、按字符读取文件内容<br />
3、按行读取文件内容<br />
4、随机读取文件内容</font></p>
<p><font style="background-color: #cce8cf">import java.io.BufferedReader;<br />
import java.io.File;<br />
import java.io.FileInputStream;<br />
import java.io.FileReader;<br />
import java.io.IOException;<br />
import java.io.InputStream;<br />
import java.io.InputStreamReader;<br />
import java.io.RandomAccessFile;<br />
import java.io.Reader; <br />
public class ReadFromFile {<br />
/**<br />
* 以字节为单位读取文件，常用于读二进制文件，如图片、声音、影像等文件。<br />
* @param fileName 文件的名<br />
*/<br />
public static void readFileByBytes(String fileName){<br />
File file = new File(fileName);<br />
InputStream in = null;<br />
try {<br />
System.out.println("以字节为单位读取文件内容，一次读一个字节：");<br />
// 一次读一个字节<br />
in = new FileInputStream(file);<br />
int tempbyte;<br />
while((tempbyte=in.read()) != -1){<br />
System.out.write(tempbyte);<br />
}<br />
in.close();<br />
} catch (IOException e) {<br />
e.printStackTrace();<br />
return;<br />
}<br />
try {<br />
System.out.println("以字节为单位读取文件内容，一次读多个字节：");<br />
//一次读多个字节<br />
byte[] tempbytes = new byte[100];<br />
int byteread = 0;<br />
in = new FileInputStream(fileName);<br />
ReadFromFile.showAvailableBytes(in);<br />
//读入多个字节到字节数组中，byteread为一次读入的字节数<br />
while ((byteread = in.read(tempbytes)) != -1){<br />
System.out.write(tempbytes, 0, byteread);<br />
}<br />
} catch (Exception e1) {<br />
e1.printStackTrace();<br />
} finally {<br />
if (in != null){<br />
try {<br />
in.close();<br />
} catch (IOException e1) {<br />
}<br />
}<br />
}<br />
}<br />
/**<br />
* 以字符为单位读取文件，常用于读文本，数字等类型的文件<br />
* @param fileName 文件名<br />
*/<br />
public static void readFileByChars(String fileName){<br />
File file = new File(fileName);<br />
Reader reader = null;<br />
try {<br />
System.out.println("以字符为单位读取文件内容，一次读一个字节：");<br />
// 一次读一个字符<br />
reader = new InputStreamReader(new FileInputStream(file));<br />
int tempchar;<br />
while ((tempchar = reader.read()) != -1){<br />
//对于windows下，rn这两个字符在一起时，表示一个换行。<br />
//但如果这两个字符分开显示时，会换两次行。<br />
//因此，屏蔽掉r，或者屏蔽n。否则，将会多出很多空行。<br />
if (((char)tempchar) != 'r'){<br />
System.out.print((char)tempchar);<br />
}<br />
}<br />
reader.close();<br />
} catch (Exception e) {<br />
e.printStackTrace();<br />
}<br />
try {<br />
System.out.println("以字符为单位读取文件内容，一次读多个字节：");<br />
//一次读多个字符<br />
char[] tempchars = new char[30];<br />
int charread = 0;<br />
reader = new InputStreamReader(new FileInputStream(fileName));<br />
//读入多个字符到字符数组中，charread为一次读取字符数<br />
while ((charread = reader.read(tempchars))!=-1){<br />
//同样屏蔽掉r不显示<br />
if ((charread == tempchars.length)&amp;&amp;(tempchars[tempchars.length-1] != 'r')){<br />
System.out.print(tempchars);<br />
}else{<br />
for (int i=0; i&lt;charread; i++){<br />
if(tempchars[i] == 'r'){<br />
continue;<br />
}else{<br />
System.out.print(tempchars[i]);<br />
}<br />
}<br />
}<br />
}</font></p>
<p><font style="background-color: #cce8cf">} catch (Exception e1) {<br />
e1.printStackTrace();<br />
}finally {<br />
if (reader != null){<br />
try {<br />
reader.close();<br />
} catch (IOException e1) {<br />
}<br />
}<br />
}<br />
}<br />
/**<br />
* 以行为单位读取文件，常用于读面向行的格式化文件<br />
* @param fileName 文件名<br />
*/<br />
public static void readFileByLines(String fileName){<br />
File file = new File(fileName);<br />
BufferedReader reader = null;<br />
try {<br />
System.out.println("以行为单位读取文件内容，一次读一整行：");<br />
reader = new BufferedReader(new FileReader(file));<br />
String tempString = null;<br />
int line = 1;<br />
//一次读入一行，直到读入null为文件结束<br />
while ((tempString = reader.readLine()) != null){<br />
//显示行号<br />
System.out.println("line " + line + ": " + tempString);<br />
line++;<br />
}<br />
reader.close();<br />
} catch (IOException e) {<br />
e.printStackTrace();<br />
} finally {<br />
if (reader != null){<br />
try {<br />
reader.close();<br />
} catch (IOException e1) {<br />
}<br />
}<br />
}<br />
}<br />
/**<br />
* 随机读取文件内容<br />
* @param fileName 文件名<br />
*/<br />
public static void readFileByRandomAccess(String fileName){<br />
RandomAccessFile randomFile = null;<br />
try {<br />
System.out.println("随机读取一段文件内容：");<br />
// 打开一个随机访问文件流，按只读方式<br />
randomFile = new RandomAccessFile(fileName, "r");<br />
// 文件长度，字节数<br />
long fileLength = randomFile.length();<br />
// 读文件的起始位置<br />
int beginIndex = (fileLength &gt; 4) ? 4 : 0;<br />
//将读文件的开始位置移到beginIndex位置。<br />
randomFile.seek(beginIndex);<br />
byte[] bytes = new byte[10];<br />
int byteread = 0;<br />
//一次读10个字节，如果文件内容不足10个字节，则读剩下的字节。<br />
//将一次读取的字节数赋给byteread<br />
while ((byteread = randomFile.read(bytes)) != -1){<br />
System.out.write(bytes, 0, byteread);<br />
}<br />
} catch (IOException e){<br />
e.printStackTrace();<br />
} finally {<br />
if (randomFile != null){<br />
try {<br />
randomFile.close();<br />
} catch (IOException e1) {<br />
}<br />
}<br />
}<br />
}<br />
/**<br />
* 显示输入流中还剩的字节数<br />
* @param in<br />
*/<br />
private static void showAvailableBytes(InputStream in){<br />
try {<br />
System.out.println("当前字节输入流中的字节数为:" + in.available());<br />
} catch (IOException e) {<br />
e.printStackTrace();<br />
}<br />
}</font></p>
<p><font style="background-color: #cce8cf">public static void main(String[] args) {<br />
String fileName = "C:/temp/newTemp.txt";<br />
ReadFromFile.readFileByBytes(fileName);<br />
ReadFromFile.readFileByChars(fileName);<br />
ReadFromFile.readFileByLines(fileName);<br />
ReadFromFile.readFileByRandomAccess(fileName);<br />
}<br />
}</font></p>
<p><font style="background-color: #cce8cf">二、将内容追加到文件尾部</font></p>
<p><font style="background-color: #cce8cf">import java.io.FileWriter;<br />
import java.io.IOException;<br />
import java.io.RandomAccessFile;</font></p>
<p><font style="background-color: #cce8cf">/**<br />
* 将内容追加到文件尾部<br />
*/<br />
public class AppendToFile {</font></p>
<p><font style="background-color: #cce8cf">/**<br />
* A方法追加文件：使用RandomAccessFile<br />
* @param fileName 文件名<br />
* @param content 追加的内容<br />
*/<br />
public static void appendMethodA(String fileName,</font></p>
<font style="background-color: #cce8cf">
<p><br />
String content){<br />
try {<br />
// 打开一个随机访问文件流，按读写方式<br />
RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");<br />
// 文件长度，字节数<br />
long fileLength = randomFile.length();<br />
//将写文件指针移到文件尾。<br />
randomFile.seek(fileLength);<br />
randomFile.writeBytes(content);<br />
randomFile.close();<br />
} catch (IOException e){<br />
e.printStackTrace();<br />
}<br />
}<br />
/**<br />
* B方法追加文件：使用FileWriter<br />
* @param fileName<br />
* @param content<br />
*/<br />
public static void appendMethodB(String fileName, String content){<br />
try {<br />
//打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件<br />
FileWriter writer = new FileWriter(fileName, true);<br />
writer.write(content);<br />
writer.close();<br />
} catch (IOException e) {<br />
e.printStackTrace();<br />
}<br />
}</p>
<p>public static void main(String[] args) {<br />
String fileName = "C:/temp/newTemp.txt";<br />
String content = "new append!";<br />
//按方法A追加文件<br />
AppendToFile.appendMethodA(fileName, content);<br />
AppendToFile.appendMethodA(fileName, "append end. n");<br />
//显示文件内容<br />
ReadFromFile.readFileByLines(fileName);<br />
//按方法B追加文件<br />
AppendToFile.appendMethodB(fileName, content);<br />
AppendToFile.appendMethodB(fileName, "append end. n");<br />
//显示文件内容<br />
ReadFromFile.readFileByLines(fileName);<br />
}<br />
}</font></p>
<img src ="http://www.blogjava.net/yes1983/aggbug/255126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2009-02-17 16:17 <a href="http://www.blogjava.net/yes1983/archive/2009/02/17/255126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse的奇怪问题总结(不断更新)</title><link>http://www.blogjava.net/yes1983/archive/2008/12/02/243982.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Tue, 02 Dec 2008 09:52:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2008/12/02/243982.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/243982.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2008/12/02/243982.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/243982.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/243982.html</trackback:ping><description><![CDATA[1.有的时候在project的java build path中定义好了一些jar包依赖,但是project在运行的时候仍然报NoClassDef的错误.这是因为project的MANIFEST.MF文件没有更新.手动在MANIFEST.MF加上那些jar包就可以了.<br />
2.Plugin A 依赖 Plugin B.B也把相应的package export出来了,但是A还是找不到B里面定义的类.修改A的MANIFEST.MF文件,在dependence tab里去掉Plugin B,再添加B.此时发现有5,6个同样的Plugin B出现在选择plugin的list中.cancel 掉该对话框,然后重启eclipse,在A的dependence里面重新加上B,问题解决. <br />
3.当我们通过在plugin.xml中用extension的方式定义action的时候,你会发现你定义的actionset和action在GUI出现的顺序不是你可以控制的,就是说同一个actionset下的多个action不是按你定义的先后顺序出现在程序的界面上的,这样对action进行排序呢?其实仔细观察一下,你会发现action在GUI出现的顺序是和你定义action的顺序相反的,比如你先后定义了3个action A,B,C,那么你就会在GUI上看见action的顺序是C,B,A.如果你定义了多个actionset,你会发现这个规律不适用与actionset,actionset在界面上出现的顺序其实是和它的id的排序相反的.比如你定义了三个actionset,它们的id分别是:seta,setb,setc,你会发现GUI上出现的顺序是setc,setb,seta <br />
4.双击激活TreeViewer的celleditor<br />
&nbsp; JFace的Viewer都有单元格编辑功能,但是celleditor默认的实现是单击激活editor,双击选中item.如果需要改成单击选中item,双击激活editor呢?Eclipse的官网上好像也有人问到这个问题,不过目前好像是开了一个bug,期待eclipse的下个版本解决这个问题.但最近找到了一个用SWT来解决这个问题的方法:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tree tree=treeViewer.getTree();<br />
&nbsp;&nbsp;&nbsp; <font style="background-color: #cce8cf">final TreeEditor editor = new TreeEditor(tree);<br />
&nbsp;&nbsp;editor.horizontalAlignment = SWT.LEFT;<br />
&nbsp;&nbsp;editor.grabHorizontal = true;<br />
&nbsp;&nbsp;// Use a mouse listener, not a selection listener, because you're<br />
&nbsp;&nbsp;// interested<br />
&nbsp;&nbsp;// in the selected column as well as row<br />
&nbsp;&nbsp;tree.addMouseListener(new MouseAdapter() {<br />
&nbsp;&nbsp;&nbsp;public void mouseDoubleClick(MouseEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;final TreeItem item = tree.getSelection()[0];<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Create a text field to do the editing<br />
&nbsp;&nbsp;&nbsp;&nbsp;final Text text = new Text(tree, SWT.NONE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;text.setText(item.getText());<br />
&nbsp;&nbsp;&nbsp;&nbsp;text.selectAll();<br />
&nbsp;&nbsp;&nbsp;&nbsp;text.setFocus();<br />
&nbsp;&nbsp;&nbsp;&nbsp;text.addFocusListener(new FocusAdapter() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void focusLost(FocusEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text.dispose();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;});<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Set the text field into the editor<br />
&nbsp;&nbsp;&nbsp;&nbsp;editor.setEditor(text, item);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;});</font>
<img src ="http://www.blogjava.net/yes1983/aggbug/243982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2008-12-02 17:52 <a href="http://www.blogjava.net/yes1983/archive/2008/12/02/243982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse中如何消除快捷键定义冲突(keybinding conflict)</title><link>http://www.blogjava.net/yes1983/archive/2008/10/14/234273.html</link><dc:creator>小牛小虾</dc:creator><author>小牛小虾</author><pubDate>Tue, 14 Oct 2008 09:42:00 GMT</pubDate><guid>http://www.blogjava.net/yes1983/archive/2008/10/14/234273.html</guid><wfw:comment>http://www.blogjava.net/yes1983/comments/234273.html</wfw:comment><comments>http://www.blogjava.net/yes1983/archive/2008/10/14/234273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yes1983/comments/commentRss/234273.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yes1983/services/trackbacks/234273.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 由于Eclipse的易扩展性,理论上可以有无数个Action运行在一个RCP 程序中,但是快捷键是有限的,尤其是一些常用的,像Ctrl+C,Ctrl+S之类的普通用户能记得住的就那么几个,万一你自定义的Action的快捷键和Eclipse默认的发生了冲突怎么办?比如Eclipse默认Ctrl+S是Save的快捷键,但是你又自定义了一个SaveAction,希望用户按下Ctrl+S之后执行的是自己的SaveAction的run方法.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 一般给Action绑定快捷键的方法是自定义binding和command,然后在action中指定definition id为command的id.如下:<br />
<font style="background-color: #cce8cf">&lt;extension<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point="org.eclipse.ui.bindings"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commandId="myplugin.actions.save"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contextId="org.eclipse.ui.contexts.window"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sequence="CTRL+S"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/key&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/extension&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;extension<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point="org.eclipse.ui.commands"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;command<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id="myplugin.actions.save"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="Save"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/command&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/extension&gt;</font><br />
这样的方法一般是不会有冲突的,但是像我们上面提到的情况,如果你自定义一个binding,它的key sequence是Ctrl+S,那就会有问题.由于org.eclipse.ui插件已经提供了一个Ctrl+S的快捷键,所以系统中会有两个Ctrl+S,这样Eclipse会在右下角pop up一个assist dialog,让你从两个Action中选择一个,这样可能会造成一些用户使用上的不习惯.<br />
解决办法:<br />
&nbsp;&nbsp;&nbsp; 1.直接改快捷键.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个最简单了,比如把你自己的save定义成Alt+S.但是这个方法也是最不好的方法,因为很多用户并不知道Alt+S在你的程序里面就是save.<br />
&nbsp;&nbsp;&nbsp; 2.修改自定义action的definition id<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们刚才说过,action的definition id绑定着一个command,而command又对应着一个binding,Eclipse通过这样的方式实现action和快捷键的绑定.我们再来看看Eclipse定义的command和key binding(摘自org.eclipse.ui的plugin.xml):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font style="background-color: #cce8cf">&lt;command<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="%command.save.name"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description="%command.save.description"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; categoryId="org.eclipse.ui.category.file"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id="org.eclipse.ui.file.save" /&gt;<font style="background-color: #cce8cf"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commandId="org.eclipse.ui.file.save"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sequence="M1+S"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key</font></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; Eclipse的Save Action把definition id指定为org.eclipse.ui.file.save,然后它就和上面的command进行了绑定,而这个command对应的key就是"M1+S"(Ctrl + S),这样就实现了快捷键绑定.如果我们也把自定义的Save Action的definition id指定为org.eclipse.ui.file.save,是不是就可以达到目的呢?答案是肯定的.<br />
&nbsp;&nbsp;&nbsp;&nbsp; Eclipse中的Action存在着一个类似"优先级"的概念(具体实现是通过action handler).越"具体"的action,优先级越高.Eclipse的Save Action明显是一个global的action,(同样的global action还有copy, cut,undo,redo等等).而我们自定义的action一般是实现了<font style="background-color: #cce8cf">IWorkbenchWindowActionDelegate</font>接口的,就是说,它是contribute to workbench window的,它是一个workbench action,它的优先级就高于任何global action.同理,如果你定义一个editor action或者view action,由于它比workbench还"具体"(workbench可以包含多个editor或view,workbench action对这些editor或view都是有效的;而editor action只对某个具体的editor有效),所以editor action的优先级就高于workbench action.这样,如果自定义的action和eclipse缺省的action都绑定到同一个command,那么eclipse runtim最后会选择自定义的action来执行.<br />
&nbsp;&nbsp;&nbsp; 3.终极解决大法:自定义schema<br />
&nbsp;&nbsp;&nbsp;&nbsp; Eclipse 有一个default的快捷键schema文件:org.eclipse.ui.defaultAcceleratorConfiguration.它存储着Eclipse所有的快捷键.如果你自定义一个自己的schema文件,并把它设成当前使用的schema文件,那么Eclipse就会调用自定义的schema文件.(新的schema文件可以在org.eclipse.ui.bindings扩展点中定义,请注意,在定义新schema的时候由一个parentID属性,如果你定义了它,新的schema会像类继承一样把parent schema里面的key binding全继承下来.如果不定义,则是一个全新的schema)<br />
&nbsp;&nbsp;&nbsp; 假定我们已经有了一个新的schema文件,id是myplugin.schema.然后我们在org.eclipse.ui.bindings下定义一个key:<br />
&lt;key<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commandId="myplugin.actions.save"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contextId="org.eclipse.ui.contexts.window"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; schemaId="myplugin.schema"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sequence="CTRL+S"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/key&gt;<br />
我们已经把schemaId换成了myplugin.schema,表示我们把CTRL+S加到了myplugin.schema中,然后把新建的schema文件在product配置文件<font style="background-color: #cce8cf">plugin_customization.ini</font>中设置成当前的key schema文件:<br />
<font style="background-color: #cce8cf">org.eclipse.ui/KEY_CONFIGURATION_ID</font>=myplugin.schema<br />
<br />
这种方法虽然麻烦了一点,但却可以治标又治本.而且由于可以指定parent schema,我们完全可以把org.eclipse.ui.defaultAcceleratorConfiguration作为parent schema,继承它全部的快捷键配置,只定制几个会产生冲突的快捷键即可</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
 <img src ="http://www.blogjava.net/yes1983/aggbug/234273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yes1983/" target="_blank">小牛小虾</a> 2008-10-14 17:42 <a href="http://www.blogjava.net/yes1983/archive/2008/10/14/234273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>