デシリアライズくらい簡単に出来るかと思ったらはまった
昨日の最小コードがあれば、後は簡単と思ってたらそうでもなかった。
はまったポイント
昨日のコードで下のように書いたけど
@Override protected IDocument createDocument(Object element) throws CoreException { // このメソッドで返したIDocumentの値が表示される IDocument document = super.createDocument(element); if (document != null) { document.set("Hello Editor"); } return document; }
IDocument#get()で取れる文字列を元に出シリアライズすればいいと思って、InputStreamやら、OutputStreamやらいじっててどうしても出来ないと思ったら、IDocument#get()の時点ですでにエンコードされてるから、正しいバイナリの値が取れてなかったみたい。
こんな感じで書いてた(ダメな例)
protected IDocument createDocument(Object element) throws CoreException { // このメソッドで返したIDocumentの値が表示される IDocument document = super.createDocument(element); ByteArrayInputStream bais = new ByteArrayInputStream(document.get().getBytes()); try { ObjectInputStream ois = new ObjectInputStream(bais); // oisからオブジェクト取り出したりしてdocumentに書き込む Object obj = ois.readObject(); // objから文字列を作ってdocumentに書き込む(省略) String text = ""; document.set(text); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return document; }
するとこんな感じの例外が発生する
java.io.StreamCorruptedException: invalid stream header: AC3F0573 at java.io.ObjectInputStream.readStreamHeader(Unknown Source) at java.io.ObjectInputStream.<init>(Unknown Source) at DeserializeEditor$1.createDocument(DeserializeEditor.java:36) ...
今考えればかなり初歩的なミス・・・
正しくは
正しいかは知らないけど、こっちは上手く動いているっぽい
protected IDocument createDocument(Object element) throws CoreException { IPathEditorInput input = (IPathEditorInput)element; File file = input.getPath().toFile(); // 空のドキュメントを作る IDocument document = createEmptyDocument(); ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(file)); // oisからオブジェクト取り出したりしてdocumentに書き込む Object obj = ois.readObject(); // objから文字列を作ってdocumentに書き込む(省略) String text = ""; document.set(text); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if (ois != null) { try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } return document; }
elementはこの場合、FileEditorInputなのでそれを使ってファイルを直接とって、ObjectInputStreamに入れちゃうって戦法ですね。
ちなみにFileEditorInputにキャストするには「org.eclipse.ui.ide」を依存関係に追加しないといけないので、今回はIPathEditorInputにキャストしてみた。
正確には型チェックとかしないとなのかもだけど、とりあえずこれでOK