Home page da disciplina MAC 324 Mapa do sítio da disciplina


MAC 324: Fontes dos programas cat, tr e wc

Os programas cat, tr e wc, abaixo, são parecidos com os seus honônimos em Unix. Estes programas foram elaborados por Marcio Rodrigo de Freitas Carneiro e por Caetano Jimenez Carezzato . Os originais destes programas podem ser encontrados na página: Diretório de Exemplos Java.

Programa cat

/**
 * Cat.java faz o mesmo (ou quase) que o cat do unix.
 * Para especificar saida ou entrada padrao (console) use -stdout, -stdin.
 * Para especificar arquivos use o nome.
 * -- Deve ser respeitada a ordem: 1o. entrada, depois saida.
 * EXEMPLO: java cat -stdin -stdout  
 *          java cat -stdin Teste
 *          java cat Blabla gravando
 *          java cat bleble -stdout
 *
 * Para sair quando a entrada for do console digite ^X e de enter.
 */
public class cat
{ 
  // e um main pois sera rodado da linha de comando
  public static void main(String[] args)

    {
      ManipulaES arquivo; // objeto do tipo ManipulaES

      if (args.length != 2) // verifica se os argumentos existem
	{
	  System.out.println("O uso de cat é: java cat [-stdin ou Nome do Arquivo] [-stdout ou Nome do Arquivo]");
	  return;
	}  // se estiverem incorretos sai do programa

      // cria o objeto com os argumentos dados.
      arquivo = new ManipulaES(args[0],args[1]);

      int temp = arquivo.Le();  // temp receber o byte 'da vez'

      // -1 significa fim do arquivo e 24 e igual a ^X. Entao do console pode ser dado um control+X e enter que ele para.
      while ((temp != -1) && (temp != 24))
	{
	  arquivo.Escreve((byte) temp);  // escreve o byte lido
	  temp = arquivo.Le();  // le outro byte
	}

      arquivo.Fecha(); // fecha stream
    }
} // fim da classe

Classe auxiliar ManipulaES usado nas classes cat, tr e wc

/** 
 * Esta classe faz a manipulacao de entrada e saida de arquivo e/ou console 
 * (Abre e fecha).
 * O construtor da classe DEVE receber duas Srings especificando o tipo de 
 * entrada e saida (-stdin (console) ou o nome do arquivo de entrada para E,
 * e -stdout (console) ou o nome do arquivo de saida para S).
 * Ha um construtor sem parametros que chama o com parametros dando -stdin e 
 * -stdout.
 * Os metodos sao:
 * - int Le(): retorna um inteiro (na verdade um byte, mas na forma de int)
 *             lido a partir do console ou do arquivo especificado.
 * - boolean Escreve(byte B): escreve um byte no console ou no arquivo especi-
 *                            ficado, e retorna true se conseguiu ou false se
 *                            algo deu errado.
 * - void Fecha(): fecha os streams, para poder tirar o ponteiro do objeto.
 */

import java.io.*;

public class ManipulaES
{
  /* stream de entrada recebe o console (System.in) ou um FileInputStream */
  private InputStream Entrada;

  /* stream de saida recebe o console (System.out) ou um FileOutputStream */
  private OutputStream Saida;

  /* construtor recebendo parametros */
  public ManipulaES(String E, String S)
  {
    // especificando a entrada
    if (E.equals("-stdin"))  //especificado a entrada pelo console
      Entrada = System.in;
    else // Vai usar o arquivo especificado
      {
	File NomeArq = new File(E); // objeto para o arquivo
          try
            {
              // associa o arquivo a entrada, tudo sera lido dele
	      Entrada = new FileInputStream(NomeArq);              
            }
          catch (IOException e) // caso aconteca algum erro
            {
	      System.out.println("Erro ao abrir o arquivo de Entrada");
	      // Obs: pode-se aqui lancar uma excecao para ser tratada por quem estiver usando a classe.
	    }
      }

    // especificando a saida
    if (S.equals("-stdout")) // especificado o console para saida
      Saida = System.out;
    else // Vai usar o arquivo especificado
      {
	File NomeArq = new File(S);
	if ((NomeArq.delete()) || !NomeArq.exists()) // Se o arquivo existir, tenta deletar.
	{// Se entrou aqui e porque o arquivo nao existia ou deixou de existir
          try
            {
              // associa o nome ao stream, tudo sera gravado no arquivo
	      Saida = new FileOutputStream(NomeArq);              
            }
          catch (IOException e)
            {
	      System.out.println("Erro ao abrir o arquivo de Saida");
	    }
	}
	else // Se entrou aqui e porque o arquivo de saida nao pode ser alterado
	  {
	    System.out.println("Nao foi possivel gravar no arquivo de Saida");
	  }
      }
  } // fim do construtor


  // construtor sem parametros (chama o de cima com in e out no console)
  public ManipulaES()
  {
    new ManipulaES("-stdin","-stdout");
  }

  // fecha o stream  
  public void Fecha() 
  {
    try
      {
        if (Entrada != null) Entrada.close();
        if (Saida != null) Saida.close();
      }
    catch (IOException e)
      {
        System.out.println("Nao foi possivel fechar os arquivos");
      }
  } // fim do metodo Fecha 

  // Le proximo byte. Retorna -2 se houver algum erro, -1 (metodo read() retorna -1) quando e o fim do arquivo, inteiro positivo o byte lido.
  public int Le()
  {
    try
      {
	return (int) Entrada.read();  // retorna e leitura
      }
    catch (IOException e)
      {
	return -2; // se houve algum erro retorna -2
      }
  } // fim do metodo Le

