Tipsカテゴリ
プログラムTips ※Tips一覧はこちら
 
■ ハイパフォーマンス?Base64(Java) (2007/04/24)

Javaでのハイパフォーマンス(注:自社比f(^_^;)なBase64エンコーダーです。
ソースコード公開。(2007/4/28訂正)

バイト配列をBase64文字列に変換します。

  private String base64Encode(byte[] bsource) throws Exception {
    // 2文字単位の変換表を準備
    String[] blist = {
        "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
        "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
        "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
        "w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"};
    String[] base64list = new String[4096];
    for(int i = 0; i < 64; i++) {
      for(int j = 0; j < 64; j++) {
        base64list[i * 64 + j] = blist[i] + blist[j];
      }
    }

    // 変換先格納StringBuffer
    StringBuffer base64 = new StringBuffer("");

    // 3バイトを4文字に変換
    int byt1, byt2, byt3;
    for(int i = 0; i < bsource.length; i += 3) {
      if(bsource.length - i >= 3) {
        byt1 = (int)bsource[i + 0]; if(byt1 < 0) byt1 = 256 + byt1;
        byt2 = (int)bsource[i + 1]; if(byt2 < 0) byt2 = 256 + byt2;
        byt3 = (int)bsource[i + 2]; if(byt3 < 0) byt3 = 256 + byt3;
        base64.append(base64list[((byt1 << 4) & 0x000FF0) | ((byt2 >> 4) & 0x00000F)]);
        base64.append(base64list[((byt2 << 8) & 0x000F00) | ( byt3       & 0x0000FF)]);
      } else if(bsource.length - i == 2) {
        byt1 = (int)bsource[i + 0]; if(byt1 < 0) byt1 = 256 + byt1;
        byt2 = (int)bsource[i + 1]; if(byt2 < 0) byt2 = 256 + byt2;
        base64.append(base64list[((byt1 << 4) & 0x000FF0) | ((byt2 >> 4) & 0x00000F)]);
        base64.append(blist[((byt2 << 2) & 0x00003C)]);
        base64.append("=");
      } else {
        byt1 = (int)bsource[i + 0]; if(byt1 < 0) byt1 = 256 + byt1;
        base64.append(base64list[((byt1 << 4) & 0x000FF0)]);
        base64.append("==");
      }
    }

    return base64.toString();
  }

スピードアップのポイントの一つは、3バイトのバイト配列を一度に4文字に変換すること。これにより、ループ回数を減少させています。

もう一つのポイントは、内部のエンコード済み文字列にStringBufferを用いることです。知っている人にとっては何ということもないのですが・・・
Stringは内容が更新されると、新しくオブジェクトを作り直し、内容をコピー&変更し、古いオブジェクトを破棄するという手順を取るので、文字列長が大きくなればなるほど著しくパフォーマンスが落ちます。長い文字列の末尾に文字を追加していくような処理は、StringBufferで行なうと劇的な向上を見込めます。

カテゴリ:Java

 
 
Copyright(c) 2007-2017 ISCS All rights reserved.