posts - 495,  comments - 11,  trackbacks - 0
 

先说下CVSNT的用户验证方式,CVSNT的用户验证方式分两种:Windows系统用户与CVSNT用户共存的混合验证方式,及CVSNT用户 单一验证方式,默认工作在混合验证方式下,当然使用单一验证方式对用户的管理肯定比较方便一点,因此下面的配置就是围绕该方式进行的。各个资源库所使用的 验证方式及用户配置由其目录下CVSROOT里的配置文件决定,其中有几个比较重要的文件。


1、config文件

控制CVSNT的验证工作方式的就是config文件,注意该文件最前面的两行:

#Set this to `no" if pserver shouldn"t check system users/passwords
#SystemAuth=yes

第二行就是我们要修改的内容,默认状态是被注释掉的,SystemAuth有两个值yes和no:

yes:pserver将使用Windows系统用户和CVSNT用户来共同验证(若CVSNT用户未定义,则用Windows系统用户来进行验证),默认为yes,CVSNT用户在后面将要介绍的passwd文件中定义。

no:只使用CVSNT用户来进行验证。

该文件可以在客户端进行修改,因此我们可以将其checkout出来将第二行改为SystemAuth=no,并commit到CVSNT上就可以启用单一验证方式了,注意启用单一验证方式后原来的Windows系统用户将变为无效,因此要注意执行该步骤的时机。

2、 admin文件

该文件保存CVSNT管理员用户列表,内容很简单,形式如下:
User1
User2
User3
每一行定义一个管理 员用户,默认时没有该文件,但你可以在客户端自己添加并add上去,再commit到CVSNT上,但是光有这个文件还是不会生效的,还要将其添加到 checklist文件中,使CVSNT能够读取该文件的内容,在checklist中添加文件列表的格式为:

[空格]文件名 出错信息

其中文件名前的空格必须要有的,不然会出错。
我们可以先添加admin文件到CVSNT中,再修改checklist文件commit,就可以使admin文件生效了。

3、passwd文件

服务器工作在CVSNT用户单一验证方式下的时候,这个文件定义了CVSNT的用户信息,这里面保存着用户名,用户密码,以及别名信息。默认状态下 没有该文件,但是我们可以在CVSNT还工作在混合验证方式下时,用系统管理员登录,通过添加用户命令来让CVSNT自动建立一个passwd文件。

添加用户的命令的示例:

cvs passwd –r administrator –a cvsadmin

之后系统提示输入密码,输入后服务器会新建一个passwd文件。

该文件的内容很简单,形式如下:

cvsadmin:fqr1fS4gDghrt:administrator
kid:aTXRfS31Bm6JA
mystique:Yna4QcXz9dEqd

以第一行为例:cvsadmin为用户名,fqr1fS4gDghrt为CVS使用UNIX标准加密函数对密码进行加密后的结果,administrator为该用户的别名,当使用混合验证方式时对应Windows系统用户名。

注意:这个文件是不能在客户端进行修改的,不能checkout出来。

4、group文件

该文件定义CVSNT中组信息,同组里的用户拥有一样的权限,对组权限的修改和对用户权限的修改一样。

group文件的内容为

administrators:cvsadmin kid mystique
users:User1 User2 User3

可以看到该文件的内容也很简单,组名:用户名,多个用户名之间用空格隔开。

Group文件可以在客户端修改,不用修改checkoutlist这个文件,系统会自动使其生效。

作为组里面的特定成员可以赋给特定的权限。

了解了以上内容,下面我说一下我自己的配置步骤,我没有使用WinCVS进行操作,是直接使用命令行进行修改的,觉得这样思路比较清晰:

1、添加系统变量CVSROOT=E:/CVSNT/Repository,并把E:CVSNT加入到系统Path路径。

2、进入命令提示符,因为此时为混合验证模式,可以不用不用登陆直接进行checkout。可以建立一个工作目录,在该目录下进行操作,我这里为E:/CVSNT/Works。

检出CVSROOT目录:

cvs co CVSROOT

3、添加CVSNT系统管理员用户,此时会提示设置用户密码:

cvs passwd –r administrator –a cvsadmin

4、修改CVSROOT访问权限:

cd CVSROOT
cvs chown cvsadmin //更改所有者为cvsadmin
cvs chacl default:n //默认权限为n
cvs chacl cvsadmin:rwc //添加cvsadmin

5、修改config文件,按上面的方法修改后commit:

cvs ci

6、此时单一验证方式已经启用了,也就是只能使用刚才添加的cvsadmin进行登录,此时可以把CVSNT控制面板上的Use local users for pserver authentication instead of domain users关掉。登录前还要改一下系统变量CVSROOT,关闭命令提示符窗口,修改CVSROOT为:

:pserver:cvsadmin@192.168.0.1:4021/CVSNT/Repository

这里的192.168.0.1是服务器的IP地址,/CVSNT/Repository就是前面设置Repository时设置的Name,可以改为你机器上的配置。修改系统变量之后以下的步骤在任何与服务器相连的机器上进行,当然该机器上应该有CVSNT的可执行文件。

7、如果为了避免出现错误,先重启一下CVSNT服务器,再启动命令提示符来到E:/CVSNT/Works,因为已经启用单一验证方式,先要进行登录。

cvs login

输入密码,此时就是以cvsadmin登录了。

8、添加admin文件,首先将CVSROOT检出,在CVSROOT下新建admin文件,内容为

cvsadmin

执行命令:

cvs add admin
cvs ci

9、修改checklist文件,在该文件末尾添加一行:

[空格]admin error message

注意:admin前的空格不能少。

执行命令:

cvs ci

经过以上步骤,可以说用户配置已经基本完成了,CVSNT可以很好的工作在单一验证方式下。进一步的管理可使用以下命令:

添加用户: cvs passwd -a username,使用时不必理会需要添加别名的提示。

修改用户权限:cvs chacl username:r|w|c|n,(r:Read w:write c:control n:none)

要添加组管理,只需同添加admin步骤一样,按照格式要求新建group文件即可。

如果还有不清楚的可以看看自带的文档,说得还是比较详细的。

posted @ 2007-12-01 13:27 jadmin 阅读(39) | 评论 (0)编辑 收藏
CVS

一、什么是CVS?

CVS――Concurrent Versions System并行版本系统;
是一个标准的版本控制系统;
对代码进行集中管理;
记录代码所有的更改历史;
提供协作开发的功能;
支持多人同时CheckOut与合并。
以客户端/服务器模式工作,所有的用户都在客户端进行CVS操作,而所有命令的执行都在CVS服务器端进行。

