Tokenizacao com Scanner em Java

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

Veja neste artigo o porquê da importância dos tokens nas buscas e “quebras” de grandes textos dentro de arquivos de texto ou qualquer outro tipo de armazenamento de Strings, com a ajuda da classe Scanner.

Existem situações onde nós, programadores, recebemos a “simples” tarefa de abrir um arquivo, ler um texto com 50 mil palavras, quebrar o texto em partes menores e utilizar estas partes para configurar Beans e coisas do tipo. Em casos como esse não se deve reinventar a roda e tentar criar algo totalmente revolucionário que irá mudar o jeito que todos os programadores executam esta tarefa. Aliás, sim, você pode tentar fazer isto. Porém, saiba que estará “perdendo tempo”, uma vez que uma solução para isto já existe e é muito simples de ser utilizada. Java oferece a seus programadores os tokens que, basicamente, executam todas as tarefas citadas anteriormente.

Utilizando o cenário anterior, suponhamos que precisamos abrir um arquivo chamado Teste.txt, fazer uma lida em seu texto, quebrá-lo em partes e atribuí-las a determinados objetos para serem utilizados posteriormente em outras partes do nosso sistema. Parece complicado, né?! Mas não é.

Neste artigo, abordaremos uma das classes que oferecem este tipo de serviço: Scanner.

Scanner

Antes de tentarmos solucionar o problema anterior, daremos uma olhada no exemplo de Scanner que existe no livro de certificação para podermos exemplificar bem e absorvermos o conceito da Classe.

Listagem 1: Exemplo de Scanner do Livro

import java.util.Scanner;


public class Testando {

	public static void main(String[] args)
	{
		boolean b2, b;
		int i;
		String s, hits = "";
		
		// Criação dos Scanners.
		Scanner s1 = new Scanner(args[0]);
		Scanner s2 = new Scanner(args[0]);
		
		// Verificação do primeiro scanner
		while (b = s1.hasNext())
		{
			s = s1.next(); 
			hits += "s";
		}
		
		// VErificação do segundo scanner
		while (b = s2.hasNext())
		{
			if (s2.hasNextInt())   // O próximo é um Integer?
			{
				i = s2.nextInt();
				hits += "i";
			}else if (s2.hasNextBoolean()) // O próximo é um Boolean?
			{
				b2 = s2.nextBoolean();
				hits += "b";
			}else
			{
				s2.next(); 				// Ou nenhum dos anteriores?
				hits += "s2";
			}
		}
		
		System.out.println("hits " + hits);
	}
}

Tendo em mente que os argumentos passados para a classe anterior foram “1 true 34 hi”, a reposta no console será “hits ssssibis2”.

Entendendo o fluxo do exemplo do livro

  • Por padrão, o delimitador padrão do Scanner é espaço. Sendo assim, a cada espaço encontrado na String, será separado um novo valor pelo Scanner. Esse delimitador pode ser alterado por outros tipos, digamos, mais específicos.
  • Foram criados dois scanners, ambos recebendo o valor do primeiro slot do vetor que veio dos argumentos.
  • A partir do primeiro Scanner, foi verificado se existia qualquer valor dentro da string. Ou seja, se o Scanner encontrasse algum qualquer valor, utilizando o delimitador de espaço, entraria no while até que o último fosse encontrado.
  • Utilizando o segundo Scanner, foi feita uma verificação mais específica na String. Quando o próximo valor a ser utilizado era um Integer, uma letra “i” era pra ser adicionada a variável hints; Quando era um boolean, uma letra “b”; Quando não era nem Integer e nem Boolean, um “s2”.
  • Com isso, obtivemos o resultado “hits ssssibis2”.

O exemplo serviu para mostrar uma utilização básica e outra mais específicas da classe Scanner.

Solucionando o problema proposto no artigo:

Para solucionar o problema proposto no início do artigo, nós poderíamos utilizar String.split(). Mas, é mais prático e eficiente que utilizemos Scanner devido a sua diversidade de funcionalidades que auxiliarão o programador na hora de execução da operação. Então, mãos na massa!