  // Escreve um byte na saida. se houver erro retorna false, se deu certo true
  public boolean Escreve(byte B)
  {
    try
      {
	Saida.write(B);  // grava
	return true;
      }
    catch (IOException e)
      {
	return false;
      }
  } // fim do metodo Escreve   
} // fim da classe ManipulaES

Programa tr

/**
 * tr.java faz o mesmo (ou quase) que o tr do unix.
 * Para especificar saída ou entrada padrão (console) use -stdout, -stdin.
 * Para especificar arquivos use o nome.
 * -- Deve ser respeitada a ordem: 1o. entrada, depois saída, primeiro a letra inicial, depois a letra final e opcionalmente o uso de maiúcula e minúscula.
 * EXEMPLO: java tr -stdin -stdout c C
 *          java tr -stdin Teste C x
 *          java tr Blabla gravando H 2 maiuscula
 *          java tr bleble -stdout 4 I minuscula
 *
 * Para sair quando a entrada for do console digite ^X e de enter (Não use ^C).
 */
public class tr
{

  public static void main(String[] args)
    {
      ManipulaES arquivo; // objeto do tipo ManipulaES
      boolean Maiúscula = false, Minúscula = false;

      if (args.length != 4) // verifica se os argumentos existem e se é para mudar tudo para maiúscula ou minúscula
        {
          if (args.length == 5)
            {
            if (args[4].equals("maiuscula"))
                Maiúscula = true;
                else if (args[4].equals("minuscula"))
                         Minúscula = true;
            }
          else
            {
              System.out.println("O uso do tr é: java tr [-stdin ou Nome do Arquivo] [-stdout ou Nome do Arquivo] [Letra inicial] [Letra final]");
              return;
            }
        }  // se estiverem incorretos, sai do programa

      // cria o objeto com os argumentos dados.
      arquivo = new ManipulaES(args[0],args[1]);
      
      //Vamos converter os argumentos para um tipo mais amigável
      byte Inicial = (byte) args[2].charAt(0); 
      byte Final = (byte) args[3].charAt(0);

      int temp = arquivo.Le();  // temp recebe o primeiro byte

      // -1 significa fim do arquivo e 24 é igual a ^X. Então do console pode ser dado um control+X e enter que ele pare.
      while ((temp != -1) && (temp != 24))
        {
          if (temp == Inicial) temp = Final; //Troca o byte
          if ((Minúscula) && (temp > 64) && (temp < 91)) temp += 32; // troca para minúscula
          else if ((Maiúscula) && (temp > 96) && (temp < 123)) temp -= 32; // troca para maiúscula
          arquivo.Escreve((byte) temp);  // escreve o byte lido
          temp = arquivo.Le();  // le outro byte
        }
      
      arquivo.Fecha(); // fecha stream
    }
} // fim da classe

Programa wc

/**
 * wc.java faz o mesmo (ou quase) que o wc do unix.
 * Para especificar saída ou entrada padrão (console) use -stdout, -stdin.
 * Para especificar arquivos use o nome.
 * -- Deve ser respeitada a ordem: 1o. entrada, depois saída.
 * EXEMPLO: java wc -stdin -stdout  
 *          java wc -stdin Teste
 *          java wc Blabla gravando
 *          java wc bleble -stdout
 *
 * Para sair quando a entrada for do console digite ^X e de enter.
 */
public class wc
{ 
  // é um main pois sera rodado da linha de comando
  public static void main(String[] args)

    {
      int linhas = 0, bytes = 0, palavras = 0; // Inteiros usados para contar
      boolean palavra = false;
      ManipulaES arquivo; // objeto do tipo ManipulaES

      if (args.length != 1) // verifica se os argumentos existem
        {
          System.out.println("O uso de wc é: java wc [-stdin ou Nome do Arquivo]");
          return;
        }  // se estiverem incorretos, sai do programa

      // cria o objeto com os argumentos dados.
      arquivo = new ManipulaES(args[0], "-stdout"); //Usa stdout só para ser compatível com a classe.

      int temp = arquivo.Le();  // temp recebe o byte 'da vez'

      // -1 significa fim do arquivo e 24 é igual a ^X. Então do console pode ser dado um control+X e enter que ele pare.
      while ((temp != -1) && (temp != 24))
        {
          if ((temp == 32) || (temp == 9)) // Se é um espaço ou um tab:
            {
              if (palavra) // Se havia uma palavra já no início, conta-a e reseta
                {
                  palavras++;
                  palavra = false; // Não é mais palavra
                }
            }
          else if (temp == 10) // Se é linha:
            {
              if (palavra) // Se havia uma palavra:
                {
                  palavras++;
                  palavra = false;
                }
              linhas++;
            }
          else if (temp != 13) palavra = true; // para ser compatível com DOS
          bytes++;
          temp = arquivo.Le();  // lê outro byte
        }
      if (palavra) palavras++;
      System.out.println("Número de Palavras: " + palavras);
      System.out.println("Número de Linhas: " + linhas);
      System.out.println("Número de Bytes: " + bytes);
      arquivo.Fecha(); // fecha stream
    }
} // fim da classe

Home page da disciplina MAC 324 Mapa do sítio da disciplina

e-mail: Imre Simon <is@ime.usp.br>

Last modified: Sun Apr 12 17:51:25 EST 1998