Avatar billede axel21 Juniormester
14. april 2009 - 11:33 Der er 20 kommentarer og
1 løsning

Hjælp til håndtering af stor fil

Hej,


jeg har efter lidt søgen gravet dette umiddelbare fantastiske script op på internettet.


SCRIPT.PHP
<?
$read_chars = ($_GET['read_chars'] == "") ? 0 : $_GET['read_chars']; //Current position in file
$num_of_lines = 10; //Number of lines to read

$handle = fopen("cvrfil/csvfil.csv");
if($handle) {
    $read_lines = 0;
    while(!feof($handle) && ($read_lines < $num_of_lines)) {
        fseek($handle, $read_chars);
        $line = fgets($handle);
        $read_chars += strlen($line);
        $user = explode(";", $line);
        $read_lines++;
    }
}
fclose($handle);
?>

REDIR.PHP
<?php
$read_chars = $_GET['read_chars'];
$redir = "script.php?read_chars=".$read_chars;
?>
<html>   
<head>       
<meta http-equiv="refresh" content="0; URL=<?php echo $redir; ?>">   
</head>
<body>
</body>
</html>



Mit spørgsmål går på at jeg skal indsætte noget SQL fra et eksisterende script, men det vil ikke rigtigt virke for mig, så håber at der er nogle kloge menesker der vil give et råd eller to ;-)

MIT SCRIPT:

<?php

include "connect.php";

$read_chars = ($_GET['read_chars'] == "") ? 0 : $_GET['read_chars']; //Current position in file
$num_of_lines = 1000; //Number of lines to read

if($handle) {   
$read_lines = 0;   


$import = mysql_query("SELECT cvr FROM virksomheder WHERE cvr > '0'");
   
while($row = mysql_fetch_array($import))
{

$handle = fopen("cvrfil/csvfil.csv");


while ($data = fgetcsv($handle, 10000000, ";"))
{


if($data[1] == $row[cvr])
{
      $import1="INSERT into virksomhederfracvr(cvrnr,pnr,navn,navn1,adresse,bynavn,postnr,postdist,region,kommunenavn,antalansatte,virkform,virkstartdato,branchenr,branchetekst,telefon,telefax,email) values('$data[1]','$data[2]','$data[3]','$data[4]','$data[7]','$data[8]','$data[11]','$data[12]','$data[15]','$data[17]','$data[32]','$data[34]','$data[39]','$data[42]','$data[46]','$data[49]','$data[50]','$data[51]')";
      mysql_query($import1) or die(mysql_error());


while(!feof($handle) && ($read_lines < $num_of_lines)) {       
fseek($handle, $read_chars);       
$line = fgets($handle);       
$read_chars += strlen($line);       
$user = explode(";", $line);       
$read_lines++;   
}}}

}
}
fclose($handle);

$redir = "redir.php?read_chars=".$read_chars;
header("Location: $redir");

?>
Avatar billede axel21 Juniormester
14. april 2009 - 12:38 #1
Meningen er at jeg vil tjekke en fil igennem efter bestemte cvr numre, hvis disse findes oploades disse i databasen. Men da min csv fil er temmelig stor, får jeg timeout, og dette skulle kunne undgås med ovenstående script. Jeg har prøvet med max_execution_time og det hjælper ikke tilstrækkeligt.
Avatar billede jakobdo Ekspert
14. april 2009 - 14:29 #2
Hvor stor er filen ?
Jeg har tidligere arbejdet med en text fil på 12mb, uden problemer.
Men det kommer meget ang på opsætningen af serveren selvfølgelig.

Måske din timeout kan snydes, ved at lave noget output og flush() undervejs (eller ofte)
Avatar billede axel21 Juniormester
14. april 2009 - 14:33 #3
Den er på hele 402 mb, den er så stor så jeg har kun set indholdet af filen et par gange i notepad! Så alle forslag er velkomne.

Har forsøgt mig med denne

