ARQ Texto - Duvidas - [RESOLVIDO]

Pessoal…

volto aqui novamente com mais dúvidas, se puderem ajudar, agradeço a todos!!

No meu código abaixo:


           while((leitor=reader.readLine() ) != null ) {     

                      String arquivoAbend = leitor;     
                      String[] novoArq = arquivoAbend.split(" ");     
                      StringBuffer linhaSaida  = new StringBuffer();

	                          
                      if(leitor.contains("ABENDED") || leitor.contains("FAILED") ||
                         leitor.contains("NOT CATLGD 2") || leitor.contains("UNEXPLA")){
	         
                          if(novoArq[13].length() > 8 && novoArq[4].equals("180211")){ 

                                  // DATA_PROCESSAMENTO
                                  linhaSaida.append(novoArq[2] + "  ");
                                  // HORA
                                  linhaSaida.append(novoArq[3] + "  ");
                                  // ODATE
                                  linhaSaida.append(novoArq[4] + "  ");               
                                  // JOB 
                                  linhaSaida.append(novoArq[13].substring(0,8) + "  ");
                                  // JOB_ID
                                  linhaSaida.append(novoArq[13].split("/")[1] + "  ");
                                  // OCORRENCIA
                                  linhaSaida.append(novoArq[15] + " " + novoArq[17]);
	                       }}    	
		        
                          //salva os ERROS na lista   
                                 dadosArquivo.add(linhaSaida.toString());  

Eu estou extraindo informações de um arquivo texto separado por colunas. Neste arquivo, existem 4 tipos de erros no qual busco na linha OCORRENCIA. Porém cada mensagem de erro, esta em uma determinada posição.

Exemplo:

Se for ABENDED, a OCORRENCIA esta na posição: linhaSaida.append(novoArq[15] + " " + novoArq[17]);

Se for COND a OCORRENCIA esta na posição: linhaSaida.append(novoArq[16] + " " + novoArq[18]);

Se for FAILED a OCORRENCIA esta na posição: linhaSaida.append(novoArq[15] + " " + novoArq[16] + " " + novoArq[17]);

Se for UNEXPLA a OCORRENCIA esta na posição: linhaSaida.append(novoArq[15] + " " + novoArq[16] + " " + novoArq[17] + " " + novoArq[18] + " " + novoArq[19]);

Como eu posso fazer para obter todas as informações diferenciando apenas a coluna OCORRENCIA conforme exemplo acima ?

E outra coisa, eu estou executando o meu programa e agora ele tá retornando apenas linhas vazias, não sei o que acontece…

valeu…

Sem o arquivo-base fica difícil de responder, mas eu utilizaria expressões regulares para capturar os valores, de acordo com cada ocorrência. Existem diversos materiais de expressões regulares, e é uma ferramenta poderosa para tratamentos de texto. Recomendo aprender!

Leo,

valeu pela ajuda, porém ainda me resta uma dúvida na seguinte situação:

quando meu IF é executado, ele pega todas as informações nas determinadas posições e adiciona tudo em uma arrayList. O Problema é que caso eu deixei a posição como esta em OCORRENCIAS : linhaSaida.append(novoArq[15] + " " + novoArq[17]); ele imprime para mim todas as linhas normalmente, porém algumas mensagem de erro vem do jeito que preciso e outras vem cortadas por que não estão na mesma posição.

como posso diferenciar as posições do item OCORRENCIAS de acordo com o meu IF que obtem as mensagem de erro quando adicionar as informações no ArrayList ?

Para cada mensagem de erro selecionada, somente o campo OCORRENCIAS terá que alterar as posições, as demais ficam iguais.


if(leitor.contains("ABENDED") || leitor.contains("FAILED") ||   
              leitor.contains("NOT CATLGD 2") || leitor.contains("UNEXPLA")){   
  
               if(novoArq[13].length() > 8 && novoArq[4].equals("180211")){   

                        ...inibido o restante dos dados
  
                       // OCORRENCIA   
                       linhaSaida.append(novoArq[15] + " " + novoArq[17]);   
             }}       
  
               //salva os ERROS na lista     
                      dadosArquivo.add(linhaSaida.toString());    

Acho que não entendi a dúvida.

Seria isso?

if (leitor.contains("ABENDED")) linhaSaida.append(novoArq[15] + " " + novoArq[17]); else if (leitor.contains("FAILED")) linhaSaida.append(novoArq[16] + " " + novoArq[18]); else if (leitor.contains("COND")) linhaSaida.append(novoArq[15] + " " + novoArq[16] + " " + novoArq[17]); else if (leitor.contains("UNEXPLA")) linhaSaida.append(novoArq[15] + " " + novoArq[16] + " " + novoArq[17] + " " + novoArq[18] + " " + novoArq[19]);

Outro jeito seria fazer um Enum que tem um “getOcorrencia”, outro jeito seria fazendo expressões regulares diferentes para cada parte, etc. Mas se você quer ficar no if, acho que isso resolve?

Leo,

pensei nisso, até fiz, mas acabou que ele não conseguiu obter nada.


 if(leitor.contains("ABENDED") || leitor.contains("FAILED") ||   
              leitor.contains("NOT CATLGD 2") || leitor.contains("UNEXPLA")){   
  
               if(novoArq[13].length() > 8 && novoArq[4].equals("180211")){   
  
                       // DATA_PROCESSAMENTO   
                       linhaSaida.append(novoArq[2] + "  ");   
                       // HORA   
                       linhaSaida.append(novoArq[3] + "  ");   
                       // ODATE   
                       linhaSaida.append(novoArq[4] + "  ");                 
                       // JOB   
                       linhaSaida.append(novoArq[13].substring(0,8) + "  ");   
                       // JOB_ID   
                       linhaSaida.append(novoArq[13].split("/")[1] + "  ");   
                       // OCORRENCIA   
                       linhaSaida.append(novoArq[15] + " " + novoArq[17]);   

então, no meu código, eu já faço um IF para coletar todas as linhas que tenham os erros, e uso um outro IF abaixo para obter somente informações com 8 posições e que tenham uma determinada data.

Pois bem, ele pega todas as linhas normalmente, porém na parte da ocorrência é que dá problema pois ele corta as informações, vou dar um exemplo:

Modo que eu quero obter as informações:
ABENDED
COND
FAILED
UNEXPLA

Modo que o sistema esta pegando a informação:

ABENDED
CON
FA
UNEX

Entendeu ? quando deixo setado as posições na ocorrência, ele pega uma informação legal de um tipo de erro e nos outros ele corta, por que não estão na mesma posição. só o campo de ocorrência.

Você pode colocar umas linhas de cada tipo de exemplo, para facilitar? Sério que eu não estou entendendo… Pode ser só uma, e mesmo com conteúdo genérico (só respeitando os espaçamentos em branco, que é o que o split usa).

Claro Leo,

As linhas originais da log são assim:

190211 040754 180211 CTMG     SEL216W JOB YABJD588 YABGD588/46235 OID=QRS9V UNEXPLAINED COND CODE 0002 STEP ST02 /
180211 013226 170211 CTMG     SEL211W JOB BJBJ2Z2K BJBG2Z2K/05106 OID=QQN3Y FAILED- JCL ERROR IN STEP ST02 /
190211 015936 180211 CTMG     SEL206W JOB YLBJD555 YLBGD555/08031 OID=QRPEL ABENDED CC U0350 STEP ST07 /
180211 061621 170211 CTMG     SPY275E JOB JABJD890 JABGD890/76576 OID=QQQ8E NOT CATLGD 2 ON DSNAME

O que eu espero que o programa faça é deixar as linhas conforme abaixo abaixo:

190211 063359 180211 JABGD890  69645  NOT CATLGD 2 
190211 013315 180211 BJBJ2Z2K  81774  FAILED- JCL ERROR
190211 014729 180211 YLBGD555  00085  ABENDED CC U0350 
190211 040754 180211 YABJD588  46235  COND 0002

Então, as colunas são separadas nesta sequência: DATA_PROCESSAMENTO, HORA, ODATE, JOB, JOB_ID, OCORRENCIA, conforme mostrado no exemplo acima.

O que esta acontecendo:

No meu código, no IF eu faço ele procurar por estas informações acima e gravo elas em um ArrayList. Até tudo bem, isso está ocorrendo, o problema é que na opção OCORRENCIA, eu defini uma posição especifica para o erro “UNEXPLAINED COND CODE 0002 STEP ST03” e ele deixa a mensagem filtrada desta forma: “COND 0002.”

Porém, esta posição não serve para os demais erros: NOT CATLGD 2, FAILED- JCL ERROR e ABENDED CC U0350 , por que ? por que ao invés de pegar o erro assim ABENDED CC U0350
ele traz assim CC U0350 , esconde a palavra ABENDED, por que as posições para estas mensagens não são as mesmas. Cada uma esta em uma posição diferente.

Para que isso aconteça, utilizo este código abaixo:

while((leitor=reader.readLine() ) != null ) {       
  
           String arquivoAbend = leitor;       
           String[] novoArq = arquivoAbend.split(" ");       
           StringBuffer linhaSaida  = new StringBuffer();   
  
                   
           if(leitor.contains("ABENDED") || leitor.contains("FAILED") ||   
              leitor.contains("NOT CATLGD 2") || leitor.contains("UNEXPLA")){   
  
               if(novoArq[13].length() > 8 && novoArq[4].equals("180211")){   
  
                       // DATA_PROCESSAMENTO   
                       linhaSaida.append(novoArq[2] + "  ");   
                       // HORA   
                       linhaSaida.append(novoArq[3] + "  ");   
                       // ODATE   
                       linhaSaida.append(novoArq[4] + "  ");                 
                       // JOB   
                       linhaSaida.append(novoArq[13].substring(0,8) + "  ");   
                       // JOB_ID   
                       linhaSaida.append(novoArq[13].split("/")[1] + "  ");   
                       // OCORRENCIA   
                       linhaSaida.append(novoArq[15] + " " + novoArq[17]);   
             }}       
  
               //salva os ERROS na lista     
                      dadosArquivo.add(linhaSaida.toString());    

Será que consegui explicar melhor ? :slight_smile:

valeuuu

Será que alguem poderia dar uma força ai ??..

valeu!!

Ficou bem mais fácil agora…

As 4 linhas vazias são porque seu IF que monta o stringbuffer nunca é “encontrado”. Se você fizer a inserção de dentro do if, você vê que fica com uma lista vazia.

Dei uma organizada para facilitar a vida:

  • Construa o objeto sempre com o menor escopo possível: por exemplo, o StringBuffer só é usado para montar a frase de erro, então, deixa ele dentro do if
  • Não crie variáveis à toa: String é imutável, não tem necessidade a linha 3 do seu último post.

Veja como ficou. Agora é só customizar o if lá…

[code]import java.util.ArrayList;
import java.util.List;

public class Main {

public static void main(String[] args) throws Exception {
	String[] linhas = new String[] {
			"190211 040754 180211 CTMG     SEL216W JOB YABJD588 YABGD588/46235 OID=QRS9V UNEXPLAINED COND CODE 0002 STEP ST02 /",
			"180211 013226 170211 CTMG     SEL211W JOB BJBJ2Z2K BJBG2Z2K/05106 OID=QQN3Y FAILED- JCL ERROR IN STEP ST02 /",
			"190211 015936 180211 CTMG     SEL206W JOB YLBJD555 YLBGD555/08031 OID=QRPEL ABENDED CC U0350 STEP ST07 /",
			"180211 061621 170211 CTMG     SPY275E JOB JABJD890 JABGD890/76576 OID=QQQ8E NOT CATLGD 2 ON DSNAME",
	};
	
	List<String> dadosArquivo = new ArrayList<String>();
	for (String leitor : linhas) {       
		if(leitor.contains("ABENDED") || leitor.contains("FAILED") ||   
				leitor.contains("NOT CATLGD 2") || leitor.contains("UNEXPLA")){   
			String[] novoArq = leitor.split("\\s+"); //juntando os delimitadores para nao ter "item" vazio
			System.out.println(retornaListaNumerada(novoArq)); //ajuda a depurar as posições
			if(novoArq[8].length() > 8 && novoArq[2].equals("180211")){    //verifica condição nos parâmetros certos
				StringBuilder linhaSaida  = new StringBuilder(); //stringbuilder é mais ágil para esses casos
				linhaSaida.append(novoArq[2]).append("  ");	// DATA_PROCESSAMENTO      
				linhaSaida.append(novoArq[3]).append("  "); // HORA   
				linhaSaida.append(novoArq[4]).append("  ");	// ODATE                    
				linhaSaida.append(novoArq[7].substring(0,8)).append("  "); // JOB      
				linhaSaida.append(novoArq[7].split("/")[1]).append("  "); // JOB_ID   
				if (leitor.contains("UNEXPLA")) { // OCORRENCIA
					linhaSaida.append(novoArq[10] + " " + novoArq[12]);
				} else if (leitor.contains("NOT CATLGD 2")) {
					linhaSaida.append(novoArq[14]); // e assim por diante
				}

				dadosArquivo.add(linhaSaida.toString()); //adiciono dado só aqui, para evitar linha vazia
			}
		}	           
	}

	for (String dado : dadosArquivo) {
		System.out.println(dado);
	}
}

private static String retornaListaNumerada(String[] a) {
	if (a == null)
		return "null";
	int iMax = a.length - 1;
	if (iMax == -1)
		return "[]";

	StringBuilder b = new StringBuilder();
	b.append('[');

	for (int i = 0;; i++) {
		b.append(i).append(" = ").append(a[i]);
		if (i == iMax)
			return b.append(']').toString();
		b.append(", ");
	}
}

}[/code]

Poxa leo, sem palavras para você…

Muitissimo Obrigado, já tava ficando doido com isso, pois isso é um sistema que vou usar para o serviço, e já estão me cobrando .hehehe.

Faltou só mais uma coisinha que eu não falei, mas só com toda essa sua explicação, já vou conseguir ir para frente.

Aquela variavel String arquivoAbend = leitor;eu a utilizei, por que o meu arquivo não está apenas com aquelas linhas que te passei, claro, elas existem e muitas outras iguais, porém tem muita sujeira no arquivo. e eu usei ela, para jogar as informações de todo o arquivo dentro dela e assim colunar as informações naquele String [] novoARQ.

naquele String [] linhas que você usou, eu posso fazer com que ele leia todo o arquivo ao invés de apenas aquelas linhas não posso ?

valeu…

:thumbup:
Pelo seu código, o leitor é somente a linha atual. O String[] era para simular o arquivo. Você pode ler todo o arquivo de uma vez com o FileUtils.readLines() do Apache Commons-IO. Recomendo dar uma olhada, se for fazer coisas com arquivo. Porém, é melhor ir lendo linha a linha, se o arquivo for muito grande!

Leo,

Então, alterei o código e deu certo, ficou desta forma:


ArrayList<String> dadosArquivo =  new ArrayList<String>();

while((leitor=reader.readLine() ) != null){

String[] novoArq = leitor.split(" "); //juntando os delimitadores para nao ter "item" vazio
		    							
if(leitor.contains("ABENDED") || leitor.contains("FAILED") ||     
leitor.contains("NOT CATLGD 2") || leitor.contains("UNEXPLA")){   
		    			     
System.out.println(retornaListaNumerada(novoArq)); //ajuda a depurar as posições   
		    				              
if(novoArq[13].length() > 8 && novoArq[4].equals("170211")){    //verifica condição nos parâmetros certos   
		    				                   
StringBuilder linhaSaida  = new StringBuilder(); //stringbuilder é mais ágil para esses casos   
		    				                  
linhaSaida.append(novoArq[2]).append("  "); // DATA_PROCESSAMENTO         
linhaSaida.append(novoArq[3]).append("  "); // HORA     
linhaSaida.append(novoArq[4]).append("  "); // ODATE                       
linhaSaida.append(novoArq[13].substring(0,8)).append("  "); // JOB         
linhaSaida.append(novoArq[13].split("/")[1]).append("  "); // JOB_ID
		    				                    
if (leitor.contains("UNEXPLA")) { // OCORRENCIA   
linhaSaida.append(novoArq[16] + " " + novoArq[18]);   
		    				                    
} else if (leitor.contains("NOT CATLGD 2")) {   
linhaSaida.append(novoArq[15] + " " + novoArq[16] + " " + novoArq[17] + " " + novoArq[18] +
" " + novoArq[19]);    
		    				                    
}else if (leitor.contains("FAILED")){
linhaSaida.append(novoArq[15] + " " + novoArq[16] + " " + novoArq[17]);

}else if (leitor.contains("ABENDED")){
linhaSaida.append(novoArq[15] + " " + novoArq[17]);
}
		    				                
dadosArquivo.add(linhaSaida.toString()); //adiciono dado só aqui, para evitar linha vazia

Deu certinho, pegou todos os dados sem problemas, brigadão por esta ajuda…

Agora, se não for abusar do todo o seu auxilio e puder me ajudar em mais estas, te agradeço…

1º - Bom, como posso fazer para ler linha a linha o arquivo? pois realmente o processo será grande, pois o programa ira ler uma média de 5 arquivos por vez, pois as informações são separas em vários arquivos.

2º - Agora estou usando o meu código para buscar informações finalizadas OK, e o que eu precisaria seria somente linhas assim:

15 = ENDED, 16 = "OK"]

E não pegar linhas desta forma:

15 = ENDED, 16 = "OK", 17 = (DUMMY, 18 = JOB)]
15 = ENDED, 16 = "OK", 17 = ,, 18 = FORCED, 19 = OK]

como posso fazer isso ?

Desculpa todas estas minhas perguntas, e que você esta me salvando…eu não sou o experte em Java, mas pelo menos, tudo que você esta passando, estou agregando ao meu conhecimento.
valeu mais uma vez.

E outra coisa que esqueci de comentar…

Aquele seu método para mostrar todas as posições, show de bola!!!

  1. Você lê linha a linha com BufferedReader.readLine(); padrão do java.

Algo como:

[code]String[] arquivos = null; //nomes dos arquivos

	for (String arquivo : arquivos) {
		BufferedReader br = new BufferedReader(new FileReader(new File(arquivo)));
		for (String linha = br.readLine(); linha != null; linha = br.readLine()) {
			//trata linha
		}
		br.close();
	}[/code]
  1. Você pode limitar pelo tamanho do array, por ex:

if (leitor.contains("UNEXPLA")) { // OCORRENCIA if (novoArq.length > 17) { // não quero o que tem "lixo" depois do param 16 continue; //continue vai ignorar o resto do loop e ir para o próximo } linhaSaida.append(novoArq[10] + " " + novoArq[12]); } else if (leitor.contains("NOT CATLGD 2")) { //... }

[quote=brunosardao]
Aquele seu método para mostrar todas as posições, show de bola!!![/quote]

Tirei do “Arrays.toString()” padrão do Java 6, só adicionei os índices! Crédito para eles…

Show maninho…sem palavras novamente…

Pode ser crédito para eles pelo padrão, mas crédito para você também pela instrução mastigada…hehe!!

E para fecharmos de vez…

Veja se é complicado…

No arquivo que contém os erros, possui o campo JOB_ID, no arquivo de Finalizados OK também possui o ID.

Tanto um arquivo como o outro possuem o mesmo ID, pois no arquivo de erro, tem o horário incial do processo e no arquivo de OK o horário final.

O que eu preciso para acabar com este processo, é fazer o seguinte:

Comparar os ID´s dos dois arquivos para saber se os processos possuem os mesmos, se possuir, será impresso em um novo arquivo, a sequência:

DATA PROCESSAMENTO, HORA, HORAFINAL (pego do arquivo de finalizados OK) JOB, JOB_ID e OCORRENCIAS.

é muito complicado isso ?

Valeu mais uma vez!! :slight_smile:

Essa vou responder menos detalhada, só dar a idéia:

  • Cria um Map<String, String> que contém “job id” na chave, e o momento de execução como valor.
  • Parseia o arquivo que tem os valores de final de execução
  • Na hora de parsear o outro arquivo, você consulta esse mapa. Se existir, você usa. Se não, deixa em branco (ou coloca null mesmo).

Tá joia leo, já fez muito por mim…só tenho que lhe agradecer…

Vou terminar o processo de captura dos finalizados OK e depois vou tentar essa sua ideia…

ai, surgindo duvidas vou postando…!!

Mais uma vez, brigadão…

:thumbup:

Não esquece de colocar o “resolvido” no título do primeiro post!

Opa, pode deixar, coloco sim!!

abs,