티스토리 뷰

my Programing/etc..

base64 디코딩

Gandawon 2008. 4. 11. 14:44
package net.me2day.java.util;
/*
* @(#)BASE64.java
*
* Copyright (c) 2001-2002, JangHo Hwang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*      1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*      2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*      3. Neither the name of the JangHo Hwang nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*    $Id: BASE64.java,v 1.1 2007/02/28 08:43:11 xrath Exp $
*/

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
/**
* BASE64 (RFC 1521)를 직접 구현한 클래스이다.
* <p>
* 사용법은 간단하며 다음과 같다.
* <p>
* <pre><code>
* String str = "안녕하세요 오랜만입니다." );
*
* BASE64 b = new BASE64();
* String encoded = b.encode( str );
* String decode = b.decodeAsString( encoded );
*
* System.out.println( str.equals( decode ) );
* </code></pre>
* <p>
* 위의 코드는 true를 리턴할 것이다.
*
* @author Jang-Ho Hwang, rath@xrath.com
* @version 1.0.000, 2002/06/04
*/
public class BASE64
{
       static final char[] MAP =
       {
               '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', '+', '/',
       };

       static final int[] REVERSE_MAP =
       {
                0, // Padding for human readable index access
                0,  0,  0,  0,  0,  0,  0,  0,
                0,  0,  0,  0,  0,  0,  0,  0,
                0,  0,  0,  0,  0,  0,  0,  0,
                0,  0,  0,  0,  0,  0,  0,  0,
                0,  0,  0,  0,  0,  0,  0,  0,
                0,  0, 62,  0,  0,  0, 63, 52,
               53, 54, 55, 56, 57, 58, 59, 60,
               61,  0,  0,  0,  0,  0,  0,  0,
                0,  1,  2,  3,  4,  5,  6,  7,
                8,  9, 10, 11, 12, 13, 14, 15,
               16, 17, 18, 19, 20, 21, 22, 23,
               24, 25,  0,  0,  0,  0,  0,  0,
               26, 27, 28, 29, 30, 31, 32, 33,
               34, 35, 36, 37, 38, 39, 40, 41,
               42, 43, 44, 45, 46, 47, 48, 49,
               50, 51,
       };

       private boolean hasCRLF = true;

       public BASE64()
       {
               this( true );
       }

       public BASE64( boolean hasCRLF )
       {
               setCRLF( hasCRLF );
       }

       public void setCRLF( boolean hasCRLF )
       {
               this.hasCRLF = hasCRLF;
       }

       public boolean hasCRLF()
       {
               return this.hasCRLF;
       }

       /**
        * BASE64 로 인코딩된 문자열을 decode 한다.
        * 만약 올바르지 않은 BASE64 라도, 되는대로 계속 디코딩하게 된다.
        * <p>
        * 만약 byte[] 리턴되는 것이 귀찮을 경우 decodeAsString 메소드를
        * 사용하도록 하라.
        */
       public byte[] decode( String str )
       {
               ByteArrayOutputStream bos = new ByteArrayOutputStream(str.length());
               try
               {
                       for(int i=0, len=str.length(); i<len; i++)
                       {
                               char c = str.charAt(i);
                               if( c=='\r' || c=='\n' ) continue;
                               int v0 = REVERSE_MAP[ str.charAt(i++) ];                        
                               int v1 = REVERSE_MAP[ str.charAt(i++) ];
                               int v2 = REVERSE_MAP[ str.charAt(i++) ];
                               int v3 = REVERSE_MAP[ str.charAt(i) ];
                               int v = (v0 << 18) | (v1 << 12) | (v2 << 6) | (v3 << 0);
                               bos.write( (v >> 16) & 0xff );
                               bos.write( (v >>  8) & 0xff );
                               bos.write( (v >>  0) & 0xff );
                       }
               }
               catch( IndexOutOfBoundsException e ) {}
               return bos.toByteArray();
       }

       /**
        * BASE64로 encode된 주어진 str 문자열을 decode 한 후,
        * 시스템 default encoding 으로 문자열로 생성해준다.
        * <p>
        * 이 메소드는 내부적으로 decode 메소드를 직접 호출한다.
        */
       public String decodeAsString( String str )
       {
               return new String( decode(str) );
       }

       /**
        * 주어진 문자열을 시스템 default encoding으로 byte[] 로 변환 후,
        * BASE64 로 인코딩한다.
        */
       public String encode( String str )
       {
               return encode( str.getBytes() );
       }

       /**
        * 주어진 byte[] 를 BASE64 로 인코딩한다.
        */
       public String encode( byte[] b )
       {
               StringBuffer sb = new StringBuffer(b.length);
               int padCount = 0;
               ByteArrayInputStream bis = new ByteArrayInputStream( b );
               for(int i=0; i<b.length; i+=3)
               {
                       int v0 = bis.read();
                       int v1 = bis.read();
                       int v2 = bis.read();
                       if( v1==-1 ) { v1 = 0; padCount = 2; }
                       else
                       if( v2==-1 ) { v2 = 0; padCount = 1; }  
                       int v =
                               ((v0<<16) & 0x00FF0000) |
                               ((v1<< 8) & 0x0000FF00) |
                               ((v2<< 0) & 0x000000FF);
                       sb.append( MAP[(v>>18) & 0x3f] );
                       sb.append( MAP[(v>>12) & 0x3f] );
                       sb.append( MAP[(v>> 6) & 0x3f] );
                       sb.append( MAP[(v>> 0) & 0x3f] );

                       if( ((i+3)%57)==0 && hasCRLF )
                               sb.append( '\n' );
               }
               for(int i=padCount, last=sb.length(); i>0; i--)
                       sb.setCharAt( last-i, '=' );
               if( hasCRLF )
                       sb.append( '\n' );
               return sb.toString();
       }
}
 

 

'my Programing > etc..' 카테고리의 다른 글

HandsetProperty.getSystemProperty();  (0) 2008.05.22
base64 Incoder Decoder #2  (0) 2008.04.11
font.....  (0) 2008.02.25
BOM (Byte-Order Mark)  (0) 2007.11.23
Symbian OS Error Codes  (0) 2007.10.27
댓글