<Files arraytest.php>
php_value max_execution_time "900"
php_value upload_max_filesize "500M"
php_value post_max_size "500M"
php_value max_input_time "200"

</Files>
Avatar billede jakobdo Ekspert
14. april 2009 - 14:41 #4
Hvad er din memory_limit på ?
Hvis filen allerede er på din server, så er upload som sådan ligemeget.
Avatar billede axel21 Juniormester
14. april 2009 - 14:45 #5
Ja du har ret, det er som sådan heller ikke upload der ikke virker, jeg har filen på min server, den er lagt op med ftp, så langt så godt. Men jeg har et script der skal køre et check på ca. 1.6 mil linier kode, og inden den er færdig med at process scriptet så timer sriptet ud, det er en kæmpe stor .csv fil der er tale om.

Jeg har et script der virker fint, men kun med meget mindre csv filer, da disse ikke timer ud.

<?
include "connect.php";
echo '<LINK href="../default.css" type="text/css" rel="stylesheet">';

if(isset($_POST['kor']))

{

mysql_query("DELETE FROM virksomhederfracvr");


$import = mysql_query("SELECT cvr FROM virksomheder WHERE cvr > '0'");
   
while($row = mysql_fetch_array($import))
{


$handle = fopen("cvrfil/csvfil.csv", "r");

while ($data = fgetcsv($handle, 10000000, ";"))
{



if($data[1] == $row[cvr])
{
      $import1="INSERT into virksomhederfracvr(cvrnr,pnr,navn,navn1,adresse,bynavn,postnr,postdist,region,kommunenavn,antalansatte,virkform,virkstartdato,branchenr,branchetekst,telefon,telefax,email) values('$data[1]','$data[2]','$data[3]','$data[4]','$data[7]','$data[8]','$data[11]','$data[12]','$data[15]','$data[17]','$data[32]','$data[34]','$data[39]','$data[42]','$data[46]','$data[49]','$data[50]','$data[51]')";
      mysql_query($import1) or die(mysql_error());
 
echo "Jubii";

}



}

}


    fclose($handle);
    print "<span class='green'>Import færdig, lukker om 5 sekunder</span>";

 
}


?>



<form enctype="multipart/form-data" action="arraytest.php" method="POST">
<input type="submit" value="Kør script" name="kor"/>
</form>
Avatar billede jakobdo Ekspert
14. april 2009 - 14:52 #6
Det optimale måtte jo være, at få alle numrene flyttet over i en mysql tabel.
Så burde du langt hurtigere kunne søge ja.

Fandt du ud af hvad: memory_limit var på din boks ?
Avatar billede axel21 Juniormester
14. april 2009 - 14:57 #7
Ja, men som du måske kan se i scriptet, er jeg kun intresseret i ca. 2000 linie af hele filen, derfor forstillede jeg mig at det var nemmer at sortere dem fra, inden data blev lagt ind, dvs. i en operation.

Med hensyn til memory_limit så må jeg melde pas, hvor ser jeg dette?
Avatar billede jakobdo Ekspert
14. april 2009 - 15:00 #8
<?php
phpinfo();
?>
Der bør du kunne se det.
Avatar billede axel21 Juniormester
14. april 2009 - 15:05 #9
Der står 24m
Avatar billede jakobdo Ekspert
14. april 2009 - 15:13 #10
Og så kan du se at der er problemer med 402mb fil. :o)
Men kan du ikke bruge din kode fra dit første indlæg ?
Den læser jo små bider.
Og så vil det jo bare være at indsætte data i en tabel.
Hvilket format står dine data i ?
Avatar billede axel21 Juniormester
14. april 2009 - 15:23 #11
De er i kommasep CSV fil, jo jeg ville gerne bruge koden fra første indlæg, men den virker ikke helt. :-)
Avatar billede jakobdo Ekspert
14. april 2009 - 15:26 #12
Hvad mener du med det ikke virker ?
Og jeg er med på kommasep csv.
men snakker vi:

