MASATOの開発日記


前の開発日記 次の開発日記 一覧

2002/12/04

最近は主にJavaを使って実装を進めているのですが、 C/C++言語に比べ、例外処理ができると、実装がやりやすいことを実感しています。 例外を考えずにだーーっと処理を書き、最初にtryして最後に例外をcatchして例外処理を行なえば 良いわけです。慣れてくると、この方法はとても楽です。

実装を後でみた場合も、例外処理が一箇所に固まっていますので見やすいコードになっています。 最初は、C/C++言語における戻り値でエラー発生を検出するような感じで、 メソッド呼出毎に細かくtry&catchブロックで囲んでいましたが、 最後には、メソッドの最初から最後まで1つのtry&catchブロックで囲むようになりました。

なお、C言語はともかくC++言語にも例外処理はあるのですが、 Win32環境で開発した場合、基本的なAPIであるWin32APIがエラー発生を戻り値で通知しますので、 例外を使う機会はさほど多くありません。
Win32APIがそうなのは仕方が無いとして、クラスライブラリがうまくカバーしてくれれば 例外を使う機会はずっと増えるのですが、 VisualC++に最初から付いてくるMFCやC++標準ライブラリでは、 ほとんどがエラー発生を戻り値で通知します。 これではC++の例外機構は宝の持ち腐れという気がします。
C++にはガベージコレクションが無いので、例外のようなどこでインスタンスが生成されるか分からないものは、 多少扱いが面倒です。

もちろん、色々と自分で実装すればいくらでも解決できるのですが、 MFCのような広く使われているライブラリでしっかりとこういった問題を解決してくれないと、 コードの使いまわしが面倒になります。
うまくいかないもんですなぁ・・・

Fileクラスの親子関係を確認する方法

Javaのクラスライブラリには、java.io.Fileというクラスがあります。 これはパス名を指定するためのクラスです。 なんでパス名を指定するのに文字列ではなくわざわざクラスを用意したのかという話は置いておいて、 Fileクラスのインスタンスa,bがあったとき、aの親がbであることを確認するには どうすれば良いかと言う方法を紹介致します。

a,b双方ともgetCanonicalFile()を取った後、aをgetParentFile()を使ってどんどん遡って行き、 a.equals(b)がtrueになればaの親はbです。もしもgetParentFile()がnullを返したら、 aの親はbではありません。
以上です。簡単ですね。

"."や".."といった冗長名は問題なく削除されるのはもちろん、 Windowsにおけるロングファイルネーム/ショートファイルネームの違いや、大文字小文字の違いも吸収されるようです。

実装は難しくないので省略します。

文字列からXML文書を読込む方法

環境Java2 1.4 Standard Edition

前回の続きとなります。前回は、XML文書のファイルに対するR/Wをやりましたが、 今回は文字列へのR/Wをやります。まずは読込みの方法からです。

ポイントは、CharArrayReaderを使うということです。 それ以外はファイルからの読込みと大差ありません。

import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
// 省略
    try {
      String xmlString = "<root><test>テスト</test></root>";
      CharArrayReader car = new CharArrayReader(xmlString.toCharArray());
      Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      StreamSource source = new StreamSource(car);
      DOMResult result = new DOMResult(doc);
      transformer.transform(source, result);
      car.close();
    } catch (TransformerConfigurationException ex) {
      ex.printStackTrace();
      // 例外処理
    } catch (ParserConfigurationException ex) {
      ex.printStackTrace();
      // 例外処理
    } catch (TransformerException ex) {
      ex.printStackTrace();
      // 例外処理
    }

これでインスタンスdocにXML文書が読込まれました。

文字列にXML文書を書込む方法

環境Java2 1.4 Standard Edition

次は、文字列への書込みの方法です。

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
// 省略
    try {
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      Source source = new DOMSource(doc);
      CharArrayWriter caw = new CharArrayWriter();
      StreamResult result = new StreamResult(caw);
      transformer.transform(source, result);
      String resultString = caw.toString();
      caw.close();
    } catch (TransformerConfigurationException ex) {
      ex.printStackTrace();
      // 例外処理
    } catch (TransformerException ex) {
      ex.printStackTrace();
      // 例外処理
    }

読込みの逆の処理です。なお、上記処理終了時点で、resultStringは、 以下ようになります。(docの内容は、上記文字列からXML文書を読込む方法で読込んだままのものとします)

<?xml version="1.0" encoding="UTF-8"?>
<root><test>テスト</test></root>

もう1つ、推奨しませんがこんな方法もあります。

String resultString = doc.getDocumentElement().toString();

resultStringは以下のようになります。

<root><test>テスト</test></root>

XML宣言が無くなるという結果になっているわけです。
この方法は場合によっては便利なのですが、推奨しません。 というのも、この方法でこの結果が得られるというのはJavaのドキュメントに記述されていないからです。 Documentインスタンスの作成にもファクトリーメソッドを使用していますので、 Java API仕様としてどのように動作するか決まってなく、また、動作を簡単に変えられる構成になっているということです。 システムのクリティカルな部分には使わないことをお勧めしておきます。

(2003/04/27) close処理を追加。

前の開発日記 次の開発日記 一覧