Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 

A Charset implementation which performs Rot13 encoding. Java code example - Click here to copy ->>>

   Can't find what you're looking for? Try our search:

Really working examples categorized by API, package, class. You can compile and run our examples right away! Not from source code for Java projects - only working examples! Copy, compile and run!

Code:

 

package com.ronsoft.books.nio.charset;

import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.util.Map;
import java.util.Iterator;
import java.io.Writer;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileReader;

/**
 * A Charset implementation which performs Rot13 encoding.  Rot-13 encoding
 * is a simple text obfuscation algorithm which shifts alphabetical characters
 * by 13 so that 'a' becomes 'n', 'o' becomes 'b', etc.  This algorithm
 * was popularized by the Usenet discussion forums many years ago to mask
 * naughty words, hide answers to questions, and so on.  The Rot13 algorithm
 * is symmetrical, applying it to text that has been scrambled by Rot13 will
 * give you the original unscrambled text.
 *
 * Applying this Charset encoding to an output stream will cause everything
 * you write to that stream to be Rot13 scrambled as it's written out.  And
 * appying it to an input stream causes data read to be Rot13 descrambled
 * as it's read.
 *
 * @author Ron Hitchens (ron@ronsoft.com)
 * @version $Id: Rot13Charset.java,v 1.9 2002/05/20 07:24:31 ron Exp $
 * Created: January, 2002
 */
public class Rot13Charset extends Charset
{
   // The name of the base charset encoding we delegate to.
   private static final String BASE_CHARSET_NAME = "UTF-8";

   // Handle to the real charset we'll use for transcoding between
   // characters and bytes.  Doing this allows applying the Rot13
   // algorithm to multi-byte charset encodings.  But only the
   // ASCII alpha chars will be rotated, no matter the base encoding.
   Charset baseCharset;

   /**
    * Constructor for the Rot13 charset.  Call the superclass
    * constructor to pass along the name(s) we'll be known by.
    * Then save a reference to the delegate Charset.
    */
   protected Rot13Charset (String canonical, String [] aliases)
   {
      super (canonical, aliases);

      // Save the base charset we're delegating to.
      baseCharset = Charset.forName (BASE_CHARSET_NAME);
   }

   // ----------------------------------------------------------

   /**
    * Called by users of this Charset to obtain an encoder.
    * This implementation instantiates an instance of a private class
    * (defined below) and passes it an encoder from the base Charset.
    */
   public CharsetEncoder newEncoder()
   {
      return new Rot13Encoder (this, baseCharset.newEncoder());
   }

   /**
    * Called by users of this Charset to obtain a decoder.
    * This implementation instantiates an instance of a private class
    * (defined below) and passes it a decoder from the base Charset.
    */
   public CharsetDecoder newDecoder()
   {
      return new Rot13Decoder (this, baseCharset.newDecoder());
   }

   /**
    * This method must be implemented by concrete Charsets.  We always
    * say no, which is safe.
    */
   public boolean contains (Charset cs)
   {
      return (false);
   }

   /**
    * Common routine to rotate all the ASCII alpha chars in the given
    * CharBuffer by 13.  Note that this code explicitly compares for
    * upper and lower case ASCII chars rather than using the methods
    * Character.isLowerCase and Character.isUpperCase.  This is because
    * the rotate-by-13 scheme only works properly for the alphabetic
    * characters of the ASCII charset and those methods can return
    * true for non-ASCII Unicode chars.
    */
   private void rot13 (CharBuffer cb)
   {
      for (int pos = cb.position(); pos < cb.limit(); pos++) {
         char c = cb.get (pos);
         char a = '\u0000';

         // Is it lower case alpha?
         if ((c >= 'a') && (c <= 'z')) {
            a = 'a';
         }

         // Is it upper case alpha?
         if ((c >= 'A') && (c <= 'Z')) {
            a = 'A';
         }

         // If either, roll it by 13
         if (a != '\u0000') {
            c = (char)((((c - a) + 13) % 26) + a);
            cb.put (pos, c);
         }
      }
   }

   // --------------------------------------------------------

   /**
    * The encoder implementation for the Rot13 Charset.
    * This class, and the matching decoder class below, should also
    * override the "impl" methods, such as implOnMalformedInput() and
    * make passthrough calls to the baseEncoder object.  That is left
    * as an exercise for the hacker.
    */
   private class Rot13Encoder extends CharsetEncoder
   {
      private CharsetEncoder baseEncoder;