二、CVS基本概念

  1. CVS仓库:又称主拷贝,是CVS系统保存软件资源的地方。所有项目的所有文件的所有版本都保存在这个仓库中。
  2. 版本:开发人员每次向CVS提交所做的修改就形成了一个新版本。
  3. 工作拷贝:从CVS服务器端取出的,保存在我们正在使用的客户端计算机上的代码拷贝。每个人员都有一个属于自己的工作拷贝。
  4. 检出代码(创建工作拷贝check out):从服务器取出代码,就是创建工作拷贝的过程。
  5. 提交代码(commit):将代码送到服务器保存,commit又叫作check in。
  6. 导入代码(import):将未被CVS进行版本管理的代码引入CVS系统中,由CVS开始对它进行版本管理。
  7. CVS日志:CVS用来记录每次操作的内容的信息。日志信息可以用cvs log命令来查看。
  8. 更新(update):在协同开发环境下,将其他人所作的最新修改从CVS仓库中取到你的工作拷贝中,从而使得你得工作拷贝与仓库中得最新版本保持一致。使用update是同步各个工作拷贝的手段。
  9. 冲突(conflict):在协同开发的环境下,当两个开发人员对同一个文件进行修改,并且依次提交CVS仓库时就发生了冲突。这种冲突需要开发人员手工消除,并提交到CVS仓库中形成解除冲突之后的新版本。

三、CVS命令:

1.设置环境变量。

set CVSROOT=:pserver:xxx@192.168.0.226:e:/cvsroot

set CVSROOT=:pserver:xxx@ansi.3322.org:e:/cvsroot

2.签出工作版本到工作目录。
$cd

$cvs    co    account/src/common
该命令只将account/src/common目录结构签出到本地。若使用
$cvs co account
则将account下所有目录结构签出来。

3.提交修改的文件到CVS版本库中:

$cvs    ci    <filename>
注意若提交多个文件可以输入多个文件名,并以空格分开。若将该目录下所有文件都提交,那么只需
$cvs    ci <回车>
即可。

4.提交新增加的目录或文件到CVS版本库中:

$cvs    add    <dirname>

$cvs    ci    <dirname>

$cvs    add    <filename>

$cvs    ci    <filename>

5.删除目录及文件,需先删除目录下的文件

$rm    <filename>

$cvs    remove    <filename>

$cvs    ci    <filename>

再执行
$cd ..
$cvs up –P

则将该空目录删除(只是删除本地工作拷贝的空目录)。

6.查看文件状态

$cvs status <filename>

例如:
$ cvs st ffun.c

=================================================================

File: ffun.c              Status: Up-to-date

     Working revision:      1.1       Wed Nov    6 11:29:04 2002

     Repository revision: 1.1       /szunicom/dev/billing/src/preproc/CDMA/ffun.c,v

     Sticky Tag:            (none)

     Sticky Date:           (none)

     Sticky Options:        (none)

注意:最重要的是Status栏,可以有以下几种状态:

Up-to-date

:表明你的工作拷贝是最新的.
Locally Modified:表明你曾经修改过该文件,但还没有提交,你的版本比仓库里的新.
Needing Patch:表明有人已经修改过该文件并且已经提交了!你没有修改但你的工作拷贝的版本比仓库里的旧.
Needs Merge:表明你修改了该文件但没有提交,而有人也修改了这个文件,并且提交给仓库了。

Locally added

:表明使用了"add"命令增加了该文件,但还没有"commit"

Locally Removed

:表明你使用了"remove"命令,但还没有"commit"

Unkown

:CVS不知道关于这个文件的情况.例如,你创建了一个新文件,而没有使用"add"命令
解决办法:
若状态为Locally Modified,则需执行$cvs ci <filename>
若状态为Needing Patch或Needing Merge,则需执行$cvs up <filename>
将版本库里的文件与工作拷贝合并后,再提交给版本库,使用命令:

$cvs ci <filename>


若状态为:Locallyadded,则需执行$cvs ci <filename>
若状态为:Removed,则需执行$cvs ci <filename>
若状态为:Unkown,则需执行$cvs add <filename>,$cvs ci <filename>。

7.查看工作拷贝和仓库中最后版本之间的修改

$ cvs diff src.c

8.查看指定的两个版本之间的修改

$ cvs diff -r 1.1 -r 1.2 <filename>

9.版本回退(取出以前的某个版本)
有两种方式:
一是只把某一版本的文件输出到标准输出上:

$cvs up –p –r <版本号> <filename>

“-p”选项让CVS命令的结果只输出到标准输出,而不写入到结果文件中。

另一种是将输出到标准输出的结果重定向到文件中:
$cvs up –p –r <版本号> <filename> > <filename>

如:目前abc.c文件的版本号为1.5,要取出1.2的版本,那么执行
$cvs up –p –r 1.2 abc.c > abc.c

若没有使用“-p”选项进行回退,而是使用了$cvs up –r 1.2 abc.c命令,之后若对1.2版本进行修改后再提交到CVS时,会出现如下提示信息:
cvs ci

cvs commit: Examining .

cvs commit: sticky tag `1.2' for file `abc.c' is not a branch

cvs [commit aborted]: correct above errors first!

解决办法两种方式:

1、修改CVS/Entries文件,将以下黄色标记部分删除即可。

$cd CVS

$ vi E*

/abc.c/1.2/Tue Dec 17 13:33:06 2002//T1.2


2、使用$cvs up –A abc.c命令来消除附着标签,但是该命令是将1.2版本与最新版本进行了合并,还需对abc.c进行修改再重新提交。

10.如何恢复已经删除的文件或目录:
1. 在执行了【Remove】命令之后恢复文件。 ◇ 【Ctrl+L】直接输入命令cvs add xxxxx,或执行【Add Selection】界面操作。 ◇ 这样就可以直接恢复还未提交的删除文件。
2. 在执行了【Commit】命令之后恢复文件。 ◇ 只能用【Ctrl+L】直接输入命令cvs add xxxxx,这时会得到一个空的文件。 ◇ 选中这个空文件,执行【Update】操作,得到这个文件的实体。 ◇ 再次选中这个文件,执行【Commit】操作,得到这个文件最新版本。
3. 由于CVS系统中本质上不会删除任何目录,因此,谈不上对目录的恢复,但是CVS系统默认情况下是要在用户本机上(如:YCW2000)要删除空目录,因此,可以用如下方法得到已被删除的空目录:cvs checkout -p xxx,也可以在Admin=>Preference的【Globals】页面进行设置。

=============================================================================

CVS是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。工作模式如下:

CVS服务器(文件版本库)

/ | \ (版 本 同 步)

/ | \

开发者1 开发者2 开发者3

CVS(Concurrent Version System)版本控制系统是一种GNU软件包,主要用于在多人开发环境下的源码的维护。实际上CVS可以维护任意文档的开发和使用,例如共享文件的编辑修改,而不仅仅局限于程序设计。CVS维护的文件类型可以是文本类型也可以是二进制类型。CVS用Copy-Modify-Merge(拷贝、修改、合并)变化表支持对文件的同时访问和修改。它明确地将源文件的存储和用户的工作空间独立开来,并使其并行操作。CVS基于客户端/服务器的行为使其可容纳多个用户,构成网络也很方便。这一特性使得CVS成为位于不同地点的人同时处理数据文件(特别是程序的源代码)时的首选。

