Ir para conteúdo
JohnnyBegood

[Resolvido] Leitura TXT com agrupamento

Recommended Posts

Pessoal, tenho um arquivo txt com o seguinte layout:

 

No 0012 de 31/01/2016
(Cod0) 12345
(Cod1) Cod1-023
(Cod2) 22/12/1945
(Cod3) travamento de portas
gabinete ou de armario.

(Cod0) 23456
(Cod1) Cod1-055
(Cod2) 01/01/2005
(Cod3) gaveteiro

(Cod0) 78920
(Cod1) Cod1-077
(Cod2) 22/02/1975
(Cod3) clipe
aluminio ou ferro
(Cod4) anodizado

---------------------------------
Preciso ler, linha alinha e agrupar pelo Cod0. Assim, esse Cod0 refere-se a cada novo registro, podendo conter Cod1, Cod2, Cod3 e por aí vai...
Outro problema é que os Cod1, Cod2, Cod3 ,... podem conter uma linha adicional (exemplo do Cod 3, no primeiro registro).

Tenho esse código implementado com base num exemplo aqui do Fórum, mas não consegui implementar o agrupamento e adição dessa eventual linha extra.

<?php
$filename = fopen("inventario.txt","r");
$grupo = array();
while( !feof($filename) ){
    $line = trim(fgets($filename));
    
    $codigo = substr($line,0,6);
    if($codigo == '(Cod0)'){
        $grupo[] = array(
            'Cod:' => substr($line,4,40).'<br>',
            'Dados' => array()
        );
        continue;
    }
    
}
fclose($filename);
print_r($grupo);

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você pode validar a linha com uma expressão regular:

^\(([^\)]+)\)

Apesar de parecer complexa, a ER em si é simples (ela apenas repete por muitas vezes caracteres similares). A linha precisa iniciar com abertura de parênteses "(", ter qualquer caracter que não seja um fechamento de parênteses e finalizar com o fechamento de parênteses.

 

Ou seja:

if (preg_match("/^\([^\)]+\)/" , $line))

Para recuperar o valor interno da variável, basta adicionar um grupo (que é definido por parênteses) na ER. Os grupos são retornados, por referência, no terceiro parâmetro (opcional) da função preg_match:

if (preg_match("/^\(([^\)]+)\)/" , $line , $matches))
{
    var_dump($matches);
}

O resultado seria mais ou menos o seguinte:

array(2) { [0]=> string(6) "(Cod0)" [1]=> string(4) "Cod0" }

Como você precisa agrupar, e, até repetir em certos momentos, eu utilizaria da seguinte forma:

if (preg_match("/^\(([^\)]+)\)/" , $line , $matches))
{
    $lastCode = $matches[1];
    $matrix[$lastCode] = $line;
}

Caso a linha não possuir code, e o $lastCode for diferente de null, indica que o código deve ser repetido:

if (preg_match("/^\(([^\)]+)\)/" , $line , $matches))
{
    $lastCode = $matches[1];
    $matrix[$lastCode] = $line;
}
else if (!is_null($lastCode))
{
    $matrix[$lastCode] = $line;
}

A loja, em princípio, é essa. Apenas precisa polir para a sua situação.

  • +1 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Gabriel,

Não consegui implementar com suas dicas e Preg_match. Seu código agrupa pelo "parenteses" e não pelo "(Cod0)", que é o que preciso.

Tentei algo assim:

if (preg_match("/^\(([Cod0])\)/" , $line , $matches))

...mas não deu certo.

Outro problema é concatenar  a linha seguinte "gabinete ou de armario. " com a anterior, contendo o " (Cod3) travamento de portas".

Lembrando que o único indice que tem valor inalterado é (Cod0). Os demais (Cod1), (Cod2)...podem estar nominados como (22), (rar)...sempre dentro de "parenteses".

Tentei utilizar while com foreach mas nao consegui, igualmente.
Se puder me dar uma luz, agradeço...
 

Compartilhar este post


Link para o post
Compartilhar em outros sites

A parte de agrupar, aí fica com voce, poderia fazer algo como:

$cod0 =[];
$others = [];

foreach($matches AS $k => $v){
	
	if($k == '(Cod0)'){
		$cod0[] = $v;
		continue;
	}

	$others[$k] = $v;

}

A lógica seria essa, o resto você adapta

  • +1 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
<?php

$cod0 =  [];
$grupo = [];

$contador = 0;

$arquivo = fopen('inventario.txt', 'r');
     while (!feof($arquivo)) {
         $linha = fgets($arquivo, 1024);

         $linha = trim($linha); 

         if (substr($linha, 0, 6) == '(Cod0)') { 
             if (!empty($grupo)) {
                 $cod0[$id] = $grupo;
                 $grupo = [];
                 $contador = 0;
             }

             $id = substr($linha, 0, 12);

             $cod0[$id][] = $linha;
         } else { 
             if (substr($linha, 0, 4) != '(Cod') {     
                 $grupo[$contador -1] .= ' ' . $linha;
             } else {
                 $grupo[] = $linha;
             }

             $contador++;
         }
     }

