HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"Encoded Streams"
Vol. 5, Issue 9, p. 38

	

Listing 1 

/* 
 * 
 *  EncodedInputStream 
 * 
 *  This class is used to decode a stream of data that has been encoded 
 * 
 * 
 * @author Mike Jasnowski 
*  @version 1.0 , 06/01/2000 
 */ 
import java.io.InputStream; 
import java.io.IOException; 
import java.io.ByteArrayOutputStream; 

public class EncodedInputStream extends InputStream{ 

  private EncodingScheme encoding_scheme; 
  private InputStream in_stream; 
  private ByteArrayOutputStream in = new ByteArrayOutputStream(); 
  

  public EncodedInputStream(InputStream in,EncodingScheme scheme){ 
        in_stream = in; 
        encoding_scheme = scheme; 
  } 

  public int read() throws IOException{ 
   int nill = -1; 
   return nill; 
  } 

  public byte[] readEncoded() throws IOException{ 

 int read = 0; 
        byte decoded[] = null; 
  
 while ((read = in_stream.read())!=-1) 
     in.write(read); 

 decoded = encoding_scheme.decode(in.toByteArray()); 
  
 return decoded; 
  } 

  public void close() throws IOException{ 
 super.close(); 
 in_stream.close(); 
  } 

}
 
Listing 2 

/* 
 * 
 *  EncodedOutputStream 
 * 
 *  This class is used to encode a stream of data 
 * 
 * @author Mike Jasnowski 
*  @version 1.0 , 06/01/2000 
 * 
 */ 

import java.io.OutputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 

public class EncodedOutputStream extends OutputStream{ 

 
  private OutputStream out_stream; 
  private ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  private EncodingScheme encoding_scheme; 

  public EncodedOutputStream(OutputStream out,EncodingScheme scheme){ 
         out_stream = out; 
         encoding_scheme = scheme; 
  } 

  public void write(int b) throws IOException{ 
        /* Encoding needs to be done here before it's written to Outputstream */ 
 out.write(b); 
   } 

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

  public void write(byte[] b,int offset,int length) throws IOException{ 
        for (int i = 0;i < length;i++) 
            write(b[offset + i]); 
  } 

  public void close() throws IOException{ 
      super.close(); 
      out_stream.write(encoding_scheme.encode(out.toByteArray())); 
      out_stream.close(); 
  } 
}
 
Listing 3 

/* 
 * 
 * 
 *  EncodingScheme - The interface class for all EncodingSchemes 
 * 
 * @author Mike Jasnowski 
*  @version 1.0 , 06/01/2000 
 */ 

public interface EncodingScheme{ 

  /* This method is called by EncodedOutputStream  */ 

  public byte[] encode(byte[] to_encode); 

  /* This method is called by EncodedInputStream */ 

  public byte[] decode(byte[] to_decode); 

} 

Listing 4 

/* 
 * 
 * This class carries the encode/decode logic for the scheme 
 * 
 * @author Mike Jasnowski 
*  @version 1.0 , 06/01/2000 
 */ 

import java.io.ByteArrayOutputStream; 

public class Base64EncodingScheme implements EncodingScheme{ 
  

  char NVT_ASCII[] = {'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','+','/'}; 

  private boolean isPadding = false; 
  
  public Base64EncodingScheme(){} 

  public byte[] encode(byte[] data){ 
  
  char temp[] = new char[4]; 
  int byte1=0,byte2=0,byte3=0,byte4=0; 
         int num_padding = 3; 
  byte[] hold_buffer = null; 
  String encoded = ""; 
  int chunk = 0; 
  ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  int counter = 0; 

  for (int i = 0;i < data.length;i+=3){ 
   hold_buffer = new byte[3]; 
   temp = new char[4]; 
   num_padding=3; 
   if (i < data.length){ hold_buffer[0] = data[i];num_padding--;} 
   if (i+1 < data.length){ hold_buffer[1] = data[i+1];num_padding--;} 
   if (i+2 < data.length){ hold_buffer[2] = data[i+2];num_padding--;} 

   /* This puts padding in place */ 
   if ((i+2 > data.length) && (hold_buffer[1] == 0)) {hold_buffer[1] = 61;isPadding=true;} 
   if ((i+3 > data.length) && (hold_buffer[2] == 0)) {hold_buffer[2] = 61;isPadding=true;} 

   /* Encoding Starts Here */ 
   byte1 = unsigned(hold_buffer[0]) >>> 2; 
   byte1 = byte1 & 0xFF; 

   temp[0] = NVT_ASCII[byte1];    /* first byte encoded */ 

          byte1 = unsigned(hold_buffer[0]) << 6; 
          byte1 = byte1 & 0xFF; 
          byte1 = byte1 >>> 2; 
   if (hold_buffer[1] != 0x3D | !isPadding) 
           byte2 = unsigned(hold_buffer[1]) >>> 4; 
   else 
    byte2 = 0; 
          byte3 = byte1 | byte2; 
  
          temp[1] = NVT_ASCII[byte3];    /* second byte encoded */ 

   if (hold_buffer[1] != 0x3D | !isPadding){ 
  
   byte1 = unsigned(hold_buffer[1]) << 4; 
   byte1 = byte1 & 0xFF; 
          byte1 = byte1 >>> 2; 
          byte2 = unsigned(hold_buffer[2]) >>> 6; 
          byte3 = byte1 | byte2; 

          temp[2] = NVT_ASCII[byte3];    /* third byte encoded */ 

   } 
  
   if (hold_buffer[2] != 0x3D | !isPadding){ 
   byte1 = unsigned(hold_buffer[2]) << 2; 
   byte1 = byte1 & 0xFF; 
          byte1 = byte1 >> 2; 
          temp[3]= NVT_ASCII[byte1];    /* fourth byte encoded */ 

   } 
  
   counter = 0; 

   for (int j = 0;j<temp.length;j++){ 
  
    if (temp[j] != 0){ 
         counter++; 
         out.write((byte)temp[j]); 
    } 
   } 

   chunk+=4; 
  
   if (chunk == 76){ 
    out.write(13); 
    out.write(10); 
    chunk=0; 
   } 
  
  } 

  /*Write out padding */ 
  for (int j = 0;j<num_padding;j++) 
   out.write(61); 

  /* Write final CRLF */ 
  out.write(13); 
  out.write(10); 

  return out.toByteArray(); 

  } 
  