Teremos um arquivo chamado Teste.txt que terá, como conteúdo, o texto; “Tiago 23 Argolo”.

Listagem 2: Criação do arquivo Teste.txt e setando seu conteúdo

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;


public class Tester {
	
	public static void main(String[] args) {

		File f = new File("Teste.txt");     
		
		try
		{
			FileWriter fw = new FileWriter(f);   // Cria o nosso arquivo
			fw.append("Tiago 23 Argolo");	 	 // Seta seu conteúdo.
			fw.flush();
			fw.close();
		}catch(IOException e){}
			
		
	}

}

Antes de utilizarmos o Scanner nesta classe, segue um resumo do livro da certificação Java explicando as suas funcionalidades:

  • Scanners podem ser construídos usando-se arquivos, streams ou Strings como fonte.
  • A tokenização é realizada dentro de um loop, para que você possa finalizar o processo a qualquer momento.
  • Os tokens podem ser convertidos automaticamente para os seus tipos primitivos apropriados.

Scanner na prática!

Iniciaremos com a utilização da classe Scanner, então.

Listagem 3: Utilização do Scanner na classe Teste.java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;


public class Tester {
	
	public static void main(String[] args) {

		File f = new File("Teste.txt");
		String linha = ""; String inteiro = ""; String texto = "";
		Scanner s;
		
		try
		{
			FileWriter fw = new FileWriter(f);   // Cria o nosso arquivo
			fw.append("Tiago 23 Argolo");	 	 // Seta seu conteúdo.
			fw.flush();
			fw.close();
		}catch(IOException e){}
			
		// Obtendo o arquivo e suas informações
		
		try
		{
			FileReader fr = new FileReader(f);			
			BufferedReader br = new BufferedReader(fr);
			linha = br.readLine();
			
			s = new Scanner(linha);	
			boolean b;
			
			while (b = s.hasNext())	// verifica se tem outro valor.
			{
				if (s.hasNextInt())   // verifica se o próximo valor é inteiro
				{
					inteiro += " " + s.next();
				}else				//   CAso não for inteiro.
				{
					texto += " " + s.next();
				}
			}
			 
		}catch(IOException e){}

		// A partir daqui, posso utilizar ambas a variáveis em outros objetos
		// que serão utilizados pela minha aplicação.
		
		System.out.println("Textos" + texto +"\nInteiros: " + inteiro);
	}

}

Nesse código foram utilizadas as formas mais práticas, para que a explicação também possa ser simples. Então, não estranhe se encontrar algo válido, porém não recomendado na classe Teste.java

Explicando o código da classe Teste.java

  • Foi criado um Scanner com um Objeto String que possui o conteúdo do arquivo Teste.txt
  • Através deste Scanner, verificamos dentro do objeto String se existe um próximo valor.
  • Caso positivo, verifique se o valor é inteiro ou não. Caso seja inteiro, escreva o valor na variável inteiro. Caso seja qualquer outra coisa que não seja inteiro, escreva na variável texto o seu valor.
  • Exiba ambas as variáveis no final.

Eis o resultado da classe Teste.java:

Execução da classe Teste.java

Figura 1: Execução da classe Teste.java

Esta foi uma exemplificação simples, porém prática. Imaginemos utilizar esse poder de busca em algo mais sofisticado, como uma matriz contendo milhares e milhares de linhas. É necessário que seja transferido este exemplo para algo mais complexo. Algo que, talvez, você use em seu trabalho e agora saiba como melhorar o procedimento, torná-lo mais rápido e eficiente.

Com isto, termino o meu artigo sobre tokenização utilizando Scanner, uma ferramenta muito importante na linguagem Java que pode ser aplicada em diversas situações bem distintas. Espero ter ajudado na compreensão do assunto e estimulado o seu uso no dia-a-dia em vossos ambientes de trabalho.

Forte abraço!

Referências:

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?