$cod0[$id] = $grupo;

fclose($arquivo);

echo '<pre>';
print_r($cod0); exit;

/*

O resultado sera:

Array
(
    [(Cod0) 12345] => Array
        (
            [0] => (Cod1) Cod1-023
            [1] => (Cod2) 22/12/1945
            [2] => (Cod3) travamento de portas gabinete ou de armario.
        )

    [(Cod0) 23456] => Array
        (
            [0] => (Cod1) Cod1-055
            [1] => (Cod2) 01/01/2005
            [2] => (Cod3) gaveteiro
        )

    [(Cod0) 78920] => Array
        (
            [0] => (Cod1) Cod1-077
            [1] => (Cod2) 22/02/1975
            [2] => (Cod3) clipe aluminio ou ferro
            [3] => (Cod4) anodizado
        )

)
*/

 

  • +1 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em 18/02/2017 at 19:19, Mateus Silva disse:

A parte de agrupar, aí fica com voce, poderia fazer algo como:


$cod0 =[];
$others = [];

foreach($matches AS $k => $v){
	
	if($k == '(Cod0)'){
		$cod0[] = $v;
		continue;
	}

	$others[$k] = $v;

}

Mateus, obrigado pela estrutura. Porém o meu maior problema estava no agrupamento e o EdCesar elucidou pra mim.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

EdCesar,

 

Excelente algoritmo. Organizou da forma que necessito.

Porém, aqui pra mim, retorna erro :

Notice: Undefined offset: -1 in G:\XAMPP\htdocs\guardiao\Lixao\inventario\inventario_2.php on line 25
Notice: Undefined variable: id in G:\XAMPP\htdocs\guardiao\Lixao\inventario\inventario_2.php on line 15

Me parece ser no array negativo:

[-1] =>  No 0012 de 31/01/2016

-------------------------------------