所有重要的免费软件项目都使用CVS作为其程序员之间的中心点,以便能够综合各程序员的改进和更改。这些项目包括GNOME、KDE、THE GIMP和Wine等。

CVS的基本工作思路是这样的:在一台服务器上建立一个源代码库,库里可以存放许多不同项目的源程序。由源代码库管理员统一管理这些源程序。每个用户在使用源代码库之前,首先要把源代码库里的项目文件下载到本地,然后用户可以在本地任意修改,最后用CVS命令进行提交,由CVS源代码库统一管理修改。这样,就好象只有一个人在修改文件一样,既避免了冲突,又可以做到跟踪文件变化等。

CVS是并发版本系统(Concurrent Versions System)的意思,主流的开放源码网络透明的版本控制系统。CVS对于从个人开发者到大型,分布团队都是有用的:

它的客户机/服务器存取方法使得开发者可以从任何因特网的接入点存取最 新的代码。它的无限制的版本管理检出(check out:注1)的模式避免了通常的因为排它 检出模式而引起的人工冲突。 它的客户端工具可以在绝大多数的平台上使用。

CVS被应用于流行的开放源码工程中,象Mozilla,GIMP,XEmacs,KDE,和GNOME等。 那么它到底怎么样?

你可能会说,它非常棒,但是对于 "我"来说它能做什么?首先,基本的 :一个版本控制系统保持了对一系列文件所作改变的历史记录。对于一个开发者来说,那就意味着在你对一个程 序所进行开发的整个期间,能够跟踪对其所作的所有改动的痕迹。对你来说,有没有出现过由于在令行上 按错键而导致一天的工作都白费的情况呢?版本控制系统给了你一个安全的网络。

版本控制系统对任何人都有用,真的。(毕竟,谁不愿意使用一个安全的 网络呢?)但是它们经常被软件开发团队使用。在团队中工作的开发者需要能够调整他们的各自的修改;一个集 中式版本控制系统允许那样做。
代码集中的配置

个人开发者希望一个版本控制系统的安全网络能够运行在他们的本地的 一台机器上。然而,开发团队需要一个集中的服务器,所有的成员可以将服务器作为仓库来访问他们的代码。在 一个办公室中,没有问题 --只是将仓库连到本地网络上的一台服务器上就行了。对于开放源码项目...噢, 还是没有问题,这要感谢因特网。CVS内建了客户机/服务器存取方法,所以任何一个可以连到因特网上的开发 者都可以存取在一台CVS服务器上的文件。

调整代码

在传统的版本控制系统中,一个开发者检出一个文件,修改它,然后将 其登记回去。检出文件的开发者拥有对这个文件修改的排它权。没有其它的开发者可以检出这个文件 -- 并且只 有检出那个文件的开发者可以登记(check in:注2)所做的修改。(当然对于管理员有很多方法可以超越这个 限制。)

想一下排它的检出可能会如何工作:Bob的兄弟检出 foo.java以便加入 注释,写好代码后他什么也没做。然后他去吃午饭了。Bob吃完午饭后,发现他的老板所指给他的一个bug在 foo.java里。他试图检出 foo.java ... 但是版本控制系统不允许他这样做,因为他的兄弟已经把它检出了。Bob不 得不等着他的兄弟吃完午饭回来(在这个 "好"日子用了两个小时),他才可以修正bug。

在一个大型的开放源码工程中,因为开发者可能在任意的时区工作得很 晚,给予一个开发者阻止任意地方的其它开发者继续处理任意文件的能力很明显示无法运转。他们最终将因为不 能够在他们想要的时候开展项目而感到厌烦。

CVS通过它的无限制的检出模式解决了这个问题。检出一个文件并不给定 开发者对那个文件的排它权。其它的开发者也可以对其检出,进行他们自己的修改,并且将其登记回去。

"等一下!"你可能会说。"但是后面的登记不是会覆盖前面的吗?"回答 是不会。详细地回答就是当多个开发者对同一个文件作了修改CVS会检测,并且自动合并那些改变。

哇噢。自动的?不用担心 -- CVS 会很小心,并且将会自动合并那些只 要不是对代码的同一行所作的改动。如果CVS不能安全的处理这些改动,开发者将不得不手工合并它们。 从此去往何处?

到现在为止,你已经毫不犹豫地着迷于CVS 的潜力,并且急不可待地想 开始。第一步就是去得到 适合你的平台的CVS软件。安装CVS通常就是将其从你下载的压缩包中解开这么一件 事。配置CVS 可能要小心一些,它非常依赖于你使用的平台和你的CVS代码仓库的存放地。CVShome.org存放了大 量的CVS 文档:
《Introduction to CVS》 Jim Blandy所写的一篇很棒地在线介绍。我也推荐《 Open Source Development with CVS》 Karl Fogel写的。你可以读一下我写的关 于它的评论在OpenAvenue VOX上。Karl已 经将书中关于CVS的部分置于GPL许可证之下;这篇文档在Karl的站点上以多种文档格式提供。

《The Cederqvist》 -- 由Per Cederqvist所编写的CVS手册 -- 是一个关于CVS信息的全面资料。

有大量的可用在许多平台上CVS 附加工具,它们给 CVS增加了功能或使得CVS更容易使用。

posted @ 2007-11-27 20:33 jadmin 阅读(54) | 评论 (0)编辑 收藏
SWT

       SWT-"Standard Widget Toolkit",它是一个Java平台下开放源码的Native GUI组件库,也是Eclipse平台的UI组件之一。从功能上来说,SWT与AWT/SWING是基本等价的。SWT以方便有效的方式提供了便携式的(即Write Once,Run Away)带有本地操作系统观感的UI组件。
       由于widget系统的固有复杂性以及平台之间微妙的差异,即使在理想情况下,能够达到工业标准的跨平台的widget类库也是很难编写和维护的。最早的AWT组件现在被认为是样貌丑陋的,而且存在很多问题;SWING组件虽然也是缺点多多,但是随着JDK版本的不断升高,它仍在不断进行着改进。我认为,SWT在功能上与AWT/SWING不相伯仲,但是组件更为丰富,平台表现稳定,BUG也相对较少。如果你的应用程序真的需要在多个平台上运行,需要更为美观的界面,又不那么依赖于其他基于AWT/SWING的图形库,那么SWT或许是一个比AWT/SWING更好的选择。

=========================================

