Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá boa tarde minha gente.
é o seguinte!!
Estou desenvolvendo um aplicativo em php que recebe o upload de um arquivo txt, porem este arquivo possui um grande numero de dados separados por " | "(pipes), Pego o txt abro ele dou um explode e separo tudo em array separada cada palavra.
Agora vem a bronca!!
para inserir estes dados em um banco, criei uma tabela com 21 colunas, ou seja vou ler um txt enorme porem preciso colocar no banco de dados apenas 21 desses dados e pior para encontrá-los no meio do txt eu crio um if que testa o primeiro elemento da linha que me identifica oque é, então quando chega nesse dado valor eu paro a varredura da array e devo inserir os próximos 21 arrays no banco.
e depois ainda devo continuar varrendo a array para procurar mais desses dados valores e repetir o processo de inserção no banco.
Como fasso isso.
Se eu crio um for quando achar o meu elemento escolhido so vou conseguir inserir o valor da primeira array em todas as colunas pois não vai acontecer incrementação do nome das colunas.
E agra??
Alguém já viu algo do tipo
estou meio perdido.
Se cada linha tem colunas separadas por pipe ("|"), basta ler uma linha e separar as colunas usando explode().
Cada índice do array retornado é uma célula da tabela. Basta selecionar as colunas desejadas e inserir no banco.
A função fgetcsv() pode lhe ser útil. Ela lê arquivos CSV, mas é possível mudar o delimitador (no seu caso, para "|")
certo eu já havia usado o explode, eu quebro certinho o txt.
Com o explode eu divido uma array inteira com todo o meu txt em diversas array pelo pipe.
o problema é que vou ter que ler um arquivo de muito grande, quando divido ele tem mais de 22 mil posições, porem preciso encontrar um alinha com um inicio igual, ler os 21 dados desta linha e inserir apenas eles no banco, depois de ler esta linha eu devo continuar verificando o txt e procurar outro inicio de linha igual a este dai tenho que fazer o mesmo guardar os próximos 21 dados, Esta parte de encontrar a palavra que me identifica a linha ja fis usei um if.
Porem vou precisas dos próximos 21 dados que estão no txt e colocá-los todos de uma unica vez, porem eu tenho um array, como coloca esse array, quando eu executar ele vai colocar sempre o mesmo dado la dentro o da posição 21 e não vai incrementar, a não ser que eu fisese 21 slq, ou colocasse em variáveis, alias ate ja implementei assim com variáveis, porem fica meio de vagar e ainda encontrei outro problema quando ele acha a primeira linha que possui o digito que o if verifica ele para ali e não verifica mais nada.
Espero que tenha sido mais claro na questão vou colocar o código que já fiz para ver oque vocês acham que pode melhorar minha situação.
Este aqui chama as funções
<?php
include_once("banco/conexao.php");
include_once("banco/funcoes.php");
$arquivo = $_FILES['txt'];
$nome = $_FILES['txt']['name'];
$nome_temporario = $_FILES['txt']['tmp_name'];
$erros = $_FILES['txt']['error'];
upload($arquivo, $nome, $nome_temporario, $erros);
$sped = analise($nome);
InserirA100($conexao, $sped);
?>
Este outro faz o serviço separa os pipes e manda par ao banco
<?php
//IMPORTAÇÃO E SEPARAÇÃO DO ARQUIVO
function upload($arquivo, $nome, $nome_temporario, $erros){
if($erros == 0){
$pasta = 'arquivos/';
move_uploaded_file($nome_temporario, $pasta . $nome);
}
else{
echo("Erro encontrado duranteo upload do arquivo tente novamnete!!");
}
}
//QUEBRA ARQUIVO TXT ENTRE AS PIPES
function analise($nome){
$sped = file_get_contents("arquivos/$nome");
$array = explode("|", $sped);
return $array;
}
//COLOCA A100 EM BANCO
function InserirA100($conexao, $sped){
set_time_limit(60);
$cont = count($sped);
for($i=0;$i<=$cont;$i++){
$contador = 0;
while($contador <= $cont){
if($sped[$i] == "A100"){
$inicial = $i;
$bloco = $sped[$inicial];
$query = ("insert into a100 (bloco) values ('{$bloco}')");
return mysqli_query($conexao, $query);
}
$contador++;
}
}
}
?>Já pensou em strpos($vetor, 'o que você quer encontrar'); ?
Você não pode ler um arquivo desse tamanho direto em memória.
E nem pode dar explode() no conteúdo inteiro.
Leia o arquivo linha por linha (pode usar fgets ou fgetcsv). Isso evita lotar a memória e consumir muitos recursos.
Depois dê explode no conteúdo da linha. Assim é fácil pegar cada uma das 21 colunas desejadas
ceerto é uma ideia porem pense assim
|a102|12|15|5|ggg|5|32|
|a102|12|15|5|ggg|5|32|
|a102|12|15|5|ggg|5|32|
|b300|15|55|4|44|7|88|1|
Meu txt é assim porem muito maior, eu preciso pegar os dados que estao na linha do a102 e colocalos em um banco de dados, depois cotinuar a leitura para encontrar a segunda linha com o a102 e assim sucessivamente ate acabar as linhas, dai poso finalizar o processo.
Vou dar um aolhada no fgets pra ver se entendo como aplicar, mas por eunquanto nao esta tao lento assim nao, peguei apenas um dado como deu pra ver no codigo levou poucos segundos.
Ate funcionou porem ele adiciona apenas ate aquela linhad epois para.
Meu txt é assim porem muito maior, eu preciso pegar os dados que estao na linha do a102 e colocalos em um banco de dados, depois cotinuar a leitura para encontrar a segunda linha com o a102 e assim sucessivamente ate acabar as linhas, dai poso finalizar o processo.
Então, é isso que estou dizendo.
fgets lê uma linha. Aí você dá explode nela e pega os campos que quiser
Pense assim: pra que guardar todas as linhas, se você quer apenas algumas? E pior, guardar o arquivo inteiro em memória e ainda um array de todos os campos. É o dobro de memória. Se for hospedagem compartilhada, logo você recebe um email falando sobre uso excessivo de recursos (se usar um arquivo muito grande, claro)
Você está pegando o caminho mais longo.
Outra coisa é o INSERT. Se executar dentro do loop, gastará tempo demais. Monte uma query só e execute só uma vez. Veja: http://rberaldo.com.br/inserindo-multiplos-registros-em-tabela-de-banco-de-dados/
Ok Beraldo Boa a sua dica, Vou tentar implementar o código
Qualquer coisa posto novamente aqui o desfecho da historia
Gostei do site!!!
@Beraldo acompanhei a sua explicação e parabens pelo post do seu blog.
Eu fiquei com uma duvida a respeito do INSERT.
Se eu estiver utilizando bibliotecas como PDO esse problema de performance durante o insert já não é corrigido utilizando o prepared statement?
Ou até mesmo neste caso é melhor armazenar a inserção a parte e executar de 1x ?
@gabrieldarezzo
Primeiramente, obrigado :)
Prepared Statements não têm ligação com desempenho. Eles servem para filtrar os dados.
O problema do INSERT dentro do loop é que é feito um INSERT (e consequentemente uma comunicação com um programa externo) a cada iteração. Isso consome muito tempo, usando Prepared Statements ou não.
Se usar um único INSERT (ou um conjunto reduzido, já que existe um limite - ainda que grande - no tamanho da query), só haverá uma comunicação entre processos.
Eu achei q o PDO cacheava algumas coisas na memoria durante cada Insert, por isso a duvida.
Eu achei q o PDO cacheava algumas coisas na memoria durante cada Insert, por isso a duvida.
Desconheço isso.
Mas, se você executa com os métodos query() ou execute() e recebe a resposta, isso significa que a consulta foi enviada. E nesse caso é a consulta propriamente dita, não só um cache
Caro /profile/218818-eduardo_ci%C3%AAncia_da_comp/?do=hovercard" data-mentionid="218818" href="/profile/218818-eduardo_ci%C3%AAncia_da_comp/" rel="">@Eduardo_ciência_da_Comp.
Estou com um projeto parecido com o seu e também estou tendo dificuldade no upload, leitura e inserção no banco.
Conseguiu evoluir nos scripts???... Utilizei vários comandos... Mas até agora sem sucesso...
explode, fopen, stream_get_line, fgets, fgetcsv...
Não entendi muito bem, post o arquivo e tabela amigo.