Index: [Article Count Order] [Thread]

Date:  Tue, 24 Oct 2000 16:49:44 +0900
From:  tetsuya@....jp
Subject:  [XP-jp:01080] VXP メッセージ関連(その2)
To:  extremeprogramming-jp@....jp (extremeprogramming-jp ML)
Message-Id:  <97BA340C0480D411BDA800062939A1890607D8@....jp>
Posted:  Tue, 24 Oct 2000 16:49:52 +0900
X-Mail-Count: 01080

栗原です。

えっと、続きです。
BASE64 のエンコーダー/デコーダーを Java のストリームクラス
で利用されている Decorator パターンに変更したものです。

オーバーライドし忘れているメソッドがいくつかありますが、
暫定ということで、ご了承を。

#フリーのやつとかがありそうなんですが、、、

/*
 * $Id$
 */
package jp.co.esm.wiki.extremedomo.util;

public abstract interface Base64 {

    public static final char PAD_CHAR = '=';

    public static final char[] encoding_array = {
        'A','B','C','D','E','F','G','H',  // 0-7
        'I','J','K','L','M','N','O','P',  // 8-15
        'Q','R','S','T','U','V','W','X',  // 16-23
        'Y','Z','a','b','c','d','e','f',  // 24-31
        'g','h','i','j','k','l','m','n',  // 32-39
        'o','p','q','r','s','t','u','v',  // 40-47
        'w','x','y','z','0','1','2','3',  // 48-55
        '4','5','6','7','8','9','+','/'   // 56-63
    };
}

/*
 * $Id$
 */
package jp.co.esm.wiki.extremedomo.util;

import java.io.*;

public class Base64EncoderStream
    extends FilterOutputStream implements Base64 {

    public Base64EncoderStream(OutputStream out) {
        super(out);
    }
    public void write(byte[] b)
        throws IOException {

        write(b, 0, b.length);
    }
    public void write(byte[] b, int off, int len)
        throws IOException {

        for (int i = 0; i < len; i++)
            write(b[off + i]);
    }
    public void write(int b)
        throws IOException {

        buffer[bufSize] = (byte)b;
        bufSize++;

        if (bufSize == 3) {
            encode();
            bufSize = 0;
        }
    }
    public void flush()
        throws IOException {

        if (bufSize > 0) {
            encode();
            bufSize = 0;
        }
        out.flush();
    }
    public void close()
        throws IOException {

        flush();
        out.close();
    }
    private void encode()
        throws IOException {

        switch (bufSize) {
            case 1:
                out.write(getEncoded1());
                out.write(getEncoded2());
                out.write(PAD_CHAR);
                out.write(PAD_CHAR);
                return;
            case 2:
                out.write(getEncoded1());
                out.write(getEncoded2());
                out.write(getEncoded3());
                out.write(PAD_CHAR);
                return;
            case 3:
                out.write(getEncoded1());
                out.write(getEncoded2());
                out.write(getEncoded3());
                out.write(getEncoded4());
                return;
            default:
                throw new IllegalStateException(
                    "invalid state. " + "[bufSize: " + bufSize + "]");
        }
    }
    private char getEncoded1() {
        return encoding_array[(buffer[0] & 0xfc) >> 2];
    }
    private char getEncoded2() {
        return encoding_array[
            ((buffer[0] & 0x3) << 4) | ((buffer[1] & 0xf0) >>> 4)];
    }
    private char getEncoded3() {
        return encoding_array[
            ((buffer[1] & 0xf) << 2) | ((buffer[2] & 0xc0) >>> 6)];
    }
    private char getEncoded4() {
        return encoding_array[buffer[2] & 0x3f];
    }

    private byte[] buffer = new byte[3];
    private int bufSize = 0;

    public static void main(String argv[]) throws Exception {
	      ByteArrayInputStream in =
            new ByteArrayInputStream("abcdefg".getBytes());
	      Base64EncoderStream encoder = new
Base64EncoderStream(System.out);
	      int c;

	      while ((c = in.read()) != -1)
            encoder.write(c);

        encoder.close();
    }
}