      /**
       * Constructor, call the superclass constructor with the
       * Charset object and the encodings sizes from the
       * delegate encoder.
       */
      Rot13Encoder (Charset cs, CharsetEncoder baseEncoder)
      {
         super (cs, baseEncoder.averageBytesPerChar(),
            baseEncoder.maxBytesPerChar());

         this.baseEncoder = baseEncoder;
      }

      /**
       * Implementation of the encoding loop.  First, we apply
       * the Rot13 scrambling algorithm to the CharBuffer, then
       * reset the encoder for the base Charset and call it's
       * encode() method to do the actual encoding.  This may not
       * work properly for non-Latin charsets.  The CharBuffer
       * passed in may be read-only or re-used by the caller for
       * other purposes so we duplicate it and apply the Rot13
       * encoding to the copy.  We DO want to advance the position
       * of the input buffer to reflect the chars consumed.
       */
      protected CoderResult encodeLoop (CharBuffer cb, ByteBuffer bb)
      {
         CharBuffer tmpcb = CharBuffer.allocate (cb.remaining());

         while (cb.hasRemaining()) {
            tmpcb.put (cb.get());
         }

         tmpcb.rewind();

         rot13 (tmpcb);

         baseEncoder.reset();

         CoderResult cr = baseEncoder.encode (tmpcb, bb, true);

         // If error or output overflow, we need to adjust
         // the position of the input buffer to match what
         // was really consumed from the temp buffer.  If
         // underflow (all input consumed) this is a no-op.
         cb.position (cb.position() - tmpcb.remaining());

         return (cr);
      }
   }

   // --------------------------------------------------------
   
   /**
    * The decoder implementation for the Rot13 Charset.
    */
   private class Rot13Decoder extends CharsetDecoder
   {
      private CharsetDecoder baseDecoder;

      /**
       * Constructor, call the superclass constructor with the
       * Charset object and pass alon the chars/byte values
       * from the delegate decoder.
       */
      Rot13Decoder (Charset cs, CharsetDecoder baseDecoder)
      {
         super (cs, baseDecoder.averageCharsPerByte(),
            baseDecoder.maxCharsPerByte());

         this.baseDecoder = baseDecoder;
      }

      /**
       * Implementation of the decoding loop.  First, we reset
       * the decoder for the base charset, then call it to decode
       * the bytes into characters, saving the result code.  The
       * CharBuffer is then de-scrambled with the Rot13 algorithm
       * and the result code is returned.  This may not
       * work properly for non-Latin charsets.
       */
      protected CoderResult decodeLoop (ByteBuffer bb, CharBuffer cb)
      {
         baseDecoder.reset();

         CoderResult result = baseDecoder.decode (bb, cb, true);

         rot13 (cb);

         return (result);
      }
   }

   // --------------------------------------------------------

   /**
    * Unit test for the Rot13 Charset.  This main() will open and read
    * an input file if named on the command line, or stdin if no args
    * are provided, and write the contents to stdout via the X-ROT13
    * charset encoding.
    * The "encryption" implemented by the Rot13 algorithm is symmetrical.
    * Feeding in a plain-text file, such as Java source code for example,
    * will output a scrambled version.  Feeding the scrambled version
    * back in will yield the original plain-text do*****ent.
    */
   public static void main (String [] argv)
      throws Exception
   {
      BufferedReader in;

      if (argv.length > 0) {
         // open the named file
         in = new BufferedReader (new FileReader (argv [0]));
      } else {
         // wrap a BufferedReader around stdin
         in = new BufferedReader (new InputStreamReader (System.in));
      }

      // Create a PrintStream which uses the Rot13 encoding
      PrintStream out = new PrintStream (System.out, false, "X-ROT13");

      String s = null;

      // Read all input and write it to the output
      // As the data passes through the PrintStream
      // it will be Rot13 encoded.
      while ((s = in.readLine()) != null) {
         out.println (s);
      }

      out.flush();
   }
}

 
 



References.

The list of classes which were used on this page you can find below. The links to Java API contain official SUN documentation about all used classes.




[ Go Back ]



Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy