Ybadoo - Soluções em Software Livre
Tutoriais
Programação Orientada a Objetos

Forneça as classes decoradoras EncryptingWriter e DecryptingReader que codificam e decodificam os caracteres do leitor ou gravador que estiver por trás. Garanta que essas classes são também leitores e gravadores, de maneira que seja possível acrescentar novas decorações. Para a codificação, use o Caesar cipher, que desloca o alfabeto de três caracteres (isto é, A se transforma em D, B se transforma em E, e assim por diante) (Horstmann, 2007).

Horstmann, Cay. (2007). Padrões e Projeto Orientados a Objeto. 2ª edição. Porto Alegre: Bookman. 424 páginas.

 

Arquivo EncryptingWriter.java

/**
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

package com.ybadoo.tutoriais.poo;

import java.io.IOException;
import java.io.Writer;

/**
 * Cifrar um fluxo de caracteres com a Cifra de Cesar
 */
public class EncryptingWriter extends Writer
{
  /**
   * Chave da Cifra de Cesar
   */
  private int key;

  /**
   * Fluxo de caracteres de saida
   */
  private Writer out;

  /**
   * Construtor para inicializar o fluxo de caracteres de saida
   * 
   * @param out fluxo de caracteres de saida
   */
  public EncryptingWriter(Writer out)
  {
    this(out, 3);
  }

  /**
   * Construtor para inicializar o fluxo de caracteres de saida e a chave da Cifra de Cesar
   * 
   * @param out fluxo de caracteres de saida
   * @param key chave da Cifra de Cesar
   */
  public EncryptingWriter(Writer out, int key)
  {
    super();

    this.out = out;

    this.key = key % 95;
  }

  /* (non-Javadoc)
   * @see java.io.Writer#append(char)
   */
  public EncryptingWriter append(char c) throws IOException
  {
    this.out.append(encode(new Character(c).toString()).charAt(0));

    return this;
  }

  /* (non-Javadoc)
   * @see java.io.Writer#append(java.lang.CharSequence)
   */
  public EncryptingWriter append(CharSequence csq) throws IOException
  {
    this.out.append(encode(new String(csq.toString())).subSequence(0, csq.length()));

    return this;
  }

  /* (non-Javadoc)
   * @see java.io.Writer#append(java.lang.CharSequence, int, int)
   */
  public EncryptingWriter append(CharSequence csq, int start, int end) throws IOException
  {  
    this.out.append(encode(new String(csq.toString())).subSequence(0, csq.length()), start, end);

    return this;
  }

  /* (non-Javadoc)
   * @see java.io.Writer#close()
   */
  public void close() throws IOException
  {
    this.out.close();
  }

  /**
   * Cifrar o texto pela Cifra de Cesar
   * @param str texto normal
   * @return texto cifrado
   */
  private String encode(String str)
  {
    StringBuilder encoded = new StringBuilder();

    for(char ch: str.toCharArray())
    {
      if((ch >= 32) && (ch <= 126))
      {
        if((ch + this.key) <= 126)
        {
          encoded.append((char)(ch + this.key));
        }
        else
        {
          encoded.append((char)(ch + this.key - 95));
        }
      }
      else
      {
        encoded.append(ch);
      }
    }

    return encoded.toString();
  }

  /* (non-Javadoc)
   * @see java.io.Writer#flush()
   */
  public void flush() throws IOException
  {
    this.out.flush();
  }

  /* (non-Javadoc)
   * @see java.io.Writer#write(char[])
   */
  public void write(char[] cbuf) throws IOException
  {
    this.out.write(encode(new String(cbuf)).toCharArray());
  }

  /* (non-Javadoc)
   * @see java.io.Writer#write(char[], int, int)
   */
  public void write(char[] cbuf, int off, int len) throws IOException
  {  
    this.out.write(encode(new String(cbuf)).toCharArray(), off, len);
  }

  /* (non-Javadoc)
   * @see java.io.Writer#write(int)
   */
  public void write(int c) throws IOException
  {
    this.out.write(encode(new Integer(c).toString()));
  }

  /* (non-Javadoc)
   * @see java.io.Writer#write(java.lang.String)
   */
  public void write(String str) throws IOException
  {
    this.out.write(encode(str));
  }

  /* (non-Javadoc)
   * @see java.io.Writer#write(java.lang.String, int, int)
   */
  public void write(String str, int off, int len) throws IOException
  {
    this.out.write(encode(str), off, len);
  }
}

Arquivo DecryptingReader.java

/**
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

package com.ybadoo.tutoriais.poo;

import java.io.IOException;
import java.io.Reader;
import java.nio.CharBuffer;

/**
 * Descifrar um fluxo de caracteres com a Cifra de Cesar
 */