为什么要使用SWT?

  SWT是一个IBM开发的跨平台GUI开发工具包。至于IBM费劲自己另起炉灶开发一个GUI工具包,而不是使用Sun有的由AWT, Swing, Java 2D, Java 3D等构成的Java GUI框架,那就话长了。(得在一个BBS读过一个SWT起源的的帖子)。

  在SWT之前,Sun提供了一个跨平台GUI开发工具包AWT (Abstract Windowing Toolkit)AWT框架也使用的是原生窗口部件(native widgets),但是它一直未能突破LCD问题LCD问题导致了一些主要平台特征的失。如果你不明白的(其我也没明白),话说,如果平台A有窗口部件(widgets1–40,而平台B有窗口部件(widgets20–25,那跨平台的AWT框架只能提供两个窗口部件集的交集。

  解决问题Sun建了一个新的框架。个框架不再使用原生窗口部件,而是使用仿真窗口部件(emulated widgets)。个方法然解决了LCD问题,并且提供了丰富的窗口部件集,但是它也来了新的问题。例如,Swing用程序的界面外不再和原生用程序的外相似。 然在JVMSwing用程序已得到了最大程度的性能改善,但是它们还是存在着其原生对应物所不具有的性能问题。并且,Swing用程序消耗太多的内存,这样Swing不适于一些小设备,如PDA和移动电话等。

  IBM行了尝试底解决AWTSwing框架来的上述问题。最IBM建了一个新的GUI就是SWTSWT框架通JNI访问原生窗口部件。如果在宿主(host)平台上无法找到一个窗口部件,SWT就会自地模它。

=====================================

Tags:java,rcp,jface,swt,ibm,eclipse,ui,gui

posted @ 2007-11-27 15:04 jadmin 阅读(82) | 评论 (0)编辑 收藏

在JDK环境配置好的情况下,进行如下操作:

1.先下载最新版Derby数据库
下载地址:http://db.apache.org/derby/
本人下载的是:db-derby-10.3.1.4-bin.zip

2.将db-derby-10.3.1.4-bin.zip解压到一目录下,我这里是才C:\Derby\db-derby-10.3.1.4-bin

3.查看“系统属性”——“高级”——“环境变量”,在“系统变量”下面新建变量“DERBY_INSTALL”,值为第2步的路径值C:\Derby\db-derby-10.3.1.4-bin

4.在CLASSPATH里增加“%DERBY_INSTALL%\lib\derby.jar;%DERBY_INSTALL%\lib\derbytools.jar;”内容

5.进入Derby安装目录“%DERBY_INSTALL%\frameworks\embedded\bin”,双击运行文件setEmbeddedCP.bat

6.测试Derby数据库环境是否配置成功,打开命令提示符窗口,输入信息“java org.apache.derby.tools.sysinfo”,如出现诸如下面的信息:

C:\Documents and Settings\Administrator>java org.apache.derby.tools.sysinfo
------------------ Java 信息 ------------------
Java 版本:        1.5.0_12
Java 供应商:      Sun Microsystems Inc.
Java 主目录:      C:\Program Files\Java\jdk1.5.0_12\jre
Java 类路径:      .;C:\Program Files\Java\jdk1.5.0_12\lib;C:\Program Files\Java
\jdk1.5.0_12\lib\dt.jar;C:\Program Files\Java\jdk1.5.0_12\lib\tools.jar;C:\Derby
\db-derby-10.3.1.4-bin\lib\derby.jar;C:\Derby\db-derby-10.3.1.4-bin\lib\derbytoo
ls.jar;C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\lib\msbase.jar
;C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\lib\mssqlserver.jar;
C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\lib\msutil.jar;C:\Pro
gram Files\MySQL\mysql-connector-java-5.0.7-bin.jar;C:\Program Files\Apache Soft
ware Foundation\Tomcat 5.5\common\lib\servlet-api.jar;C:\Program Files\Libs\dom4
j-1.6.1.jar
OS 名:            Windows XP
OS 体系结构:      x86
OS 版本:          5.1
Java 用户名:      Administrator
Java 用户主目录:C:\Documents and Settings\Administrator
Java 用户目录:    C:\Documents and Settings\Administrator
java.specification.name: Java Platform API Specification
java.specification.version: 1.5
--------- Derby 信息 --------
JRE - JDBC: J2SE 5.0 - JDBC 3.0
[C:\Derby\db-derby-10.3.1.4-bin\lib\derby.jar] 10.3.1.4 - (561794)
[C:\Derby\db-derby-10.3.1.4-bin\lib\derbytools.jar] 10.3.1.4 - (561794)
------------------------------------------------------
----------------- 语言环境信息 -----------------
当前语言环境: [中文/中国 [zh_CN]]
找到支持的语言环境:[cs]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[de_DE]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[es]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[fr]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[hu]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[it]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[ja_JP]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[ko_KR]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[pl]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[pt_BR]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[ru]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[zh_CN]
         版本:10.3.1.4 - (561794)
找到支持的语言环境:[zh_TW]
         版本:10.3.1.4 - (561794)
------------------------------------------------------
Derby数据库环境已经基本配置好了

本文作者:曦勤

http://hi.baidu.com/jadmin

posted @ 2007-11-27 10:24 jadmin 阅读(125) | 评论 (0)编辑 收藏

要用开源数据库Derby了,下面先转篇入门级的文章,学习学习!

数据库做为数据持久化存储的重要手段怎么强度都不过分,但传统的数据库都比较庞大,需要安装配置等,对于一些比较轻量级的应用来说有点象杀鸡用牛刀一样.

Derby做为一个开源的、纯Java数据库引起了越来越多的关注,它源自IBM的CloudScape,现在成了大名鼎鼎的Apache基金会的开源项目。Apache一项是开源项目的领导者,从他们手里出去的东西都很不错,在此感谢一下这些无私奉献的人们。

Derby做为嵌入式数据库的一个方便之处就是对数据库的一切操控都可以在Java程序代码中实现,并且它非常的小,几个jar文件总共才2M多,非常轻巧,非常便于我们程序的移植。下面说一步步的来说明一下怎样使用。

首先,从http://db.apache.org/derby/下载Derby的最新版本,直接解压到本地,然后设置程序运行的环境变量。

在win2000/xp中“我的电脑”--》右键--》属性--》环境变量--》变量--》添加

1.设置JAVA_HOME

2.设置DERBY_INSTALL(一定要是这个名字,否则可能无法正常运行),值为解压的目录

环境变量设置好了之后,我们就可以着手写第一个测试程序了。

和使用其它的数据库一样,首先加载数据库驱动:

Class.forName("org.apachy.derby.jdbc.EmbeddedDriver");

然后我们创建一个数据库:

Connection conn=DriverManager.getConnection("jdbc.derby.derbyDB;create=true","user","pwd");

在上面的Url中指定create=true,则创建一个新的数据库。

得到连接之后,我们就可以象访问其它数据库一样,进行相关操作了。

Statement st=conn.createStatement();

st.execute("create table test1(id int,name varchar(20));

st.execute("insert into test1 values(1,'sinboy')");

st.execute("inert into test1 values(2,'Tom')");

ResultSet rs=st.executeQuery("select * from test1");

while(rs.next){

   System.out.println("id:"+rs.getInt(1)+" name:"+rs.getString(2));

}

rs.close();

st.close();

conn.commit();

conn.close();

Derby的最大好处应该还是小巧、纯Java、好移植,比较适全小量的数据存储。

posted @ 2007-11-25 20:21 jadmin 阅读(434) | 评论 (0)编辑 收藏

做项目时,经常遇到要把数据库的内容放到javascript里。不管是单个字符串(String),还是集合(array)。javascript不能直接从数据库拿东西。所以只得借助一些其他条件。比如在页面上的标签里放id,name 之类的标志。

假如:

1,获取字符串:

user.getName() 是一条单个的记录。

<div id=a><%=user.getName() %></div>

那么javascript很容易获取 : var jsa=     document.getElementById("a").innerText; (注:innerHTML也可以获取。)

2,获取集合,数组:

<form name="form1">
       <table>
                  <%
     Mgr mgr=new Mgr();
     ArrayList list=mgr.getonebbs();
     for(int i=0;i<list.size();i++)
     {
       Ext role=(Ext)list.get(i);
      %>
               <tr>
               <td id="cid<%=i %>"><%=role.getId()%></td>
               <td id="cname<%=i %>"><%=role.getName()%></td>
               <td id="cpass<%=i %>"><%=role.getPass()%></td>
               <td id="ctel<%=i %>"><%=role.getTel()%></td>
               </tr>
            <%
      }%>
     <input type="hidden" value="<%=list.size() %>" name="hid" >
      </table>
</form>

javascript获取:
         var cc = document.getElementById("hid").value; //首先获取长度,下面循环输出
          var a=new Array();
            var b=new Array();
              var c=new Array();
                var d=new Array();
          var myData=new Array();
        for(var j=0;j<cc;j++)
        {
          a[j]= document.getElementById("cid"+j).innerText;
          b[j]= document.getElementById("cname"+j).innerText;
          c[j]= document.getElementById("cpass"+j).innerText;
          d[j]= document.getElementById("ctel"+j).innerText;
                   //      alert(a+" "+b+" "+c+" "+d+" ");     //测试
                   myData[j] =     [a[j],b[j],c[j],d[j]] ;   
        }

这样就把数组放到myData中去了。

3,总结:
先把输出放到jsp页面上,               //也就是把数据查询出来
然后在js里面获取jsp上的数据,     //通过document.获取。 单个,循环。
然后放到string 或者 array里面。//OK

反正感觉多做了2步似的,绕了个圈,不过没办法,人家都是这样做的。。。

js数组的写法:
ArrI=new Array();
ArrI[0] = new Array("username1","0","609");
ArrI[1] = new Array("username2","609","610");
ArrI[2] = new Array("username3","609","611");

ArrII=new Array(
new Array("username1","0","609"),
new Array("username2","609","610"),
new Array("username3","609","611")
);

ArrIII=[];
ArrIII[0] = new Array("username1","0","609");
ArrIII[1] = new Array("username2","609","610");
ArrIII[2] = new Array("username3","609","611");

ArrIIII=[
["username1","0","609"],
["username2","609","610"],
["username3","609","611"]
];
一般最后一种..
posted @ 2007-11-10 20:02 jadmin 阅读(94) | 评论 (0)编辑 收藏

How to clone:

1. Implement the Cloneable interface, and

2. Redefine the clone method with the public access modifier.


Cloneable:

The Cloneable interface is one of a handful of tagging interfaces that Java provides.A tagging interface has no methods; its only purpose is to allow the use of instanceof in a type inquiry:
if (obj instanceof Cloneable) . . .
We recommend that you do not use this technique in your own programs.


Shallow copy:

Even if the default (shallow copy) implementation of clone is adequate, you still need to implement the Cloneable interface, redefine clone to be public, and call super.clone(). Here is an example:

class Employee implements Cloneable
{
   // raise visibility level to public, change return type
   public Employee clone() throws CloneNotSupportedException
   {
      return super.clone();
   }
   . . .
}


Deep copy:

class Employee implements Cloneable
{
   . . .
   public Object clone() throws CloneNotSupportedException
   {
      // call Object.clone()
      Employee cloned = (Employee) super.clone();

      // clone mutable fields
      cloned.hireDay = (Date) hireDay.clone()

      return cloned;
   }
}

1 The clone method of the Object class threatens to throw a CloneNotSupportedException—it does that whenever clone is invoked on an object whose class does not implement the Cloneable interface. Of course, the Employee and Date class implements the Cloneable interface, so the exception won't be thrown.

2
public Employee clone()
{
   try
   {
      return super.clone();
   }
   catch (CloneNotSupportedException e) { return null; }
   // this won't happen, since we are Cloneable
}

This is appropriate for final classes. Otherwise, it is a good idea to leave the tHRows specifier in place. That gives subclasses the option of throwing a CloneNotSupportedException if they can't support cloning.


Use clone:

public static void main(String[] args) {
     try {
        Employee original = new Employee("John Q. Public", 50000);
        original.setHireDay(2000, 1, 1);
        Employee copy = original.clone();
        copy.raiseSalary(10);
        copy.setHireDay(2002, 12, 31);
        System.out.println("original=" + original);
        System.out.println("copy=" + copy);
    }
    catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
}

posted @ 2007-11-10 10:39 jadmin 阅读(73) | 评论 (0)编辑 收藏

1。list方法。   将 Enumeration 类型转换成list类型

2。swap方法。方便的调换一个list中的两个元素的位置。

3。lastIndexOfSubList方法。从一个list中从后面开始查找另外一个list第一次出现的位置。

4。rotate方法。在一个list中,顺序移动每一个元素的位置到指定的位置。

5。replaceAll方法。用指定的元素替换一个list中所用匹配的元素。

6。indexOfSubList方法。从一个list中从前面开始查找另外一个list第一次出现的位置。

示例程序:

import java.util.*;

class TestCollections {

public static void main(String[] args) {
TestCollections t = new TestCollections();
t.testList();
}
public void testList() {
Vector v = new Vector();
v.add("a");
v.add("b");
Enumeration e = v.elements() ;
List l = Collections.list(e);
System.out.println(l);
}

public void testSwap() {
List l = new ArrayList();
l.add("t");
l.add("a");
l.add("n");
l.add("k");
l.add("s");
System.out.println(l);
Collections.swap(l,1,3);
System.out.println(l);
}

public void testLastIndexOfSubList() {
List l = new ArrayList();
l.add("a");
l.add("b");
l.add("c");
l.add("d");
l.add("e");
l.add("a");
l.add("b");
l.add("c");
l.add("d");
l.add("e");
List l2 = new ArrayList();
l2.add("b");
l2.add("c");
l2.add("d");
int result = Collections.lastIndexOfSubList(l,l2);
if(result != -1) {
   System.out.println("!!! " + result + ". Found from " + l + " with " + l2);
} else {
   System.out.println("!!! Not found from " + l + " with " + l2);
}
List l3 = new ArrayList();
l3.add("b");
l3.add("d");
l3.add("d");
result = Collections.lastIndexOfSubList(l,l3);
if(result != -1) {
   System.out.println("!!! " + result + ". Found from " + l + " with " + l3);
} else {
   System.out.println("!!! Not found from " + l + " with " + l3);
}
}
public void testRotate() {
List l = new ArrayList();
l.add("t");
l.add("a");
l.add("n");
l.add("k");
l.add("s");
System.out.println(l);
Collections.rotate(l,1);
System.out.println(l);

//
   l = new ArrayList();
l.add("t");
l.add("a");
l.add("n");
l.add("k");
l.add("s");
System.out.println(l);
Collections.rotate(l,-4);
System.out.println(l);

   l = new ArrayList();
l.add("a");
l.add("b");
l.add("c");
l.add("d");
l.add("e");
System.out.println(l);
Collections.rotate(l.subList(1, 4), -1);
System.out.println(l);


}

public void testReplaceAll() {
List l = new ArrayList();
l.add("t");
l.add("a");
l.add("n");
l.add("a");
l.add("s");
System.out.println(l);
boolean b = Collections.replaceAll(l,"a","hello");
System.out.println(l);
System.out.println(b);

// not found
b = Collections.replaceAll(l,"a","hello");
System.out.println(b);

}

public void testIndexOfSubList() {
List l = new ArrayList();
l.add("a");
l.add("b");
l.add("c");
l.add("d");
l.add("e");
List l2 = new ArrayList();
l2.add("b");
l2.add("c");
l2.add("d");
int result = Collections.indexOfSubList(l,l2);
if(result != -1) {
   System.out.println("!!! " + result + ". Found from " + l + " with " + l2);
} else {
   System.out.println("!!! Not found from " + l + " with " + l2);
}
List l3 = new ArrayList();
l3.add("b");
l3.add("d");
l3.add("d");
result = Collections.indexOfSubList(l,l3);
if(result != -1) {
   System.out.println("!!! " + result + ". Found from " + l + " with " + l3);
} else {
   System.out.println("!!! Not found from " + l + " with " + l3);
}
}
}

posted @ 2007-11-08 07:37 jadmin 阅读(73) | 评论 (0)编辑 收藏
1.在一些字符串数组中,常会有重复的记录,比如手机号码,我们可以通过Hashtable来对其进行过滤
public String[] checkArray(String[] str)...{
        Hashtable<String, String> hash=new Hashtable<String, String>();

        for(int i=0;i<str.length;i++)...{
            if(!hash.containsKey(str[i]))
                hash.put(str[i], str[i]);
        }

        Enumeration enumeration=hash.keys();
        String[] str_new=new String[hash.size()];
        int i=0;

        while(enumeration.hasMoreElements())...{
            str_new[i]=enumeration.nextElement().toString();
            i++;
        }
        return str_new;
    }

示例:
        String[] mobile={"13811071500","13811071500","13811071501","13811071503","13811071501"};
        mobile=checkArray(mobile);
        for(int i=0;i<mobile.length;i++)
            System.out.println(mobile[i]);
       输出结果为:
        13811071503
        13811071501
        13811071500
2.A,B均为字符串数组,找出在A中存在,而在B中不存在的字符串
    public String[] compareArray(String[] A,String[] B){
        Hashtable<String, String> hash=new Hashtable<String, String>();
        Hashtable<String, String> hash_new=new Hashtable<String, String>();

        for(int i=0;i<B.length;i++)
            hash.put(B[i], B[i]);

        for(int i=0;i<A.length;i++){
            if(!hash.containsKey(A[i]))
                hash_new.put(A[i], A[i]);
        }

        String[] C=new String[hash_new.size()];
        int i=0;
        Enumeration enumeration=hash_new.keys();

        while(enumeration.hasMoreElements()){
            C[i]=enumeration.nextElement().toString();
            i++;
        }
        return C;
    }
示例:
        String[] mobile1={"13811071500","13811071501","13811071502","13811071503","13811071504"};
        String[] mobile2={"13811071500","13811071505","13811071502","13811071506","13811071504"};
        String[] mobile3=compareArray(mobile1,mobile2);
        for(int i=0;i<mobile3.length;i++)
            System.out.println(mobile[i]);
输出结果:
    13811071503
    13811071501
存在的问题:
每次都是倒序,可以再对程序稍加改动,变成正序。

3.将一个字符串数组中某一个特定的字符串过滤掉
/** *//**检验一个字符串数组,若包含某一特定的字符串,则将该字符串从数组中删
除,返回剩余的字符串数组
     * @param str_array 字符串数组
     * @param str_remove 待删除的字符串
     * @return 过滤后的字符串
     */
    public String[] removeStrFromArray(String[] str_array,String
str_remove)...{
        Hashtable<String, String> hash=new Hashtable<String, String>();
        for(int i=0;i<str_array.length;i++)...{
            if(!str_array[i].equals(str_remove))
                hash.put(str_array[i], str_array[i]);
        }
        //生成一个新的数组
        String[] str_new=new String[hash.size()];
        int i=0;
        Enumeration enumeration=hash.keys();
        while(enumeration.hasMoreElements())...{
            str_new[i]=enumeration.nextElement().toString();
            i++;
        }
        return str_new;
    }
posted @ 2007-11-06 21:07 jadmin 阅读(93) | 评论 (0)编辑 收藏

如果你的很多时间是用来敲纯文本,写程序或HTML,那么有效地使用一个好的编辑器能节省你不少时间。这篇文章里的指导和提示将有助于你更快工作,更少犯错误。

文中采用开源文本编辑器Vim(Vi IMproved)说明有效编辑的思想,但这些思想也适用于其他编辑器。择合适的编辑器只是有效编辑的第一步,对于哪个编辑器更好的讨论将占很大地方,这里就不提了。如果你不知道该用哪个编辑器,或者对现在所使用的不太满意,不妨试试Vim;你是不会失望的。

第一部分:编辑一个文件

快速定位

编辑中大部分时间是花费在阅读、查错和寻找应该进行编辑的地方上,而不是插入新文字或进行修改。在文件中不断定位(navigate)是经常要做的,所以最好学会如何快速地进行。

你常会搜寻文档中的一些文字。或者找出包含特定词或词组的行。你当然可以使用搜寻命令 /pattern,不过还有更聪明的方法:

* 如果你看到一个特定词,想看看其他地方是不是出现过同样的词,可以使用* 命令。它将对光标所指的词进行搜寻。
* 如果设置了 ' incsearch' 选项,Vim将在你正在输入搜寻模式的时候就显示搜寻的结果(而不是等到你敲了回车之后)。这能够使你更快地找出拼写错误。
* 如果设置了 ' hlsearch' 选项,Vim将使用黄色背景对搜寻结果进行高亮显示。你可以对搜寻的结果一目了然。应用在程序代码中可以显示变量的所有引用。你甚至不需要移动鼠标就能看到所有的搜寻结果。

对于结构化的文档,快速定位的办法就更多了。Vim提供专门针对C程序(以及C++、Java等等)的特殊命令:

* 使用 %可以从开始括号跳到对应的关闭括号。或者从 ``#if'' 跳到对应的 ``#endif''。事实上, % 可以完成许多对应项之间的跳转。可以用来检查if()和{}结构是否平衡。
* 使用 [{可以在代码段(block)中跳回到段起始的 ``{``。
* 使用 gb 可以从引用某个变量的地方跳转到它的局部声明。

定位的方法当然不止这些。关键是你需要知道有这些命令。你也许会说不可能学会所有命令 — Vim里有成百个定位命令,有的很简单,有的很聪明 — 这需要几星期的学习。不过,你不必如此;你只需要了解自己的编辑特点,然后掌握相关的定位命令就可以了。

可以采取三个基本步骤:

1. 在你进行编辑的时候,注意那些重复进行的操作。
2. 找出能快速进行这些操作的编辑命令。阅读文档,问问朋友,或者看看其他人是如何做的。
3. 进行练习,知道熟练为止。

让我们通过以下这个例子说明一下:

1. 你发现在写C程序时,经常要查找函数定义。你目前使用 * 命令对函数名进行搜寻,但得到的往往是函数的引用而不是函数定义。你觉得一定会有更好的办法。
2. 读过一篇快速参考以后,你发现关于定位标记的说明,里面说明了如何定位函数定义,这正是你要找的!
3. 你试着生成了一个标记文件,使用Vim自带的ctags程序。你学会了使用CTRL-] 命令,发现这省了不少事。为了更方便,你在 Makefile 里加入了几行以自动生成标记文件。

当你使用以上三个步骤时,有几点需要注意的地方:

* ``我只想完成任务,不想去读那些文档来找新的命令。''。如果你真的是这么想的,那么你将永远停留在计算的石器时代。有些人编写什么都用Notepad,却总不明白为什么其他人总能用他一半的时间成任务。
* 不要过分。如果你总为一点小事也要去找完美的命令,你就没法集中精力到你本要完成的任务上了。只要找出那些耗费过多时间的操作,然后使用相关的命令直到熟练就可以了。这以后你就能集中精力到自己的文档上了。

下面这些章节给出了大多数人遇到的操作。你仿照它们在实际工作中使用

三个基本步骤

不要敲两次

我们所使用的字词集合是有限的。既使是词组和句子也不过是有限的几个。对于程序来说更是如此。很明显,你不想把同样的东西敲上两遍。

你经常会想把一个词替换成另一个。如果是全文件替换,你可以使用:s (substitute)命令。如果只是几个位置需要被替换,一个快速办法是使用 * 命令找出下一个词,使用 cw 来进行替换。然后敲n 找到下个词,再用 . 重复 cw 命令。

. 命令重复上一个改变。这里的改变是插入、删除或替换操作。能够重复进行操作是个极为强大的机制。如果好好使用它,那么你大部分的编辑工作可能只不过是敲几下 . 的事。小心不要在两次重复之间做其他修改,因为这将改变你要重复的操作。如果确实需要如此,可以使用 m 命令记住要修改的位置,等重复操作进行完毕之后再回过头来修改它。

有些函数名和变量名可能很难敲。你能准确无误地输入``XpmCreatePixmapFromData''么?Vim的自动补齐机制能给你省不少事。它查看你正在编辑的文件以及#include文件,你可以只敲入``XpmCr'',然后使用CTRL-N 命令让Vim把它补齐为``XpmCreatePixmapFromData''。这不但节省了输入时间,而且减少了输入的错误。

如果你有同样的词组或句子需要输入多次,还有个更简单的办法。Vim可以进行录制宏。使用 qa 命令开始在'a'寄存器里录制宏。然后正常地输入编辑命令,最后用 q 退出录制状态。如果你想重复所录制的命令,只需执行 @a 命令。Vim总共提供26个这样的宏寄存器。

使用宏录制功能可以记录各种操作,不只限于插入操作。如果你想重复一些东西,不妨一试。

需要注意的是记录的命令会被原封不动地重复执行。在进行定位时简单的重复宏操作可能不是你想要的结果。比如对于一个词这里可能需要左移4个字符,在下个地方可能就要左移5个字符。所以必须定位到合适的位置再重复进行宏操作。

如果你要重复的命令很复杂,把它们一次敲进去会很困难。这时你可以写一个脚本或宏。这常被用于建立代码模板;比如,一个函数头。你想做得多聪明就可以做得多聪明。

知错就改

编辑时经常会出错。无人能免。关键是快速发现并进行改正。编辑器应该提供这方面的支持,不过你必须告诉它什么是对什么是错。

你可能常常会重复同样的错误,你的手指所做的并非是你要它做的。可以使用缩写(abbreviation)进行修正。下面是一些例子:


* :abbr Lunix Linux
* :abbr accross across
* :abbr hte the


这些词会在编辑时被自动改正。

同样的机制也可以用于对很长的词语进行缩写。特别适用于输入那些你觉得很难敲的词,它可以避免出错。比如:

* :abbr pn pinguin
* :abbr MS Mandrake Software

但有时候你想要的正是那些缩写,比如想插入``MS''。所以缩写中最好使用那些不会出现在文中的词。

Vim提供了一个很聪明的高亮机制,一般用于程序的语法高亮,不过也可以用来查错。

语法高亮会使用颜色显示注释。这听上去不是什么特别重要的功能,不过一旦用起来就会发现这其实很有用。你能够快速地发现那些没有高亮却本应作为注释的文字(可能是因为忘了敲注释符)。也可以发现一些被错误当成注释的代码(可能是因为忘了敲``*/'')。这些错误在黑白方式下是很难被发现的,浪费了不少调试时间。

语法高亮也可以用来查找不匹配的括号。一个未被匹配的``)''会被亮红色背景加以标识。你可以使用 % 命令他们是被如何匹配的,然后把``(''或``)''插入到合适的位置。

另一类常犯的错误也很容易发现,比如把 ``#include <stdio.h>''敲成了``#included <stdio.h>''。在黑白方式下这是很难发现的,但在语法高亮下则能很快发现``include''能被高亮而``included''没有。

再看一个更复杂的例子:对于英文文本你可以定义一个所要使用的词的长列表。所有未在表中出现的词都可能是错误,并进行高亮显示。可以定义几个用于编辑词表的宏。这正是字处理器的拼写检查功能。Vim中是靠一些脚本来实现的,你也可以对它进行定制:比如,只对注释中的文字进行拼写检查。

第二部分:编辑多个文件

文件总是成帮结伙

人们很少只编辑一个文件。一般需要顺序或同时编辑一些相关的文件。你应该利用编辑器使多文件编辑工作更为高效地。

上面提到的标识(tag)机制也支持跨文件搜寻。一般做法是为项目的所有文件生成标识文件,然后在项目的所有文件中搜寻函数、结构、类型(typedef)等的定义。这比手工搜寻要快捷的多;我浏览一个程序要做的第一件事便是建立标识文件。

另一个强大的功能是使用 :grep 命令对一组文件进行模式搜寻。Vim把搜寻结果做成一个列表,然后跳到第一个结果。使用 :cn 命令跳到下一个结果。如果你想改变一个函数调用的、参数个数,那么这个功能会很有用。

头文件里有很多有用的信息。然而要知道一个声明出现在哪个头文件中却需要花不少时间。Vim能够理解头文件,能够从中找到你需要的东西。把光标移动到函数名下,然后敲 [I:Vim就会显示出一个头文件中该函数名的所有匹配。
如果你想得到更详细的结果,可以直接跳到声明中。一个类似的命令可以用于检查你所使用的头文件是否正确。

你可以把Vim的编辑区域进行分隔,用来编辑不同的文件。你可以对两个或多个文件进行比较,或者进行拷贝/粘贴。有许多命令用于打开关闭窗口,文件间跳转,暂时隐藏文件等等。可以再使用上面提到的三个基本步骤选择合适的命令进行学习。

多窗口还有更多的用法。预览标识(preview-tag)就是个很好的例子。它打开一个特殊的预览窗口,光标还保留在你正在编辑的文件中。预览窗口中可以是光标所指函数的声明。如果你移动光标到另一个名字下,停留一两秒,预览窗口中就会显示那个名字的定义。名字还可以是头文件中声明的结构或函数。

让我们一起来工作

编辑器可以编辑文件。e-mail程序可以收发消息。操作系统可以运行程序。每个程序都有它自己的任务,而且应该做好。如果能让程序一同工作,那么就会实现很强大的功能。

举个简单的例子:选择一个列表中的结构化的文字,并对它进行排序:!sort。这将使用外部命令``sort''来过滤文件。容易吧?排序功能是可以添加到编译器中的。不过看一下``man sort''就知道它有很多选项。它可能用了一个极为精巧的排序算法。你还打算把它加到编辑器中么?更何况还有其他不少过滤程序。编辑器可能会变得很大。

Unix精神的一个体现就是提供独立的程序,各自做好自己的任务,然后组合起来完成更大的任务。不幸的是,许多编辑器不能很好地和其他程序一起工作,比如,你不能包Netscape的邮件编辑器换成其他编辑器。这样你只能使用那个不顺手的程序。另一个趋势是在编辑器里提供所有的功能,Emacs就是个代表(有人说Emacs其实是个操作系统,只是可以用来编辑文件)。

Vim尽力和其他程序集成,但这需要经过斗争。目前Vim已经可以作为MS-Developer Studio和Sniff的编辑器。一些e-mail程序(比如Mutt)也支持外部编辑器。和Sun Workshop的集成工作正在进行中。总的来说这个领域还有待提高。将来我们会有一个大于其各部分总和的系统。

文本结构化

你可能经常会遇到有一些结构的文本,这些结构可能同于那些现有命令所支持的结构。这样你不得不利用那些底层的``砖头''创建你自己的宏和脚本。这里说明的就是这类更复杂的东西。

有个简单的办法可以加速编辑-编译-修改这个循环。Vim提供 :make 命令,用于进行编译,并且获取错误输出,把你带到发生错误的地方进行修正。如果你使用了另一个编译器,那么错误就无法被Vim获得。如果不想自己动手,可以修改' errorformat'选项。告诉Vim错误是什么样子,以及如何从中获得文件名和行号。它支持复杂的gcc错误信息,所以应该也能支持其他编译器。

有时处理一个新的文件类型只需要设置几个选项或写一些宏。比如,为了在man手册中进行跳转,你可以写一个宏获取光标下的词,清除缓冲区,然后读入新的man手册。这是简单而高效的参照(cross-reference)方法。

使用三个基本步骤,你可以更有效地处理各种结构化文件。只需要想想你想对文件采取的操作,然后找到相应的命令去用就是了。就这么简单,你只要去做就成了。

第三部分:磨刀

养成习惯

要学会开车必须下功夫。这是不是你只骑自行车的原因么?当然不是,你会发现你必须花时间来获得所需的技术。文本编辑也不例外。你需要学习新的命令,并使用它直至成为习惯。

另一方面,你不应该试图学习编辑器提供的每个命令。这是彻底的浪费时间。大多数人只需要学习10%到20%的命令就足够工作了。但是每个人所需要的命令都各不相同。你需要不断学习,找出那些可以自动完成的重复操作。如果你只做一次操作,而且以后也不会再去做,那么就不需要进行优化。是如果你发现你在过去的一小时中重复了好几遍同样的操作,那么就有必要查看一下手册,看看能否更快速地完成。或者写一个宏来做。如果是是个不小的任务,比如对一类文本进行对齐,你需要阅读一下新闻组或看看Internet上是不是有人已经解决了同样的问题。

最根本的步骤是最后的那一个。你可能能够找到一个重复性的任务,找到一个不错的作法,可过了一个周末就彻底忘了自己是怎么做的了。这不成。你必须重复你的作法直到烂熟于胸。只有这时你才真正获得了你需要的高效。一次不要学得太多。一次只试一些工作得很好的方法。对于那些不常用的技巧,你可能只需要把它记下来,留待以后查阅。总之,如果抱着这样的目标,你的编辑技能就会更加有效。

最后需要指出的是,如果人们忽略了以上几点会发生什么:我仍然可以看到有人盯着屏幕看上半天,用两个指头敲几下,然后继续抬头看着屏幕,还抱怨自己太累.. 把十个指头都用上!这不光更快,还不累。每天抽出一个小时练习一下指法,只要几星期就足够了。

后记

书名得益于Stephen R. Covey所著的那本畅销书《高效人的七种习惯》(``The 7 habits of highly effective people'')。

关于作者

Bram Moolenaar是Vim的主要作者。他编写了Vim核心功能,并采纳了许多开发者提供的代码。他的e-mail地址是:Bram@Moolenaar.net

posted @ 2007-11-06 11:14 jadmin 阅读(54) | 评论 (0)编辑 收藏
仅列出标题
共50页: First 上一页 20 21 22 23 24 25 26 27 28 下一页 Last