Wcztywanie dużych plików CSV

0

Cześć jestem nowy na tym forum.
Mam problem z wczytywaniem do MySQL
Rekordy są wczytywane z pliku .CSV -kilkadziesiąt MB
Plik jest wywoływany co 2 minuty z Crona i na raz wczytuje 10 000 linijek

function CzytajBigCsv($path, $skip,$lines){
   $file = new \SplFileObject($path, 'r');
   $file->setFlags(\SplFileObject::READ_CSV);
   $file->seek($skip);
 
   while (!$file->eof()){
     yield $file->current();
     if($i++>$lines)break;
     $file->next();
 $l=$file->key();';
 $_SESSION["ofset"]=$l;
 }   

Prawie wszystko prawidłowo się wczytuje ale niestety, gdy pojawi się przecinek w jakimś polu, to wczytuje tę linijkę tylko do przecinka a reszty nie wczytuje i prawidłowo przechodzi do następnej linijki.
Przy wczytywaniu do Bazy pojawia się błąd
Będę wdzięczny za jakąkolwiek pomoc

2

Pokaż kilka problematycznych linijek pliku.
Jak duży on jest, że używasz generatorów?

0

@jurek1980: to jest prawidłow wczytana

string(478) "G-Art4You;"9287614494";"shop|23503";"29893";"0";"";"A0-N3256";"Obraz - Platyna z pazurem 100 x 50";"2";"998";"1";"0";"1589919206";"2020-05-19 22:13:26";"1646400261";"2022-03-04 14:24:21";"1617625287";"2021-04-05 14:21:27";"217.46";"15.00";"0";"23.00";"2";"110911";"Dom i Ogród/Wyposażenie/Dekoracje i ozdoby/Obrazki i obrazy";"95430";"G-artObrazy v2";"544066";"podstawwy";"PT72H";"24880";"Grin Sp. Z O.o.";"20200519_33151_67";"";"";"10520251360";"208";"3";"";"";"";"";"";"";"""

A to jest wczytana do przecinka

string(95) "G-Art4You;"9345608676";"shop|23503";"53754";"0";"";"A0-TNTTUR0297";"Fototapeta na drzwi - Wyspa"
2

https://www.php.net/manual/en/splfileobject.setcsvcontrol.php
Masz delimiter w postaci średnika ; no to przed wczytaniem pliku ustaw parametr by delimiterem był średnik. Wartość domyślna to właśnie przecinek.

0

@jurek1980: dopisałem

$file->setCsvControl(";","\"" ); 

i efekt jet taki

string(9) "G-Art4You"

wczytuje tylko do pierwszego delimitera ";"
no to ustawiłem

$file->setCsvControl("*","\"" ); // gwiazdki w tych stringach nie ma:)))

i przeczytało całość:))

Dziękuję za pomoc:)

2

$file->setCsvControl("*",""" ); // gwiazdki w tych

yyy? to co Ty robisz z tym plikiem? Bo wygląda na to, że tylko czytasz go po linii. Jeśli tak to w ogóle nie musisz go traktować jako CSV i używać do tego funkcji.

0

@jurek1980: wpisuje wszystko do MySql i tam dalej z tym pracuje. Jak wczytuje wszystko na raz to mi serwer siada bo to jest ok 180 000 linjjek.

@jurek1980: Traktuje każdą linijke jak tekst, zmieniam delimitery i wpisuje wszystko do MySql i tam dalej z tym pracuje. Jak wczytuje wszystko na raz to mi serwer siada bo to jest ok 180 000 linjjek.
Traktuje każdą linijkę jak tekst, zmieniam delimitery i do bazy a delimiter * nie jest w tych tekstach obecny.

2

Nie wiem. Jakoś te opisy mi nie pasują. Chcesz wklej prawidłowo cały kod i pokaż jak to robisz. jakoś tak myślę, że kiedyś na gwiazdkę trafiasz i się możesz zdziwić.

0

To jest główny plik wczytujący

$wynik =readBigCsv($path, $ofset,10000);
if ($value[0]==NULL)break;
$w[]=$value[0];
$ofset=$_SESSION["ofset"];
 ZapiszWiele($w, $db, "Allegro");

i funkcje:

 function ZapiszWiele($lines, $dbi, $tab){
 
 foreach($lines as $val){

        $val=str_getcsv($val,";");
      
       $va= KonwertString(",",$val);
        $Result="$Result,$va";
    
       }
    $Result=substr($Result,1);
      $dbi->query("Replace into  `$tab` VALUES $Result ");
      }
 function KonwertString($delimiter, $val){
    foreach ($val as $value) {
        $value=str_replace(",",".",$value);
        $value=str_replace("'","*",$value);
        $wyn="$wyn$delimiter\"$value\"";
        
    }
    $wyn=substr($wyn,1);
    $wyn="($wyn)";
    return $wyn;
}
1

Trochę słabo to wygląda. Przede wszystkim wąskim gardłem tu masz zapytanie SQL. Czemu replace u czemu pojedynczo. Zobacz ile będzie trwał insert pojedynczego wiersza a ile wielu wierszy na raz. Pewnie możesz spokojnie i z 1000 ich na raz zapisywać ( o ile pamiętam MySQL miał ograniczenie na ilość danych w MB nie wierszach, więc trzeba by sprawdzić ile taki insert zajmuje).
Samo replace jest też wolniejsze niż insert, Jeśli Twoim celem jest posiadanie unikalnych wierszy, to może jakiś unique na kolumnie.
Inna sprawa to jak nietraktujesz tego pliku jako CSV i robisz złączenie wartości po wycięciu średników to możesz równie dobrze odczytywać go po linii jak zwykły tekstowy plik. Unikniesz w nim szukania danych i zaoszczędzisz jakąś moc obliczeniową.

0

@jurek1980: Za jednym poleceniem jest wpisywane do bazy 10000 rekordów i po drobnych poprawkach bardzo dobrze działa:)) Replace ponieważ całe wpisy będą często odświeżane a nie nie chce za każdym razem wszystkiego kasować. Nie wczytuje pól z CSV ale wczytuje po linijce a to ułatwia sprawę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1