Protocol Buffersを使う

ProtocolBuffers

protobuf - Project Hosting on Google Code
http://code.google.com/p/protobuf/
ProtocolBuffersはシリアライズライブラリです。
バージョン2.4.0aを使ってみます。

ダウンロード

http://code.google.com/p/protobuf/downloads/list
ここからダウンロード

ビルド

C++のところをビルド

$ ./configure
$ make
$ make check
$ sudo make install

jarつくる

cd java
mvn package

targetフォルダ内にprotobuf-java-2.4.0a.jarというファイルができていると思います

eclipseでプロジェクト作成

普通にjavaプロジェクトを作成
libsフォルダを作成し、中にprotobuf-java-2.4.0a.jarを入れてビルドパスに追加する

シリアライズ化するクラスの作成

ProtocolBuffersはシリアル化するクラスのprotoファイルを書く必要があります

Language Guide - Protocol Buffers - Google Code 
http://code.google.com/intl/ja/apis/protocolbuffers/docs/proto.html

このprotoファイルはIDLって言語で書くみたいです。
androidでserviceとの通信インターフェイスを定義するaidlファイルもIDLですね

インタフェース記述言語 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E8%A8%98%E8%BF%B0%E8%A8%80%E8%AA%9E
EmployeeTranslater.proto
package jp.tomorrowkey;

message Employee {
  required string name;
  required int32 age;
}

ファイル名とメッセージ名は違うやつにしないと怒られます

クラスに変換

プロジェクトルートで以下をコマンドする

protoc --java_out=src src/jp/tomorrowkey/EmployeeTranslater.proto

するとsrc/jp/tomorrowkeyにEmployeeTranslater.javaができあがります。

クラス変換を楽にするために

protoclipseというeclipse pluginがあります
これを使うとproto→javaの変換をjavaのビルドのタイミングで自動でやってくれます。

protoclipse - Project Hosting on Google Code 
http://code.google.com/p/protoclipse/

インストールが終わったらprotocの場所を設定したあとProtocolBuffersを使いたいプロジェクトで
右クリックして[Add Google ProtoBuf Compiler Nature]を選べば完了です。
Buildersの中にProtocolBuffersの変換する処理が追加されてると思います。

コードを書く

import com.google.protobuf.InvalidProtocolBufferException;

public class Main {
  public static void main(String[] args) {
    EmployeeTranslater.Employee.Builder builder = EmployeeTranslater.Employee.newBuilder();
    builder.setName("taro");
    builder.setAge(25);
    EmployeeTranslater.Employee src = builder.build();

    // シリアライズ
    byte[] buffer = src.toByteArray();

    // 表示してみる
    for (byte b : buffer) {
      System.out.print(Integer.toHexString(b & 0xFF) + " ");
    }
    System.out.println();

    // デシリアライズ
    EmployeeTranslater.Employee dst = null;
    try {
      dst = EmployeeTranslater.Employee.parseFrom(buffer);
    } catch (InvalidProtocolBufferException e) {
      dst = null;
    }

    // ちゃんと復元されたかな?
    if (dst != null) {
      System.out.println("name:" + dst.getName());
      System.out.println("age:" + dst.getAge());
    } else {
      System.out.println("dst is null");
    }
  }
}

実行

a 4 74 61 72 6f 10 19 
name:taro
age:25

やったー!シリアライズされたー!