Intellij IDEA插件开发(二)虚拟文件系统

VFS简介

虚拟文件系统(VFS)是一个Intellij Platform组件,它封装了大部分对活动文件的处理操作,为了达成以下目的:
– 提供一个处理文件的通用API,而不关心文件的具体位置(无论文件位于磁盘上、归档文件中还是HTTP服务器上)
– 追踪文件变化,并且在检测到文件内容发生更改时能提供新旧两个版本的文件
– 建立文件在VFS和持久化存储之间的关联

为了达到后两个目的,VFS为用户磁盘上的内容管理了一个持久化的快照,快照只存储那些通过VFS API访问过的和被异步更新后发生变化了的文件。快照是应用程序级别而不是工程级别的,也就是说,如果一个文件被多个项目引用,它的内容只会在快照中存在一个副本。所有的VFS访问操作都要经过快照。

如果通过VFS API访问文件时该文件不存在于快照中,VFS将从磁盘中加载该文件并存入快照,然后从快照返回数据。快照中只存储那些可被直接访问的信息,例如一个文本文件的内容会被全部存入快照,而另一些不可被直接访问的内容例如jar文件等,VFS只会存储它的元数据,例如文件名、文件尺寸和时间戳等。快照这一特性意味着IDE中显示的文件系统和文件内容可能并不总是能匹配磁盘上的实际内容。在IDE中,有一个观察者进程会从文件系统中接收到文件更改的通知并通知IDE进行刷新操作,刷新操作基于文件的时间戳,如果文件内容被更改而时间戳维持不变的话IDE将不会更新该文件的内容到快照。

获取VirtualFile

从IOFile获取

假设我们已经有一个位于磁盘上的io.java文件,要将其添加到VFS,可通过如下操作进行:
– 创建一个File实例File ioFile = new File("./io.java")
– 将文件从磁盘载入VFSVritualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile)
– 刷新VFSvirtualFile.refresh(false, true)

其中refresh方法的两个参数分别为是否进行异步刷新和是否进行递归刷新。通过以上代码逻辑即可获得IOFile在VFS中的实例。

使用FileChooser获取

SDK中为我们提供了文件选择组件,通过简单的步骤可以直接获得一个VirtualFile实例:
– 创建一个FileChooserDescriptor实例,FileChooserDescriptor封装了一组对需要选择的目标文件的特征描述
– 通过FileChooser.chooseFile()获取VirtualFile实例

从URL获取

VirtualFileManager类提供了findFileByUrl()refreshAndFindFileByUrl()方法让我们可以从URL获取VirtualFile实例

从VFS获取

IDE所有的文件访问都要通过VFS,上述几种方式最终都是将文件添加到VFS的快照之后再提供访问。当文件已经被快照管理时,可以通过FilenameIndex.getFilesByName()获取到VirtualFile实例。

写入内容到VirtualFile

正如Android不允许在UI线程中进行耗时操作一样,Intellij Platform也不允许在主线程中进行实时的文件写入,而需要通过一个异步任务来进行。

ApplicationManager.getApplication().invokeLater(new Runnable() { 
@Override
public void run() { 
new WriteCommandAction(project) {
@Override
protected void run(@NotNull Result result) throws Throwable {
//writing to file
} 
}.execute();
}
});

上面是一个写入文件的示例,需要说明的是,WriteCommandAction也并不是实时写入的,如果有多个WriteCommandAction操作,可能会被合并到某一时间同时执行写操作,所以如果在一组WriteCommandAction中有对不同文件的写操作,而该文件在这组操作中是动态获取的,那么最好在写操作执行前先将WriteCommandAction与文件建立一个映射关系。

VFS就介绍到这里,下一篇文章将介绍如何操作工程中的目录、代码和其他资源文件