  public byte[] decode(byte[] data){ 

  byte decoded[] = new byte[3]; 
  byte hold_buffer[] = new byte[4]; 
  int byte1=0,byte2=0,byte3=0; 
  int running_length = 0; 
  ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  ByteArrayOutputStream temp = new ByteArrayOutputStream(); 
  int remove_padding = 0; 

  /* Strip out CRLF - Chunk markers */ 
  for (int c = 0;c<data.length;c++){ 
   if (data[c] != 0x0D && data[c] != 0x0A) 
      temp.write(data[c]); 
  } 

  byte newdata[] = temp.toByteArray(); 
  
  running_length = newdata.length; 
  
  for (int i = 0;i < running_length;i+=4){ 
  
       hold_buffer = new byte[4]; 
       decoded = new byte[3]; 
       remove_padding = 0; 
  
       hold_buffer[0] = newdata[i]; 
       hold_buffer[1] = newdata[i+1]; 
       hold_buffer[2] = newdata[i+2]; 
       hold_buffer[3] = newdata[i+3]; 

       if (hold_buffer[2] == 61) remove_padding++; 
       if (hold_buffer[3] == 61) remove_padding++; 
  
       byte1 = nvt_lookup((char)hold_buffer[0]) << 2; 
       byte2 = nvt_lookup((char)hold_buffer[1]) >> 4; 
       byte3 = byte1 | byte2; 
  
       decoded[0] = (byte)byte3; /* First Byte Decoded */ 

       byte1 = nvt_lookup((char)hold_buffer[1]) << 4; 
       byte2 = nvt_lookup((char)hold_buffer[2]) >> 2; 
       byte3 = byte1 | byte2; 

       decoded[1] = (byte)byte3;  /* Second Byte Decoded */ 
  
       byte1 = nvt_lookup((char)hold_buffer[2]) << 6; 
         byte2 = nvt_lookup((char)hold_buffer[3]) ; 
       byte3 = byte1 | byte2; 

       decoded[2] = (byte)byte3; /* Third Byte Decoded */ 
  
       out.write(decoded,0,decoded.length-remove_padding); 

  } 
  
  return out.toByteArray(); 
  } 

private int nvt_lookup(char c){ 
 for (int i = 0;i<NVT_ASCII.length;i++){ 
  if (c == NVT_ASCII[i]) 
   return i; 
 } 
 return 0; 
} 

private int unsigned(int value){ 
          int newvalue = value << 24; 
          return newvalue >>> 24; 
 } 

} 

Listing 5 

/* 
 * 
 *  This sample performs the following: 
 * 
 *  1) Encodes some sample text using the "EncodedOutputStream" 
 *  2) Displays the encoded text from a file 
 *  3) Decodes the  sample text by reading in the file using 
 *     the "EncodedInputStream" 
 * 
 * @author Mike Jasnowski 
 * @version 1.0 , 06/01/2000 
 */ 

import java.io.*; 

public class EncodingSample{ 
  

  public static void main(String args[]){ 
    new EncodingSample(args[0]); 
  } 
  

  public EncodingSample(String filename){ 

    Base64EncodingScheme scheme = new Base64EncodingScheme(); 

    try { 

   /* Write it out and encode */ 

          EncodedOutputStream encOut = new EncodedOutputStream(new FileOutputStream("encoded.txt"),scheme); 
   ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
   FileInputStream fin = new FileInputStream(filename); 

   int ch = 0; 
   while ((ch = fin.read())!=-1) 
  buffer.write(ch); 

          byte edata[] = buffer.toByteArray(); 

          encOut.write(edata); 

          encOut.close(); 

   System.out.println(filename + " has been encoded"); 

   /* Read it back in and decode */ 
  
   EncodedInputStream encIn = new EncodedInputStream(new FileInputStream("encoded.txt"),scheme); 
   int r = 0; 
   byte ddata[] = encIn.readEncoded(); 
   encIn.close(); 

   FileOutputStream fout = new FileOutputStream(filename); 
   fout.write(ddata,0,ddata.length); 
   fout.close(); 

    System.out.println(filename + " has been decoded"); 

    }catch(IOException e){ 
          System.out.println(e); 
    } 

  } 
}
 
Listing 6 

public class HelloWorld{ 

 public static void main(String args[]){ 
  new HelloWorld(); 
 } 

 public HelloWorld(){ 
  System.out.println("HelloWorld"); 
 } 

} 

  
 
 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.