Simpleライブラリの検証(1)
ざっくりと試してみたSimpleライブラリ。
いろいろと気になる点もあったので、ざくっと検証してみる。
XML宣言と文字エンコーディング
サンプルでは、出力されたXMLファイルにXML宣言が存在しない。そこで気になるのが、文字エンコーディングの扱いはどうなっているのかとか、XML宣言はどうやれば書けるのか、ということ。
そこで、JavaDocを参考にして書いたのが次のコード。
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import org.simpleframework.xml.Serializer; import org.simpleframework.xml.core.Persister; import org.simpleframework.xml.stream.Format; public class Main { /** * @param args */ public static void main(String[] args) { System.out.println("=== Serializer#write(T, File) ==="); try { Serializer serializer = new Persister(); HelloWorld helloWorld = newHelloWorld(); File result = new File("data/main-1.xml"); System.out.println(" " + result); serializer.write(helloWorld, result); } catch (Exception e) { e.printStackTrace(System.out); } System.out.println("=== Serializer#read(Class<? extends T>, File) ==="); try { Serializer serializer = new Persister(); File source = new File("data/main-1.xml"); HelloWorld helloWorld = serializer.read(HelloWorld.class, source); System.out.println(" " + source); dumpHelloWorld(helloWorld); } catch (Exception e) { e.printStackTrace(System.out); } String[] encodings = { "UTF-8", "Shift_JIS", "EUC_JP", "ISO-2022-JP", }; System.out.println("=== Serializer#write(T, OutputStream, String) ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(); HelloWorld helloWorld = newHelloWorld(); File result = new File("data/main-1-" + encoding + ".xml"); System.out.println(" " + result); serializer.write(helloWorld, new FileOutputStream(result), encoding); } catch (Exception e) { e.printStackTrace(System.out); } } System.out.println("=== Serializer#write(T, Writer) ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(); HelloWorld helloWorld = newHelloWorld(); File result = new File("data/main-1-2-" + encoding + ".xml"); System.out.println(" " + result); serializer.write(helloWorld, new OutputStreamWriter(new FileOutputStream(result), encoding)); } catch (Exception e) { e.printStackTrace(System.out); } } System.out.println("=== Serializer#write(T, Writer):XML宣言を書いてみる ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(new Format("<?xml version='1.0' encoding='" + encoding + "'?>")); HelloWorld helloWorld = newHelloWorld(); File result = new File("data/main-1-3-" + encoding + ".xml"); System.out.println(" " + result); serializer.write(helloWorld, new OutputStreamWriter(new FileOutputStream(result), encoding)); } catch (Exception e) { e.printStackTrace(System.out); } } System.out.println("=== Serializer#read(Class<? extends T>, File):XML宣言なし ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(); File source = new File("data/main-1-" + encoding + ".xml"); System.out.println(" " + source); HelloWorld helloWorld = serializer.read(HelloWorld.class, source); dumpHelloWorld(helloWorld); } catch (Exception e) { e.printStackTrace(System.out); } } System.out.println("=== Serializer#read(Class<? extends T>, InputStream, String):XML宣言なし ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(); File source = new File("data/main-1-" + encoding + ".xml"); System.out.println(" " + source); HelloWorld helloWorld = serializer.read(HelloWorld.class, new FileInputStream(source), encoding); dumpHelloWorld(helloWorld); } catch (Exception e) { e.printStackTrace(System.out); } } System.out.println("=== Serializer#read(Class<? extends T>, Reader):XML宣言なし ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(); File source = new File("data/main-1-" + encoding + ".xml"); System.out.println(" " + source); HelloWorld helloWorld = serializer.read(HelloWorld.class, new InputStreamReader(new FileInputStream(source), encoding)); dumpHelloWorld(helloWorld); } catch (Exception e) { e.printStackTrace(System.out); } } System.out.println("=== Serializer#read(Class<? extends T>, File):XML宣言あり ==="); for (String encoding : encodings) { System.out.println(" === " + encoding + " ==="); try { Serializer serializer = new Persister(); File source = new File("data/main-2-" + encoding + ".xml"); System.out.println(" " + source); HelloWorld helloWorld = serializer.read(HelloWorld.class, source); dumpHelloWorld(helloWorld); } catch (Exception e) { e.printStackTrace(System.out); } } } private static HelloWorld newHelloWorld() { HelloWorld helloWorld = new HelloWorld(); helloWorld.setJapanese("こんにちは、世界"); helloWorld.setEnglish("Hello World"); return helloWorld; } private static void dumpHelloWorld(HelloWorld helloWorld) { System.out.println(" japanese: " + helloWorld.getJapanese()); System.out.println(" english: " + helloWorld.getEnglish()); } }
HelloWorldクラスは次のようなもの。
import org.simpleframework.xml.Element; import org.simpleframework.xml.Root; @Root public class HelloWorld { @Element private String japanese; @Element private String english; public String getJapanese() { return japanese; } public void setJapanese(String japanese) { this.japanese = japanese; } public String getEnglish() { return english; } public void setEnglish(String english) { this.english = english; } }
これを実行すると、次のような出力が得られる。(スタックトレースは長いので一部省略している。)
=== Serializer#write(T, File) === data\main-1.xml === Serializer#read(Class<? extends T>, File) === data\main-1.xml japanese: こんにちは、世界 english: Hello World === Serializer#write(T, OutputStream, String) === === UTF-8 === data\main-1-UTF-8.xml === Shift_JIS === data\main-1-Shift_JIS.xml === EUC_JP === data\main-1-EUC_JP.xml === ISO-2022-JP === data\main-1-ISO-2022-JP.xml === Serializer#write(T, Writer) === === UTF-8 === data\main-1-2-UTF-8.xml === Shift_JIS === data\main-1-2-Shift_JIS.xml === EUC_JP === data\main-1-2-EUC_JP.xml === ISO-2022-JP === data\main-1-2-ISO-2022-JP.xml === Serializer#write(T, Writer):XML宣言を書いてみる === === UTF-8 === data\main-1-3-UTF-8.xml === Shift_JIS === data\main-1-3-Shift_JIS.xml === EUC_JP === data\main-1-3-EUC_JP.xml === ISO-2022-JP === data\main-1-3-ISO-2022-JP.xml === Serializer#read(Class<? extends T>, File):XML宣言なし === === UTF-8 === data\main-1-UTF-8.xml japanese: こんにちは、世界 english: Hello World === Shift_JIS === data\main-1-Shift_JIS.xml javax.xml.stream.XMLStreamException at com.bea.xml.stream.MXParser.fillBuf(MXParser.java:3700) at com.bea.xml.stream.MXParser.more(MXParser.java:3715) : === EUC_JP === data\main-1-EUC_JP.xml javax.xml.stream.XMLStreamException at com.bea.xml.stream.MXParser.fillBuf(MXParser.java:3700) at com.bea.xml.stream.MXParser.more(MXParser.java:3715) : === ISO-2022-JP === data\main-1-ISO-2022-JP.xml javax.xml.stream.XMLStreamException: ParseError at [row,col]:[4,14] Message: Unexpected end of stream at com.bea.xml.stream.MXParser.parseEntityRef(MXParser.java:2889) at com.bea.xml.stream.MXParser.nextImpl(MXParser.java:1846) : === Serializer#read(Class<? extends T>, InputStream, String):XML宣言なし === === UTF-8 === data\main-1-UTF-8.xml japanese: こんにちは、世界 english: Hello World === Shift_JIS === data\main-1-Shift_JIS.xml japanese: こんにちは、世界 english: Hello World === EUC_JP === data\main-1-EUC_JP.xml japanese: こんにちは、世界 english: Hello World === ISO-2022-JP === data\main-1-ISO-2022-JP.xml japanese: こんにちは、世界 english: Hello World === Serializer#read(Class<? extends T>, Reader):XML宣言なし === === UTF-8 === data\main-1-UTF-8.xml japanese: こんにちは、世界 english: Hello World === Shift_JIS === data\main-1-Shift_JIS.xml japanese: こんにちは、世界 english: Hello World === EUC_JP === data\main-1-EUC_JP.xml japanese: こんにちは、世界 english: Hello World === ISO-2022-JP === data\main-1-ISO-2022-JP.xml japanese: こんにちは、世界 english: Hello World === Serializer#read(Class<? extends T>, File):XML宣言あり === === UTF-8 === data\main-2-UTF-8.xml japanese: こんにちは、世界 english: Hello World === Shift_JIS === data\main-2-Shift_JIS.xml japanese: こんにちは、世界 english: Hello World === EUC_JP === data\main-2-EUC_JP.xml japanese: こんにちは、世界 english: Hello World === ISO-2022-JP === data\main-2-ISO-2022-JP.xml japanese: こんにちは、世界 english: Hello World
文字エンコーディングに関しては、
- 何も指定しない(つまり、サンプルのように)と、シリアライズもデシリアライズもUTF-8を仮定するようだ。
- Serializerインタフェースのメソッドの一覧を見てもらうとわかるが、InputStream/OutputStreamを指定するメソッドのうち、引数を3つとるメソッドの第3引数には文字エンコーディング名が指定できる。
- 文字エンコーディングに関して適切な対処をした上でReader/Writerを渡すのもひとつの手段。
- デシリアライズする場合には、適切なXML宣言(encoding指定あり)があればFileやInputStreamを指定しても正しく読める。ただし、(試してはいないが)Readerを指定する場合には、XML宣言が嘘にならないように適切な対処が必要となる。
XML宣言に関しては、
- Formatオブジェクトを使用してすべて自前で作るしかなさそう。
といったところだろうか。