public class DecryptingReader extends Reader
{
  /**
   * Fluxo de caracteres de entrada
   */
  private Reader in;

  /**
   * Chave da Cifra de Cesar
   */
  private int key;

  /**
   * Construtor para inicializar o fluxo de caracteres de entrada
   * 
   * @param in fluxo de caracteres de entrada
   */
  public DecryptingReader(Reader in)
  {
    this(in, 3);
  }

  /**
   * Construtor para inicializar o fluxo de caracteres de entrada e a chave da Cifra de Cesar
   * 
   * @param in fluxo de caracteres de entrada
   * @param key chave da Cifra de Cesar
   */
  public DecryptingReader(Reader in, int key)
  {
    super();

    this.in = in;

    this.key = key % 95;
  }

  /* (non-Javadoc)
   * @see java.io.Reader#close()
   */
  public void close() throws IOException
  {
    this.in.close();
  }

  /**
   * Decifrar o texto pela Cifra de Cesar
   * @param str texto a ser decifrado
   */
  private void decode(char[] cbuf)
  {
    for(int i = 0; i < cbuf.length; i++)
    {
      if((cbuf[i] >= 32) && (cbuf[i] <= 126))
      {
        if((cbuf[i] - this.key) >= 32)
        {
          cbuf[i] = (char)(cbuf[i] - this.key);
        }
        else
        {
          cbuf[i] = (char)(cbuf[i] - this.key + 95);
        }
      }
    }
  }

  /* (non-Javadoc)
   * @see java.io.Reader#mark(int)
   */
  public void mark(int readAheadLimit) throws IOException
  {
    this.in.mark(readAheadLimit);
  }

  /* (non-Javadoc)
   * @see java.io.Reader#markSupported()
   */
  public boolean markSupported()
  {
    return this.in.markSupported();
  }

  /* (non-Javadoc)
   * @see java.io.Reader#read()
   */
  public int read() throws IOException
  {
    char[] buffer = new char[1];

    buffer[0] = (char)this.in.read();

    decode(buffer);

    return buffer[0];
  }

  /* (non-Javadoc)
   * @see java.io.Reader#read(char[])
   */
  public int read(char[] cbuf) throws IOException
  {
    int retorno = this.in.read(cbuf);

    decode(cbuf);

    return retorno;
  }

  /* (non-Javadoc)
   * @see java.io.Reader#read(char[], int, int)
   */
  public int read(char[] cbuf, int off, int len) throws IOException
  {
    int retorno = this.in.read(cbuf, off, len);

    decode(cbuf);

    return retorno;
  }

  /* (non-Javadoc)
   * @see java.io.Reader#read(java.nio.CharBuffer)
   */
  public int read(CharBuffer target) throws IOException
  {
    CharBuffer charBuffer = CharBuffer.allocate(target.capacity());

    int retorno = this.in.read(charBuffer);

    char[] buffer = charBuffer.array();

    decode(buffer);

    target.put(buffer);

    return retorno;
  }

  /* (non-Javadoc)
   * @see java.io.Reader#ready()
   */
  public boolean ready() throws IOException
  {
    return this.in.ready();
  }

  /* (non-Javadoc)
   * @see java.io.Reader#reset()
   */
  public void reset() throws IOException
  {
    this.in.reset();
  }

  /* (non-Javadoc)
   * @see java.io.Reader#skip(long)
   */
  public long skip(long n) throws IOException
  {
    return this.in.skip(n);
  }
}

Arquivo Application.java

/**
 * Copyright (C) 2009/2024 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

package com.ybadoo.tutoriais.poo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;

/**
 * Programa de teste dos decoradores para a Cifra de Ceaser
 */
public class Application
{
  /**
   * Metodo principal da linguagem de programacao Java
   * 
   * @param args argumentos da linha de comando (nao utilizado)
   */
  public static void main(String[] args)
  {
    try
    {
      PrintWriter out = new PrintWriter(
                        new BufferedWriter(
                        new EncryptingWriter(new FileWriter("teste.txt", true), 12)));
      out.println("the quick brown fox jumped over the lazy dog");
      out.println("abcdefghijklmnopqrstuvwxyz");
      out.println("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
      out.println("0123456789");
      out.close();

      LineNumberReader in = new LineNumberReader(
                            new BufferedReader(
                            new DecryptingReader(new FileReader("teste.txt"), 12)));
      System.out.println(in.readLine());
      System.out.println(in.readLine());
      System.out.println(in.readLine());
      System.out.println(in.readLine());
      in.close();
    }
    catch(IOException exception)
    {
      exception.printStackTrace();
    }
  }
}