Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

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.

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

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
        )

)
*/

 

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

  • Conteúdo Similar

    • Por Fernando Rafael
      Boa tarde, estou com um problema ao tentar usar o CMD para imprimir o conteúdo de um arquivo TXT, estou usando o comando:
       
      PRINT /d:"\\cxgeral\Brother HL-1210W series" "imprimir.txt"  
      A impressora responde e faz o processo de impressão, porém a página sai em branco, usando este mesmo comando em uma impressora de pedido (Daruma DR800, Epson T20X, Elgin i9) funciona normalmente. mas em uma impressora comum fica em branco, sei que as impressoras na qual deram certo permitem impressão escrevendo direto na porta na qual estão instaladas. Mas a minha "Brother Hl-1210W" é uma impressora laser A4.
       
      Agradeço pela atenção.
       
       
      visite: www.sisnorg.com
    • Por Artur Mendonça
      Olá amigos.
      espero que estejam todos bem.
       
      Estou tentando criar uma galeria de imagens e colocar nestas um botão para votação (Gosto como no Facebook).

      Já consegui criar a galeria e colocar o Like nas imagens, mas acontece que quando  as imagens passam para a linha de baixo o botão Like não acompanha a imagem.
       
      Junto uma imagem para exemplificar como está e como deveria ser.
       
      O CSS está assim
      h1 { text-align: center; color: forestgreen; margin: 30px 0 50px; } .container h2 { text-align: center; color: rgb(8, 8, 8); margin: 30px 0 50px; } .gallery { margin: 10px 50px; padding-right: 0px; padding-left: 0px; } .gallery img { width: 230px; padding: 0px; opacity: 0.5; filter: grayscale(10%); transition: 1s; margin-top: 10px; margin-left: 10px; margin-bottom: 10px; margin-right: 0px; border: 2px solid #ccc; border-radius: 10%; } .ilike { display: grid; border-radius: 10%; box-sizing: border-box; text-align: left; padding: 15px; font-size: 20px; vertical-align: top; position: absolute; z-index: 1000; margin-top: 10px; margin-left: 10px; overflow: hidden; color: white; } O código da página da galeria de fotos está assim:
      <div class="gallery"> <?php $sql = "SELECT * FROM tbl_gallery where aid=$aid"; $num_rows = mysqli_num_rows(mysqli_query($conectar, $sql)); $result = mysqli_query($conectar, $sql); while ($row = mysqli_fetch_array($result)) { $gimage = $row['gimages']; $fotoid = $row['gid']; $likes = $row['likes']; ?> <a href="páginapararegistarovoto" ?> "><i class="far fa-thumbs-up ilike" alt="Vote"> <?php echo $likes; ?> </i></a> <i class="inum" > <?php echo "Foto " . $fotoid; ?> </i> <?php echo "<a href='../fotos/$gimage' data-lightbox='mygallery' data-title='Foto n.º: $fotoid'><img src='../thumbnails/$gimage' class='pic'></a>"; } ?> </div>  
       
       

    • Por Gilberto Jr
      Olá, boa tarde.
      Tudo bem?
       
      Preciso de uma ajuda aqui.
       
      Seguinte, através desse código eu consigo ler as informações que esta dentro do arquivo txt.
      <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>FileAPI HTML5</title> <style type="text/css"> #filecontents { border: double; overflow-y: scroll; height: 400px; } </style> </head> <body> Por favor selecione arquivo que será lido:<br /> <input type="file" id="txtfiletoread" /><br /> <div>Conteúdo do arquivo:</div> <div id="filecontents"> </div> <script> window.onload = function () { //Check the support for the File API support if (window.File && window.FileReader && window.FileList && window.Blob) { var fileSelected = document.getElementById('txtfiletoread'); fileSelected.addEventListener('change', function (e) { //Set the extension for the file var fileExtension = /text.*/; //Get the file object var fileTobeRead = fileSelected.files[0]; //Check of the extension match if (fileTobeRead.type.match(fileExtension)) { //Initialize the FileReader object to read the 2file var fileReader = new FileReader(); fileReader.onload = function (e) { var pontovirgula = ";"; var virgula = ","; var fileContents = document.getElementById('filecontents'); fileContents.innerText = fileReader.result.replace(virgula, pontovirgula).replace(virgula, pontovirgula); } fileReader.readAsText(fileTobeRead); } else { alert("Por favor selecione arquivo texto"); } }, false); } else { alert("Arquivo(s) não suportado(s)"); } } </script> </body> </html> So que o arquivo vem separado por virgulas. Eu quero substituir todas as virgulas por ponto e virgula. Se eu usar dessa forma, ele altera a virgula para ponto e virgula da primeira linha.
      <script> window.onload = function () { //Check the support for the File API support if (window.File && window.FileReader && window.FileList && window.Blob) { var fileSelected = document.getElementById('txtfiletoread'); fileSelected.addEventListener('change', function (e) { //Set the extension for the file var fileExtension = /text.*/; //Get the file object var fileTobeRead = fileSelected.files[0]; //Check of the extension match if (fileTobeRead.type.match(fileExtension)) { //Initialize the FileReader object to read the 2file var fileReader = new FileReader(); fileReader.onload = function (e) { var pontovirgula = ";"; var virgula = ","; var fileContents = document.getElementById('filecontents'); fileContents.innerText = fileReader.result.replace(virgula, pontovirgula).replace(virgula, pontovirgula); } fileReader.readAsText(fileTobeRead); } else { alert("Por favor selecione arquivo texto"); } }, false); } else { alert("Arquivo(s) não suportado(s)"); } } </script> 7909377852089;1;8380 7909377852133,1,8380 7909377820729,2,8380 7909377820736,2,8380 7909377820743,2,8380 E também, o ultimo valor eu preciso separar os centavos por , virgula.
       
      Arquivo deve ficar dessa forma quando mostrado na pagina.
       
      7909377852089;1;83,80
      7909377852133;1;83,80
      7909377820729;2;83,80
      7909377820736;2;83,80
      7909377820743;2;83,80
       
      Ou seja, contando da direita para esquerda, as duas primeiras posições é o centavos.
       
      Se alguém puder me ajudar, ficarei muito grato.
       
      Att;
      Gilberto Jr
    • Por pandinha_000
      Olá,
      Estou desenvolvendo um código em c++ utilizando manipulação de arquivos .txt (não por ponteiros), e gostaria de saber como fazer para que o algoritmo "pule" a primeira linha em branco do meu arquivo e passe já para a próxima, com dados válidos (na leitura). A propósito, existe a possibilidade de, ao escrever no arquivo, essa primeira linha em branco não exista?
      Desde já agradeço.
    • Por LucasSamuel
      Olá! Sou participante do grupo em um projeto de desenvolvimento de jogos em grupo. Estamos aceitando participantes de todos os tipos de categorias de desenvolvimento de jogos ... Convido você a participar deste projeto. A ideia de criar um grupo e ganhar US $ foi tirada de um colega meu que tinha câncer e acabou morrendo com esse sonho. Até agora, temos 4 participantes que, juntos, estamos tentando reunir 20 pessoas que têm idéias como a nossa…
      O grupo está na versão beta, porque ainda precisamos conversar com todos os participantes e convocar uma reunião para decidir democraticamente sobre jogos de categoria de mecanismo, lucros, servidores ... Mas, a princípio, o dinheiro que você ganhará estará relacionado à sua porcentagem no desenvolvimento de jogos . EX: 10% do jogo que você ajudou a criar; portanto, 10% do jogo é seu. Portanto, 10% de todos os lucros do jogo serão seus.
      Você escolhe seus turnos e horários e quanto ajudará. Pedimos apenas que você tente realizar determinadas tarefas determinadas para você, caso contrário, outro desenvolvedor fará em seu lugar. NOTA: Quanto mais você contribuir para a criação do jogo, mais lucros obterá.
      O grupo não terá um chefe ou um “comandante” organizador… Pois no grupo somos todos os chefes. Portanto, as decisões são tomadas em grupos por meio de reuniões e também de votos onde colocamos nossas idéias.
      Precisamos de mais de 20 participantes para iniciar nosso projeto. Todos no início do projeto assinaram um contrato com todos os termos “legais” do grupo, que serão decididos com todos os participantes. Portanto, se você não gosta de algum aspecto do grupo, pode e deve comentar e alterar os termos ... 
      O nome da categoria de estilo de jogo ... será decidido em grupos para que cada participante apresente 1 ou mais idéias de jogo. Serão escolhidos os mais votados e os mais adequados para todos os participantes. será vendido em várias plataformas ... android, PC ... em muitas lojas online diferentes ... será vendido acima de 5US $ e abaixo de 30US $
      Diga o que você pensa se quiser saber mais ou ligue para mim no whatsapp: +55 51 993700013 
      Vamos apresentar a todos os participantes do nosso grupo e aplicá-lo ao nosso grupo, discutir, conversar, criar, testar, aplicar e vir com idéias para o grupo com você.
×

Informação importante

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