No caso dos índices conterem nomes diferentes de (Cod, basta eu inserir no agrupamento condições diversas, certo?

         } else if (substr($linha, 0, 4) != '(Cod') {     
                 $grupo[$contador -1] .= ' ' . $linha;
             }else{
             if (substr($linha, 0, 4) != '(22)') {     
                 $grupo[$contador -1] .= ' ' . $linha;
             }else {
                 $grupo[] = $linha;
             }

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

JohnnyBegood, essa mensagem deve estar aparecendo provavelmente pq veio um daqueles registro que tem quebra de linha, na primeira posição. para resolver, basta adicionar um isset na linha:

$grupo[$contador -1] .= ' ' . $linha;  

 
ficando assim:

 if (isset($grupo[$contador -1])) {
      $grupo[$contador -1] .= ' ' . $linha;   
 }    

No else acima de (substr($linha, 0, 4) != '(Cod') { } eu já sei que esse é um dos registro que vai ser agrupado em (Cod0) e então faço essa verificação apenas para saber se não é uma linha quebrada, por exemplo:

 

(Cod3) travamento de portas
gabinete ou de armario.

pois se for,  jogo para a posição anterior para fazer um merge, por isso do -1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Resolvido EdCesar. Agradeço imensamente sua ajuda.

Aproveitando, você desenvolve para web e mobile? Caso precise de seus serviços, como você cobra? Estou desenvolvendo um sistema diferenciado, contendo uma primeira fase, de importação de dados disponibilizados em TXT e XML para um BD em mysql. Esta primeira fase estou desenvolvendo sozinho mas a segunda fase depende de sistema de comercialização de serviços ONLine e aí precisarei de um profissional pra implementar. Poderia me passar uma prévia de seu curriculum?

Compartilhar este post


Link para o post
Compartilhar em outros sites

JohnnyBegood, fico contento por ter ajudado!

Após oito longos anos, eu pedi demissão do meu trabalho e estou de ferias prologadas até Abril, focando apenas nos estudos. Depois dessa data, se precisar, meu contato é edcesar@edcesar.com
Você pode ver minhas especialidades no meu linkedin que esta no meu perfil aqui do forum.


Abraço.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Moderadores, Este tópico foi marcado como Resolvido, porém continuo com problemas na resolução do código. Gostaria que fosse reaberto. Agradeço a atenção.

Inicialmente postei uma estrutura de arquivo TXT, para exemplificar a ordenação recebida e recebi a contribuição do EdCesar, em especial, que auxiliou com um código funcional para tal estrutura. Porém, após implementar com a estrutura real, estou tendo inúmeros problemas:

Minha estrutura do arquivo TXT, real, é esta:
Preciso ler, linha alinha e agrupar pelo (Cd), que é o único indice de cada registro. Assim, esse (Cd) refere-se a cada novo registro, podendo conter sub indices diversos - (11), (22), (Co), etc. Estes sub indices podem conter uma linha adicional (exemplo do (Co) , no primeiro registro, que deve concatenar as linhas contendo "para gabinete" e "para armario.").
 

inventario.txt

//inicio
No 0012 de 31/01/2016

No 0012 de 31/01/2016
(Cd) 12345
(11) Cod1-023
(22) 22/12/1945
(Co) travamento de portas
para gabinete
para armario.

(Cd) 23456
(11) Cod1-055
(21) 01/01/2005
(22) gaveteiro
ferro
,madeira
,aluminio
(Cd) 78920
(22) Cod1-077
(54) 22/02/1975
(Co) clipe
aluminio ou ferro
(74) anodizado
(Cd) 0002525
(Di) Cod4-07100
(11) 22/02/2017
(22) camisa
vermelha
verde
(54) botoes amarelos
(Co) manga
,abacate
,cereja

 

//fim

Implementei a rotina do EdCesar mas, após muita pesquisa e modificações, não consegui agrupar os sub indices:

Juntamente , uma rotina para transferir os dados do array para variaveis e, posteriormente para o BD do mysql.

<?php


$cd =  [];
$grupo = [];

$contador = 0;

$arquivo = fopen('inventario.txt', 'r');
     while (!feof($arquivo)) {
         $linha = trim(fgets($arquivo, 1024));

         //$linha = trim($linha); 

         if (substr($linha, 0, 4) == '(Cd)') { 
             $contador = 0;
             if (!empty($grupo)) {
                 $cd[$id] = $grupo;
                 $grupo = [];
                 $contador = 0;
             }

             $id = substr($linha, 5, strlen($linha)-5 ); 
             $cd[$id][] = $linha;
         } else { 
          
                if (substr($linha, 0, 4) !== '(11)') {     
                     if (isset($grupo[$contador-1])) {
                           $grupo[$contador -1] .= ' ' . $linha;   
                           $contador--;
                      } 
                } else {
                    $grupo[] = $linha;
                }
             $contador++;
         
         }


     }

$cd[$id] = $grupo;

fclose($arquivo);



echo '<pre>';
print_r($cd); exit;

//-------------------------
//Rotina para transferir os dados do array para variaveis
$keys = array_keys($cd);
for($i = 0; $i < count($cd); $i++) {
    echo $keys[$i] . "<br>";
    foreach($cd[$keys[$i]] as $key => $value) {
        echo $key . " : " . $value . "<br>";
    }
    echo "<br>";
}

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Conteúdo Similar

    • Por Lenon John
      Eu preciso inserir mais de 3000 itens no ArrayList, o que gera o erro: method code too large.
      Acredito que usando um TXT como "BANCO DE DADOS" vai resolver o meu problema.
       
      Atualmente eu faço assim:
      -----------------------------------------------------
      ArrayList lista = new ArrayList();

      // inserindo os itens no ArrayList
      lista.add(new produtoItem(R.drawable.imagem, "AA", "AA", "AA", "AA"));

      adapter = new produtoAdapter(this, lista);
      ListView listView = (ListView) findViewById(R.id.listView1);
      listView.setAdapter(adapter);
      -----------------------------------------------------
       
      Como pegar os dados de um TXT e inserir no meu arrayList?

      OBS: Esse APP precisa funcionar sem a necessidade de internet. Ou seja, não posso usar um banco dados externo.
    • Por Alex_Dias_Vga
      Olá, tenho uma dúvida e espero que você ou alguém que veja este post possa me ajudar. Bom criei um app com flash cc6 usando Action Script 3. vários frames com vários mc tudo funcionando em um dos frame tenho um scrollpane que carrega um movie clip e o que tiver dentro dele normal, super simples, minha dúvida é como importar um texto do word com toda a sua formatação , importar um txt para um campo TLF é fácil mas a formatação é um problema. Tem que ser do word porque minha aplicação tem muitos texto e se algum texto precisar de alteração somente eu tenho que fazer porque ninguém no meu trabalho sabe usar o flash. Alguém pode me ajudar?
    • Por avelar.avelar
      Galera, estou tentando pegar de um arquivo TXT, 4 informacoes que cada linha dele da e gravar numa tabela do banco de dados, e esta dando erro e já mexi e remexi e não sei pq nao da certo, alguem poderias me ajudar?

      processa.php
      <?php
      session_start();
      //Incluir a conexao com BD
      include_once("conexao.php");
      //Receber os dados do formulário
      //$arquivo = $_FILES['arquivo'];
      //var_dump($arquivo);
      $arquivo_tmp = $_FILES['arquivo']['tmp_name'];
      //ler todo o arquivo para um array
      $dados = file($arquivo_tmp);
      //var_dump($dados);
                          $line = fgets($dados);
                         for($x=0; $x<0; $x++) {
                              $line = fgets($dados);
                          }
                          $ArrayRetornogru = array();
                          echo "dados".$dados;
                          echo "line". $line;
                          break;
                          
                          
                          while ($line = fgets($dados)) {
                                      
                                  $data_vencto = substr($line, 56,8);
                                  $data_pago = substr($line, 101,8);
                                  $valor          = substr($line, 122,4);
                                  $cpf  = substr($line, 256,11);
                                  // captar as 3 variaveis e fazer a busca das inscricoes pelo cpf data e valor
                                  echo $data_pago;
                                  echo $data_vencto;
                                  echo $valor;
                              $nbr_cpf = $cpf;
                              $parte_um     = substr($nbr_cpf, 0, 3);
                              $parte_dois   = substr($nbr_cpf, 3, 3);
                              $parte_tres   = substr($nbr_cpf, 6, 3);
                              $parte_quatro = substr($nbr_cpf, 9, 2);
                              $monta_cpf = "$parte_um.$parte_dois.$parte_tres-$parte_quatro";
                              echo $monta_cpf;
                               $ArrayRetornogru[] = $monta_cpf;
                                   
                                      echo "<pre>";
                                          print_r($ArrayRetornogru);
                                      echo "</pre>";
                                      echo "TESTE";
                                      
                          }
                          fclose($dados);
                          print_r($ArrayRetornogru);
                          echo "teste 2";
                          break;
                          
                          
      foreach($dados as $linha){
          $linha = trim($linha);
          $valor = explode(',', $linha);
          var_dump($valor);
          
          $data_vencto = $ArrayRetornogru[0];
          $data_pago = $ArrayRetornogru[1];
          $valor = $ArrayRetornogru[2];
          $cpf = $ArrayRetornogru[3];
          
          $result_usuario = "INSERT INTO gru_concurso (data_vencto, data_pago, valor, cpf) VALUES ('$data_vencto', '$data_pago', '$valor', '$cpf')";
          
          $resultado_usuario = mysqli_query($conn, $result_usuario);    
      }
      $_SESSION['msg'] = "<p style='color: green;'>Carregado os dados com sucesso!</p>";
      header("Location: index.php");
       
      ARQUIVO TXT:
       

       
      de cada linha eu preciso tirar as informacoes datavencto, datapago, valor, cpf e gravar numa tabela a parte.
       
      Falow galera !!!
       
       
       
    • Por Hozana
      Ola, bom dia!!
      pessoal preciso de ajuda!
       
      tenho a seguinte lista criada no html, ela não esta completa, só p vcs entenderem.
       
      <ul class="lista">                                            
                              <li>Datetime:</li>
                              <li>Velocidade:</li> 
                              <li>$ Inicial:</li> 
                              <li>$ Atual: </li>
                              <li>$ Financ: </li>
                              <li>% Neil: </li> 
                              <li>% Financ: </li> 
                              <li>% Ultimo: </li> 
                              <li>Estado: </li> 
                              <li>QDT Trade: </li> 
       
      e tenho no JS isso( peguei em um tutorial, e acho que é disso que eu preciso
       
      var numsList = [];
      $.ajax( 'Input.txt', {
          dataType: 'text',
          success: function(response){
              //response é o conteudo do Input.txt
              var lines = response.split('\n'); //quebra o arquivo em linhas, 
              for(var i in lines){
                  var row = lines;
                  var nums = row.split(','); //quebra a linha em valores separdos por virgula
                  for(var j in nums){
                      var num = parseInt(nums[j]); //converte o valor para int
                      if( !isNaN(num) ) //basicamente verifica se é um numero
                          numsList.push(num); //adiciona o item no array
                  }}
              console.log(numsList);
          }
      });
       
      Tenho também um arquivo txt(Input.txt) com algumas informações separadas por virgula.
      O que quero é alimentar a lista com as informações do arquivo txt, mas coloca-los na posição correta
       
      por exemplo
      eu Tenho o 1º item da lista Datatime:  e dentro dele quero colocar o primeiro item do arquivo
      mas não sei como chamar o JS  no HTML.
       
       
      Desde ja Obrigada.
    • Por itismejao
      Olá pessoal.
       
      Estava precisando de alguma tecnologia para fazer o seguinte:
       
      Vamos supor que eu tenha um cadastro de pessoas e tenha um modelo de um documento.
      Precisava que meu algoritmo/tecnologia pegasse esse texto, e que substituísse em certas posições por dados coletados do cadastro vinculado, isso tudo em um editor WYSIWYG.
      Alguém conhece algum jeito de fazer isso? Javascript/Ajax ou outra linguagem?
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.