本文来自《自己动手写开发工具——基于Eclipse的工具开发》
http://book.youkuaiyun.com/bookfiles/550/10055018421.shtml
说到Eclipse中与资源相关的最重要的概念就是:工作空间、项目、文件夹和文件。工作空间的资源组织成树结构,项目位于顶部,而文件夹和文件在下面。特殊资源、工作空间根目录资源充当资源树的根目录。工作空间可以有任意数目的项目,每个项目都可以存储在磁盘上的不同位置。工作空间负责管理用户资源,组织一个或多个顶级项目。每个项目对应于工作空间目录中的子目录。每个项目都可以包含文件和文件夹。图3.11是项目中不同资源的示意图。
图3.11 项目中的不同资源
相信上图我们大部分都能看懂,需要注意的是Java工程中的包、源文件夹、普通文件夹在Eclipse资源这一个层次看起来都属于文件夹,它们的不同其实是由JDT来标识和区分的。
工作空间下可能有一个 .metadata目录,它是一个特殊的文件夹,其中存储的是工作空间相关的配置文件,我们不能使用一般文件系统 API 来编辑或处理这些文件。与此相似的就是每个项目目录下的 .project。
工作空间、项目、文件夹、文件对应的类型接口分别为IWorkspace、IProject、IFolder、IFile。资源相关的接口都继承了IResource接口,由于工作空间并不只是资源的管理者,因此IWorkspace并没有继承IResource接口,为了将工作空间作为资源的管理者这一功能体现出来,抽象出了IWorkspaceRoot的接口(即工作空间根目录),通过IWorkspace的getRoot就可以得到对应的工作空间根目录。由于工作空间根目录、项目、文件夹都是可以容纳其他资源的,因此为它们抽取了一个基类接口IContainer。图3.12 为Eclipse中资源相关类的继承结构图。
图3.12 资源的继承结构图
3.6.1 资源相关接口的常见方法
为了方便地找到有用的方法,这里我们简单介绍一下资源相关接口的常见方法。
(1) IResource
l delete:删除此资源。
l getFileExtension:返回文件的扩展名。
l getFullPath:返回此资源相对于工作空间根目录的相对路径,返回值类型是IPath。
l getLocation:返回此资源在文件系统中的绝对路径,返回值类型是IPath。
l exists:判断此资源是否存在。处理资源与使用 java.io.File 处理文件非常相似。IResource只是一个句柄。当调用像 getProject、getFolder 这样的方法时,会将句柄返回给资源,即使指定的资源并不存在。因此在必要的时候要使用 exists 方法来确定资源是否存在。
l getParent:得到父资源容器,返回值类型为IContainer。
l getProject:返回此资源所属的项目,返回值类型为IProject。
l getProjectRelativePath:返回此资源在项目中的相对路径,返回值类型是IPath。
l getWorkspace:返回此资源所属的工作空间,返回值类型为IWorkspace。
l isSynchronized:判断资源是否与文件系统同步。
(2) IContainer
l exists(IPath path):判断指定的路径path是否在本容器内存在。
l findMember:返回指定路径的资源,返回值类型为IResource。
l getDefaultCharset:返回此容器内资源的默认编码。
l getFile:返回指定路径的文件,返回值类型为IFile。
l getFolder:返回指定路径的文件夹,返回值类型为IFolder。
l members:返回容器下的所有直接资源,返回值类型为IResource[]。
(3) IFolder
l create:创建此文件夹所代表的资源。
l getFile:返回此文件夹下指定路径下的文件,返回值类型为IFile。
l getFolder:返回此文件夹下指定路径下的文件夹,返回值类型为IFolder。
(4) IFile
l appendContents:向文件中附加数据流,方法中有一个参数是InputStream类型,要添加的数据流就是在此流中。
l create:用数据流创建文件,方法中有一个参数是InputStream类型,要创建的文件的数据流就是在此流中。
l getCharset:返回文件的编码。
l setCharset:设定文件的编码。
l getContents:返回文件的流,返回值类型为InputStream。
l setContents:用数据流设定文件的内容,方法中有一个参数是InputStream类型,要设定的文件的数据流就是在此流中。
(5) IWorkspaceRoot
l getProject:返回指定名字的项目,返回值类型为IProject。
l getProjects:返回工作空间中所有的项目,返回值类型为IProject[]。
3.6.2 方法中force参数的意义
上面列出的许多资源相关接口的方法都包括一个 force 布尔参数,它指定是否将更新与本地文件系统中的相应文件不同步的资源。很多刚刚接触Eclipse的开发人员错误地认为工作空间中的资源是和文件系统中同步的,而事实并非如此。当添加、删除或编辑资源时,资源和文件系统就不再同步;在工作空间外对工作空间中的资源进行添加、删除或编辑后也会造成不同步。API 中的其他方法允许使用程序控制文件系统刷新,例如:
IResource.refreshLocal(int depth, IProgressMonitor monitor);
用户还可以在工作台的资源导航器视图中显式地强制执行刷新。
3.6.3 资源相关接口的方法使用示例
下面来看一看上面介绍的资源相关接口的方法的使用示例。
(1) 取得工作空间
用如下代码取得工作空间:
IWorkspace workspace = ResourcesPlugin.getWorkspace();
其中的ResourcesPlugin定义在org.eclipse.core.resources.ResourcesPlugin中。
(2) 访问工作空间中的资源
要访问工作空间中的资源必须首先获得IWorkspaceRoot,它表示工作空间的根目录,也就是资源层次结构的最顶部:
IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
一旦得到工作空间根目录,就可以访问工作空间中的项目,由于项目必须被打开才能被方法访问,因此我们要首先打开项目:
IProject myProject = myWorkspaceRoot.getProject("MyProject");
if (myProject.exists() && !myProject.isOpen())
myProject.open(null);
一旦有打开的项目,我们就可以访问它的文件夹和文件。在下面的代码中,我们根据位于工作空间外部的文件的内容来创建文件资源:
IFolder imagesFolder = myProject.getFolder("images");
if (imagesFolder.exists()) {
IFile newLogo = imagesFolder.getFile("newLogo.png");
FileInputStream fileStream = new FileInputStream(
"c:/MyOtherData/newLogo.png");
newLogo.create(fileStream, false, null);
}
第一行获得图像文件夹的句柄。必须检查该文件夹是否存在,然后才能对它执行任何操作。同样地,当我们获得文件newLogo时,在我们在最后一行创建文件之前,句柄不代表实际的文件。
3.6.4 在Eclipse中没有当前项目
经常听到有人问这种问题:
“我怎么在当前项目下创建一个文件呢?”
“如何取得当前项目的源文件夹呢?”
这通常是受其他IDE使用的惯性思维影响的开发人员提出来的问题。在VS.NET Studio、JBuilder等IDE中也有与Eclipse中类似的工作空间、项目的概念的,允许在一个IDE中同时打开多个项目,在这多个项目中,有一个主项目,其他项目都是为此项目提供服务的,启动的时候启动的也是这个主项目。Eclipse则不同,在Eclipse工作空间中的各个项目也是有联系的(即依赖项目),但是这些项目之间是平等的关系,每个项目都可以启动。
这样一来,我们也许会发出疑问了:如果没有当前项目的概念,为什么我新建Java文件的时候是建在项目A下而不是项目B下呢?这就是使用了当前选择项目的概念,可以参考前面“枚举代码生成器”中根据selection得到当前包的代码。