/*
 * $Id$
 */
package jp.co.esm.wiki.extremedomo.util;

import java.io.*;

public class Base64DecoderStream
    extends FilterInputStream implements Base64 {

    public Base64DecoderStream(InputStream in) {
        super(in);
    }
    public int read()
        throws IOException {

        int result = -1;
        if (index >= bufSize) {
            decode();

            if (bufSize == 0)
                return -1;
            index = 0;
        }
        result = buffer[index];
        index++;
        return result;
    }
    public int read(byte[] b)
        throws IOException {

        return read(b, 0, b.length);
    }
    public int read(byte[] b, int off, int len)
        throws IOException {

        int result = -1;
        for (int i = 0; i < len; i++) {
            int c = read();
            if (c == -1)
                break;

            b[off + i] = (byte)c;
            result = i;
        }
        return result;
    }
    private void decode()
        throws IOException {

        bufSize = 0;
        byte[] chunk = new byte[4];

        while (true) {
            int c = in.read();
            if (c == -1)
                return;

            if (c != '\r' && c != '\n') {
                chunk[0] = (byte)c;
                break;
            }
        }

        int off = 1;
        int ready = 3;
        while (true) {
            int len = in.read(chunk, off, ready);
            if (len == ready)
                break;
            if (len == -1)
                throw new IOException("invalid stream length.");

            ready -= len;
	          off += len;
	      }

        byte[] converted = convertOnEncodeArray(chunk);

        buffer[bufSize] = getDecoded1(converted);
        bufSize++;
        if (chunk[2] == PAD_CHAR
            || converted[2] == OUTSIDE_OF_THE_RANGE)
            return;

        buffer[bufSize] = getDecoded2(converted);
        bufSize++;
        if (chunk[3] == PAD_CHAR
            || converted[3] == OUTSIDE_OF_THE_RANGE)
            return;

        buffer[bufSize] = getDecoded3(converted);
        bufSize++;
    }
    private final byte[] convertOnEncodeArray(byte[] original) {
        byte[] result = new byte[4];
        result[0] = convert_array[original[0]];
        result[1] = convert_array[original[1]];
        result[2] = convert_array[original[2]];
        result[3] = convert_array[original[3]];
        return result;
    }
    private byte getDecoded1(byte buf[]) {
	      return (byte)(((buf[0] & 0x3f) << 2) | ((buf[1] & 0x30) >>>
4));
    }

    private byte getDecoded2(byte buf[]) {
	      return (byte)(((buf[1] & 0xf) << 4) | ((buf[2] &0x3c) >>> 2));
    }

    private byte getDecoded3(byte buf[]) {
	      return (byte)(((buf[2] & 0x3) << 6) | (buf[3] & 0x3f));
    }

    private static final byte OUTSIDE_OF_THE_RANGE = -1;
    private static final byte[] convert_array = new byte[256];

    static {
        for (int i = 0; i < 256; i++)
            convert_array[i] = OUTSIDE_OF_THE_RANGE;

        for (int i = 0; i < encoding_array.length; i++)
            convert_array[encoding_array[i]] = (byte)i;
    }

    private byte[] buffer = new byte[4];
    private int bufSize = 0;
    private int index = 0;

    public static void main(String argv[]) throws Exception {
    	ByteArrayInputStream in =
          new
ByteArrayInputStream("GyRCJD0kbCRPOiNJLE1XJEokYiROJEckOSQrISkbKEI=".getBytes
());
	    Base64DecoderStream decoder = new Base64DecoderStream(in);

      byte[] buff = new byte[256];

      int readLen = decoder.read(buff);


      System.out.println("len:" + readLen + " " + new String(buff,
"iso-2022-jp"));
    }
}

---
Tetsuya Kurihara
tetsuya@....jp