Eclipseプラグイン開発でのパス取得とかファイル操作とかのやり方


Eclipseのプラグイン開発における小ネタ。

ファイル操作

プラグイン開発ではjava.io.Fileを使わずに、IFileの実装クラスであるorg.eclipse.core.internal.resources.Fileのインスタンスを作成して操作する。

// ワークスペースのルートを取得して、プロジェクトのファイルのFileインスタンスを作成する。
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IFile scopeFile  = root.getFile(new Path("/RemoteSystemsTempFiles/tempFileName"));

ちなみにgetFileに渡すPathは、プロジェクト名とリソース名を含んでいないと、以下のエラーになる。

java.lang.IllegalArgumentException: Path must include project and resource name: /tempFileName
    at org.eclipse.core.runtime.Assert.isLegal(Assert.java:63)
    at org.eclipse.core.internal.resources.Workspace.newResource(Workspace.java:2137)
    at org.eclipse.core.internal.resources.Container.getFile(Container.java:208)
    <ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("/tempFileName"));の実行箇所>

具体例

例えば、アクティブなエディタのプロジェクトルートを取得し、その配下のファイル情報を作成する場合は、以下のようなコードになる。

// アクティブエディタ(編集中のファイル)の情報を取得する。
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IEditorPart editor = window.getActivePage().getActiveEditor();
ITextEditor textEditor = (ITextEditor)editor;

// エディタ情報をもとに、編集中のファイルが属するプロジェクト情報を取得する。
IFileEditorInput editorInput = (IFileEditorInput)textEditor.getEditorInput();
IFile file = editorInput.getFile();
IProject project = file.getProject();

// プロジェクトのフルパスに、取得したいファイルのプロジェクトルートからの相対パスを追加して、
// ファイル情報を取得する。
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IPath path = project.getFullPath().append("tempFileName");
IFile file  = root.getFile(path);

パスの操作

Pathインスタンスにパスを追加する場合はappendメソッドを使う。
ただし、StringBuilderのappendなどとは違い、appendメソッドが返すのは新規Pathインスタンスなので、呼ぶだけでは情報が捨てられてしまう。

逆に削除する場合はremoveLastSegmentsメソッドを使う。
合わせたサンプルは以下。

// 同一階層の別ファイルにパスを変更
IPath newPath = path.removeLastSegments(1).append("otherFileName");

ファイルの作成、更新、削除

上記手順でFileインスタンスは取得できたので、それに対して作成等の操作を行うサンプルは以下。

try (InputStream in = new ByteArrayInputStream("hoge".getBytes())){

    if (file.exists()) {
        // 上書き
        file.setContents(in, true, true, null);
    } else {
        // 新規作成
        file.create(in, true, null);
    }

    // 削除
    file.delete(false, null);

} catch (CoreException | IOException e) {
    e.printStackTrace();
}

importとライブラリ

import文

今回の実装を記述した場合に書くimport文は以下。

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;

依存解決

plugin.xmlを「プラグインのマニフェスト・エディター」で開き、依存解決タブに以下を追加する。
※最小バージョンを指定する必要はない。

  • org.eclipse.ui
  • org.eclipse.core.runtime
  • org.eclipse.core.resources
  • org.eclipse.jdt.core
  • org.eclipse.ui.ide
  • org.eclipse.ui.editors
  • org.eclipse.jface.text

結局わからなかったこと

以下は結局わからなかった。

workspace直下にフォルダ、ファイルを作成する方法

先に触れている通り、getFileはプロジェクト名とリソース名を指定していなければエラーとなるため、ワークスペース直下にフォルダやファイルを作成する方法がわからなかった。

以下のようにするとワークスペース配下にプロジェクトとしてフォルダを作成することはできるが・・・

// ワークスペースにRemoteSystemsTempFilesを作成する
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject("RemoteSystemsTempFiles");
if (!project.exists()) {
    try {
        project.create(null);
    } catch (CoreException e) {
        e.printStackTrace();
    }
}

どうしたらいいのだろうか。