firmanavn_1;cvr_nummer_1;adresse_1;osv...
firmanavn_2;cvr_nummer_2;adresse_2;osv...
eller
cvr_nummer1;cvr_nummer2;cvr_nummer3;osv... ?
Avatar billede axel21 Juniormester
14. april 2009 - 15:33 #13
Det med det ikke virker, er det script jeg selv har forsøgt mig med at klistre sammen, ud fra det script jeg fandt på nettet. http://www.simon-jensen.net/haandtering-af-store-filer-i-php.html

firmanavn_1;cvr_nummer_1;adresse_1;osv...
firmanavn_2;cvr_nummer_2;adresse_2;osv...
Avatar billede jakobdo Ekspert
14. april 2009 - 15:39 #14
Hvad med at bruge scriptet:

SCRIPT.PHP
<?
$read_chars = ($_GET['read_chars'] == "") ? 0 : $_GET['read_chars']; //Current position in file
$num_of_lines = 10; //Number of lines to read

$handle = fopen("cvrfil/csvfil.csv");
if($handle) {
    $read_lines = 0;
    while(!feof($handle) && ($read_lines < $num_of_lines)) {
        fseek($handle, $read_chars);
        $line = fgets($handle);
        $read_chars += strlen($line);
        $user = explode(";", $line);
        $read_lines++;
    }
}
fclose($handle);
?>

REDIR.PHP
<?php
$read_chars = $_GET['read_chars'];
$redir = "script.php?read_chars=".$read_chars;
?>
<html> 
<head>     
<meta http-equiv="refresh" content="0; URL=<?php echo $redir; ?>"> 
</head>
<body>
</body>
</html>

til at indsætte alle data fra den store fil, i en database/tabel og når det er gjort, så lave søgningen i databasen/tabellen fremover ?
Avatar billede axel21 Juniormester
14. april 2009 - 15:49 #15
Det var også den oprindelige ide, men det virker bare mere logisk for mig, at sortere alle de spild data fra inden disse kommer ind i databasen.

Man kan jo sige, at mit script jo virker fint, det sortere dem fra og sætter kun dem ind der skal ind, men det timer out før at alt er sorteret, så der kommer jo data ind, bare ikke alt. Derfor er jeg også intresseret i den løsning, da det jo "kun" skal kunne køre længere det script jeg allerede har lavet!
Avatar billede jakobdo Ekspert
14. april 2009 - 20:27 #16
Hvad hvis du prøver at lave en echo '.'; flush();, der hvor du udlæser data fra den store fil ?
Kan det måske omgå timeout ?
Avatar billede axel21 Juniormester
15. april 2009 - 19:53 #17
Hmm, har prøvet med din flush() der, i forskellige versioner, men der hjælper ikke rigtigt.

if($data[1] == $row[cvr])
{
      $import1="INSERT into virksomhederfracvr(cvrnr,pnr,navn,navn1,adresse,bynavn,postnr,postdist,region,kommunenavn,antalansatte,virkform,virkstartdato,branchenr,branchetekst,telefon,telefax,email) values('$data[1]','$data[2]','$data[3]','$data[4]','$data[7]','$data[8]','$data[11]','$data[12]','$data[15]','$data[17]','$data[32]','$data[34]','$data[39]','$data[42]','$data[46]','$data[49]','$data[50]','$data[51]')";
      mysql_query($import1) or die(mysql_error());
 
echo '.'; flush();

}

Andre forslag.?
Avatar billede jakobdo Ekspert
15. april 2009 - 20:02 #18
Du kan evt. prøve at kontakte mig på msn:
jakobdo [snabel-a] hotmail {punktum} com
Måske jeg kan finde ud af noget, hvis jeg får direkte adgang...
Avatar billede axel21 Juniormester
02. juli 2010 - 21:58 #19
Smid et svar, ellers bliver tråden lukket...
Avatar billede jakobdo Ekspert
03. juli 2010 - 07:12 #20
Svar!
Avatar billede jakobdo Ekspert
03. juli 2010 - 09:33 #21
Takker for point
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester