kostenloser Webspace werbefrei: lima-city


Datei ab bestimmter Zeile (mit LImit) auslesen

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    kataloge

    kataloge hat kostenlosen Webspace.

    Hallo

    ich habe eine .txt Datei mit sehr vielen Zeilen

    wie kann ich die Daten ab einer bestimmten Zeile (mit Limit = 100) auslesen

    also so, dass ich je Aufruf nicht die komplette Datei einlesen muss
    sondern z.B. ab Zeile 101 bis Zeile 200 ... oder ab Zeile 201 bis Zeile 300 ... etc.

    Wenn ich versuche die komplette Datei in ein Array zu lesen,
    und erst dann in Teile zu zerlegen dann reicht der Speicher nicht aus ...
    ---> Allowed memory size of 67108864 bytes exhausted

    gibt es eine Möglichkeit beim Datei-Auslesen für "starte bei Zeile n" ??
    das Ende (Limit) ist dann ja kein Problem mit Zähler und break();

    wie setze ich den "Zeiger" genau an den Anfang einer bestimmten Zeile?
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. u***e

    Du kannst mit fseek() den Datenzeiger, den du z.B. mit fopen() erzeugt hast, an deine gewünschte
    Anfangsposition verschieben und ab diesen Punkt die Daten, mit fgets() und der gewünschten Länge, lesen.

    fseek(): http://www.php.net/manual/de/function.fseek.php
    fgets(): http://www.php.net/manual/de/function.fgets.php

    Der Blick ins Manual ist sehr hilfreich. ;D

    Okay, das ganze wie oben beschrieben in einer Funktion ... ^^
    file_get_contents(): http://www.php.net/manual/de/function.file-get-contents.php

    Beitrag zuletzt geändert: 5.11.2011 13:38:24 von umble
  4. Autor dieses Themas

    kataloge

    kataloge hat kostenlosen Webspace.

    ja, das Prinzip ist genau was ich brauche

    aber wie bekommr ich die Zeiger-Position von z.B. Anfang der Zeile 101 ... oder Zeile 201 ... etc. ?

    also doch erstmal die ganze Datei durchgehen,
    alle 100 Zeilen den Zeiger "zwischenspeichern" (in eine info-textdatei)
    und dann könnte ich mit den Zeigern arbeiten

    $datei = 'datenliste.txt'; 
    
    $fpo = fopen($datei, "r");  
    
    $zeigerdaten = ''; 
    $zeilen = 0; 
    while($line = fgets($fpo, 128)) {   // ---- Quelldatei Zeilen gekützt einlesen 
    $zeilen++;  // ---- Zaehler erhoehen (neue Zeile) 
    
    if ($zeilen == 100) {   // ---- Zaehler Limit erreicht 
    
    // ---- ? ... Zeiger am Anfang dieser Zeile ermitteln ?? .... ftell() ... ? 
    
    $zeigerdaten .= $zeigerwert.'|';   // ---- Zeiger-Wert in String mit Trenner ablegen  
    $zeilen = 0;   // ---- Zaehler zuruecksetzen 
    }
    
    }
    
    $zeigerdaten = rtrim($zeigerdatenm'|'); 
    
    $zinfo = 'zeigerinfo.txt'; 
    $fpz = fopen($zinfo, "w"); 
    fwrite($fpz,$zeiger.'|');



    Zeiger am Anfang dieser Zeile ermitteln ?? .... ftell() .
    ftell() von WAS ? ... von $fpo ?? ... Anfang der Zeile ?


    und dann zum Lesen der Daten auf Seiten (je Seite 100 Zeilen)

    $zeiger_string = file_get_contents($zinfo); 
    $zeiger_array = explode('|',$zeiger_string); 
    $zeiger_anzahl = count($zeiger_array); 
    
    // --- Seiten blaettern ... Auslesen mit fseek() aus Werte in $zeiger_array


    so ungefähr, aber ich bekomms nicht hin (Zeiger an Zeilenanfang alle 100 Zeilen)


    EDIT: ok, mit file_get_contents() kann ich dann auch die eigentlichen Daten mit Zeiger-Pos lesen
    aber dazu brauche ich ja zuerst einmal die Zeiger-Positionen alle 100 Zeilen ... ?!



    Beitrag zuletzt geändert: 5.11.2011 14:24:23 von kataloge
  5. u***e

    Okay ich habe nicht beachtet das du das offset der Zeilen nicht kennen kannst. :shy:
    Ohne diesen Datenzeigerkram ist es natürlich auch machbar. ^^

    $FileHandle = fopen('datenliste.txt', 'r');
        $Zaeler1    = 1;
        $Start      = 5;    //Start bei Zeile x
        $Stop       = 100;  //Ende bei Zeile x
        $Daten      = '';
    
        //Bis Dateiende oder Stop
        while($Zaeler1 <= $Stop && !feof($FileHandle)){
            $Zeile = fgets($FileHandle);    //Zeile einlesen
    
            if($Zaeler1 >= $Start){
                $Daten .= $Zeile;           //Zeile anhängen
            }
    
            ++$Zaeler1;
        }

    Die Schleife läuft bis zu $Stop oder bis zum Dateiende durch.
    Wenn der Zähler über $Start ist beginnst du erst die Zeilen zu speichern,
    bzw. mehrere Zeilen zu speichern.

    Beitrag zuletzt geändert: 5.11.2011 17:16:52 von umble
  6. Autor dieses Themas

    kataloge

    kataloge hat kostenlosen Webspace.

    Ja, gute Idee

    gleich beim Einlesen alle 100 Zeilen eine neue Sub-Datei speichern

    ich hoffe mal, dass das keine Probleme macht mit Memory-Limit oder Script-Laufzeit
    weil dazu muss ich ja doch alle Zeilen der grossen Datei komplett auslesen
    und dann auch noch (alle x Zeilen) inneue Datei Speichern

    deshalb hatte ich ja die Idee, jede Zeile nur ein paar Zeichen auslesen
    while($line = fgets($fpo, 64)) { ... }
    und den Zeiger vom Anfang jeder 100sten Zeile zwischen zu speichern

    Frage mich aber gerade, ob ich beim Lesen von nur paar Zeichen je Zeile
    überhaupt auf den richtigen zeiger kommen kann, gwenn dann brauche ich ja
    die Position des letzten \n (Zeilenumbruch) alle 100 Zeilen
    denn ein Zeichen für "Zeilenanfang" gibt es soweit ich weiss garnicht, oder?

    habe Deinen Code mal getestet und ein paar Änderungen gemacht

    als Funktion (noch ausbaufähig)

    <?php 
    // ------------------------------------------------- 
    
    function getSubFiles ($quelldatei, $z=100, $csvhead=false) { 
    
    $FileHandle = fopen($quelldatei, 'r');
    
    $zcount  = 0;        // Zeilen-Zaehler
    $fcount  = 1;        // Datei-Zehler 
    $zlimit  = $z;       // Zeilen Limit pro Datei 
    $savedir = 'data";   // Speicher-Verzeichnis
    
    $sub_Datei = $savedir.'/subdaten_'.$fcount.'.txt';  // ---- Erste Sub-Datei 
    $HandleSub = fopen($sub_Datei, 'w', 0666);
    
    if ($csvhead === true) { 
    $kopf = fgets($FileHandle, 2048); 
    fwrite($HandleSub,$kopf); // ---- Kopf-Zeile schreiben 
    } 
    
    	while($line = fgets($FileHandle, 2048)) { 
    	
    	$zcount++;  // --- neue Zeile 
    	$rest = ($zcount % $zlimit); 
    
    		if ($rest == 0) { 
    		
    		fclose($HandleSub);  // ---- Alte Sub-Datei schliessen 
    		$fcount++; 
    		
    		$sub_Datei = $savedir.'/subdaten_'.$fcount.'.txt';  // ---- Neue Sub-Datei 
    		## echo "<br /> ... neue Datei: <strong>".$sub_Datei."</strong> \r\n"; 
    		$HandleSub = fopen($sub_Datei, 'w', 0666);
    		
    		if ($csvhead === true) { 
    		fwrite($HandleSub,$kopf); // ---- Kopf-Zeile schreiben 
    		}
    	
    		}
    	
    	fwrite($HandleSub,$line); // ---- Zeile in Sub-Datei schreiben 
    	
    	}
    
    fclose($HandleSub); // ---- Letzte Sub-Datei schliessen 
    fclose($FileHandle);
    
    $out = array($zcount,$fcount); 
    
    return $out; 
    
    }
    
    // ------------------------------------------------- 
    
    
    
    /* ---------------
    * 
    *   Drei (3) Parameter bei Funktion: getSubFiles
    * 
    *   Parameter1  =  Quell-Datei (filename / Dateiname) 
    *   Parameter2  =  Zeilen pro Sub-Datei (int / Zahl) 
    *   Parameter3  =  CSV Daten Kopf-Zeile (true oder false) 	
    * 
    ------------- */
    
    
    $qdatei = 'datenlsite.txt'; 
    $zeilen = 100; 
    
    $erg = getSubFiles($qdatei, $zeilen, true); 
    
    echo "<br /> Gesamt ".$erg[0]." Zeilen. \r\n"; 
    echo "<br /> Gesamt ".$erg[1]." Sub-Dateien. \r\n"; 
    
    
    // ------------------------------------------------- 
    ?>


    wenn dritter Parameter TRUE ist, dann wird die erste Zeile aus der Quelldatei
    in jede SubDatei auch als erste Zeile geschrieben (für. CSV Daten)


    aber wie gesagt vermute ich, dass dies bei sehr grossen Datein
    wegen Memory-Limit oder Script-Laufzeit zu Problemen (Abbruch) kommt



    Beitrag zuletzt geändert: 5.11.2011 21:15:15 von kataloge
  7. kataloge schrieb:
    aber wie gesagt vermute ich, dass dies bei sehr grossen Datein
    wegen Memory-Limit oder Script-Laufzeit zu Problemen (Abbruch) kommt


    Hallo, das Script funktioniert zwar (prinzipiell), aber nicht für gro0e Datei
    ich habe genau das Problem, das du angesprochen hast

    habe sogar unabhängig von Deiner Funktion ein sehr ähnlich arbeitendes Script geschrieben,
    aber bei sehr großen CSV-Dateien bekomme ich immer Memory Error

    Meine Version ist quasi das gleiche wie Deine Funktion: (nur nicht als Funktion)

    <?php
    // ---------------------------------------------------------
     
    ini_set('display_errors','on');
    error_reporting(E_ALL);
     
    header("Content-Type: text/html; charset=utf-8");
     
    // -----------------------------------------------------------
    
    $c_path = 'data';   	// --- ohne Slash / am Ende 
    $c_name = 'bestand2012'; 
    $c_file = $c_path.'/_'.$c_name.'.csv'; 
    
    // ------------- To-Do: Update CACHE --------------- 
    
    $csvsource = $c_file; 	// --- Pfad und Dateiname der Quell-Datei
    $debuginfo = false; 	// --- Debug-Ausgabe on (true) oder off (false)
    $csvheader = true; 		// --- die CSV hat eine Kopfzeile mit Spalten-Namen
    $max_fsize = 50; 		// --- max. Anzahl Daten-Zeilen je Sub-Datei 
    
    // ------------------------------------------------------------
    
    $rnum = 0; 		// --- Zeilen Zähler
    $fnum = 0; 		// --- Datei Zähler
    
    $handle_read = @fopen($csvsource, "r");    // --- Quell-Datei zum Lesen öffnen ----
    
    if ($handle_read) { 
     
    if ($csvheader) { 
      $headrow = fgets($handle_read);   // --- Kopf-Zeile einlesen ----
    }
    else {
      $headrow = '';
    }
     
    // -------------------------------------------------- 
    
    while (($buffer = fgets($handle_read)) !== false) {
    	
    	$rmax = ($rnum % $max_fsize);
    
    	if ($rmax == 0) {  	// --- Start neue Sub-Datei 
    		$fnum++; 		// --- Datei Zähler 
    		
    		if (isset($handle_write)) { fclose($handle_write); }   	// --- alte Sub-Datei schliessen 
    		$sub_file = $c_path.'/_'.$c_name.'_sub_'.$fnum.'.csv'; 	// --- Dateiname neue Sub-Datei 
    		$handle_write = @fopen($sub_file, "w+", 0666);     		// --- neue Sub-Datei erstellen 
    		
    		echo "<br />NEW SUB FILE: <strong>".$sub_file."</strong>\n";
    		echo "<br />\n";
    		
    		$entry = $headrow.$buffer;  	// --- erster Eintrag in neue Sub-Datei 
    	}
    	else {
    		$entry = $buffer;  				// --- weitere Zeile Eintrag in Sub-Datei 
    	}
    	
    	fwrite($handle_write,$entry);   	// --- neuer Eintrag in Sub-Datei schreiben ---- 
    
    ######### DEBUG INFO #########
    
    	if ($debuginfo) { 
    		$inrow = ($rnum - ($fnum*$max_fsize) + $max_fsize);
    		echo "<br />Sub ID Nummer: ".$fnum." \n";
    		echo "<br />Sub File-Name: ".$sub_file." \n";
    		echo "<br />Gesamt Zeilen: ".($rnum+1)." \n";
    		echo "<br />Interne Zeile: ".($inrow+1)." \n"; 
    		
    		print "<pre style=\"margin:0px 0px 0px 10px; padding:6px; background:#DEDEDE;\">\n";
    		print_r($entry);
    		print "</pre>\n";
    	}
    
    #########
    
    $rnum++; 	// --- Zeilen Zähler 
    
    }
     
    // -------------------------------------------------- 
    
    if (!feof($handle_read)) {
    echo "<p>Fehler ... unerwartetes Ende</p>\n";
    }
     
    fclose($handle_read);
    }
    else {
    echo "<p>Fehler ... kann Datei nicht lesen</p>\n";
    }
     
    // -------------------------------------------------- 
    
    fclose($handle_write);  // --- letzte Sub-Datei schliessen ----
    
    // -------------------------------------------------- 
    
    echo "<br />\n";
    echo "<br />\n";
    echo "<br />Anzahl Sub-Files: ".$fnum."\n";
    echo "<br />\n";
    
    
    echo "<ol>\n";
    
    for ($x=1; $x<=$fnum; $x++) {
    	$sname = $c_path.'/_'.$c_name.'_sub_'.$x.'.csv';
    	echo "<li><a href=\"".$sname."\" target=\"_blank\">".$sname."</a></li>\n";
    }
     
    echo "</ol>\n";
    
    
    echo "<br />\n";
    echo "<br />\n";
    
    
    // ---------------------------------------------------------
    ?>



    gibt es eine andere Möglichkeit, um eine große Datei in in mehrere kleinere Dateien aufzuteilen
    aber nicht mitten in der Zeile abschneiden, sondern immer Zeilen "ganz" lassen ?

    habe es mit Datei-Zeiger aisprobiert, so dass nach 100 KB eine neue Datei angelegt wird
    (und aus der großen Datei jeweils dann wieder erst ab diesem Zeiger gelesen wird)
    das geht zwar, aber so werden Zeilen "abgeschnitten" und ist daher für CSV nicht brauchbar

    oder wie kann ich den Datei-Zeiger so setzen,
    dass er alle (max.) 100 KB aber immer am (direkt nach) Zeilenumbruch gesetzt wird ?

    geht das überhaupt? .. bzw. andere (Speicher-sparende) Methode,
    um eine große Datei in mehrere kleine aufzuteilen, ohne Zeilen abzuschneiden ?
    ... jemand ne Idee ?

  8. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    guteseiten schrieb:
    gibt es eine andere Möglichkeit, um eine große Datei in in mehrere kleinere Dateien aufzuteilen
    aber nicht mitten in der Zeile abschneiden, sondern immer Zeilen "ganz" lassen ?
    Versuch es so:
    <?php
    header('content-type: text/plain');
    
    $limit = 32; // Zeichen / Datei
    
    $file = fopen('file.txt', 'rt');
    
    $filebase = 'file_%d.txt'; // Dateiname
    $nextfile = 0;
    
    $content = '';
    
    echo('splitting files...');
    while(!feof($file)) {
    	$content .= fgets($file);
    	if(strlen($content) > $limit) {
    		$filename = sprintf($filebase, $nextfile++);
    		file_put_contents($filename, $content);
    		$content = '';
    	}
    }
    echo(' done');
    ?>
    Das spaltet dir die große Datei 'file.txt' in kleinere Dateien auf, die maximal $limit Bytes groß sein sollten. Wenn allerdings eine Zeile länger ist wird sie komplett noch in die Datei geschrieben, was in einer Datei resultiert, die etwas größer als das eingestellte Limit ist.
  9. ja Danke
    das ist auch gut und deutlich schlanker als meine bisherigen Versionen

    ABER ... das Problem großer Dateien bleibt dabei bestehen, (Memory Limit)
    weil durch while(!feof($file)) wird ja auch wieder immer die ganze Datei in einem Lauf behandelt

    Daher nochmal genauere Beschreibung der Idee mit dem Datei-Zeiger setzen (fseek)

    die Datei nicht im ganzen auszulesen, sondern (je Script-Lauf) nur Teile davon
    und jeder Script-Lauf durch META-REFRESH neu starten, damit Script-Laufzeit ausreicht

    nach dem öffnen den Dateizeiger setzen, z.B. bei 3000 Zeilen
    Lauf 1: Dateizeiger an Beginn Zeile 1 setzen und bis Ende Zeile 1000 lesen
    Lauf 2: Dateizeiger an Beginn Zeile 1001 setzen und bis Ende Zeile 2000 lesen
    Lauf 3: Dateizeiger an Beginn Zeile 2001 setzen und bis Ende Zeile 3000 lesen

    wenn ich die Script-Läufe mit header("Location:....") neu starte, dann kommt Laufzeit-Fehler
    daher die Idee per META-REFRESH und GET-Werte den Script-Lauf neu starten


    also wenn Limit erreicht, dann Wert von Zeiger ftell() und Wert neue Datei-Nummer
    per GET übergeben (Seite neu laden mit Meta-Refresh)
    damit im nächsten Script-Lauf direkt ab dem Zeiger (mit fseek) weiter gelesen werden kann

    ... $zeiger = ftell($file) wenn limit erreicht ... $zeiger übergabe (GET) ... lesen ab fseek($zeiger)
    leider bekmme ich das nicht hin, die Datei-Zeiger sind immer falsch
    ?

    PS:

    Wenn die Quell-Datei in utf-8 ist, muss ich dann nicht Zeichen mit mb_strlen() zählen ?!
    if( mb_strlen($content, 'utf8') > $limit ) { ...


    $limit = 1024; ist doch 1 KB, oder ?! .. für 300 KB dann (1024*300) ??

  10. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    guteseiten schrieb:
    ABER ... das Problem großer Dateien bleibt dabei bestehen, (Memory Limit)
    weil durch while(!feof($file)) wird ja auch wieder immer die ganze Datei in einem Lauf behandelt
    Schon richtig, allerdings heißt das nicht, dass die Datei auch als ganzes in den Arbeitsspeicher geladen wird, sondern immer nur teilweise.

    Das wo du hingegen Probleme bekommen könntest ist mit der Auführungszeit...

    Hast du es bereits ausprobiert und hat es dabei nicht funktioniert?
  11. habe es ausprobiert,
    bis z.B. 10 MB klappt es damit gut, aber ich brauche es bis ca. 37 MB (ja, ist viel)
    damit kommt Fehler: Fatal error: Maximum execution time of 20 seconds exceeded

    deshalb brauche ich was, das nach z.B. 8 MB die Seite neu aufruft (Meta-Refresh)
    und ab dem letzten Dateizeiger aus vorherigem Lauf (ab Zeilen-Anfang) weiter macht

    Problem ist auch noch, in jede Sub-Datei auch die CSV-Kopfzeile einzufügen
    das habe das jetzt so gelöst:

    $quelle = 'big_file.csv';  
    
    $csvheader = true; 
    
    if ($csvheader && empty($headrow)) { 
      $handle_kopf = @fopen($quelle, "r");
      $headrow = fgets($handle_kopf); 
      fclose($handle_kopf);
    }
    else { 
      $headrow = '';
    }


    und mit der Kopf-Zeile ändert sich ja auch sie Länge von $content (ab Sub-Datei Nr. 2)
    also dann in der while() Schleife so

    ausserdem setze ich oben $nextfile = 1; ... damit die erste Datei die Nr: 1 hat (nicht 0)

    $limit = (1024*500);  // --- 500 KB 
    $file = fopen($quelle, 'rt');
    $filebase = 'file_%d.txt'; // Dateiname
    $nextfile = 1;
     
    $content = '';
    
    echo "<ol>\n";
    
    while(!feof($file)) {
    
        if ($csvheader && $nextfile != 1) { // ---- Länge mit Kopf-Zeile (ab Datei Nr.2) 
              $golimit = ($limit + mb_strlen($headrow, 'utf8'));
              } 
    		  else { $golimit = $limit; }
    		  
        $content .= fgets($file);
    	
        if(mb_strlen($content, 'utf8') > $golimit) { 
            $filename = sprintf($filebase, $nextfile++);
            echo " <li>SUB-FILE: ".$filename."</li>\n";
            file_put_contents($filename, $content);
    // ---- Content mit CSV Kopfzeile (ab Datei Nr.2) 
            if ($csvheader) { $content = $headrow; } else { $content = ''; }
        }
    }
     
    echo "</ol>\n";



    Problem ist, wie ich das mit dem Dateizeiger hinbekomme,
    um die 37 MB Datei in z.B. 37 Dateien a ca. 1 MB zu splitten (inkl. der Kopf-Zeile)
    (oder 74 Dateien mit je ca. 500 KB)

    Wenn ich die Quell-Datei von externem Server hole (http)
    kann man da überhaupt den Dateizeiger setzen (fseek) ???
    oder geht sowas dann besser mit curl
  12. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    guteseiten schrieb:
    bis z.B. 10 MB klappt es damit gut, aber ich brauche es bis ca. 37 MB (ja, ist viel)
    damit kommt Fehler: Fatal error: Maximum execution time of 20 seconds exceeded
    Du hast 2 Möglichkeiten:
    1) du gibst dem Script eine längere Laufzeit
    2) du machst das mit den meta-redirects

    So funktioniert stückweises Spalten, das kannst du dir anpassen wie du willst, jetzt kommt ein Link auf den du drücken dafst:
    <?php
    
    $limit = 32; // Zeichen / Datei
    
    $file = fopen('file.txt', 'rt');
    $filebase = 'file_%d.txt'; // Dateiname
    $nextfile = 0;
    
    if(isset($_GET['start']) && isset($_GET['id'])) {
    	fseek($file, $_GET['start']);
    	$nextfile = $_GET['id'];
    }
    
    $content = '';
    
    echo('splitting files...');
    while(!feof($file)) {
    	$content .= fgets($file);
    	if(strlen($content) > $limit) {
    		$filename = sprintf($filebase, $nextfile++);
    		file_put_contents($filename, $content);
    		$content = '';
    		if(!feof($file)) {
    			echo('<a href="' . $_SERVER['PHP_SELF'] . '?start=' . ftell($file) . '&id=' . $nextfile . '">continue</a>');
    			exit();
    		}
    	}
    }
    
    echo(' done');
    ?>
  13. Super, Danke

    ich hatte es auch (so ähnlich) mit ftell und fseek ausprobiert,
    aber bei mir hat das irgendwie nicht geklappt, jetzt geht's :)

    und anstatt Link zum Klicken ist es ja kein Problem das als Meta-Refresh zu machen

    und ich habe es jetzt doch wieder so gemacht, dass jede Sub-Datei
    als Limit die Anzahl der (Daten-) Zeilen hat, anstatt Dateigröße in Byte
    (das Byte-Limit ist nur auskommentiert, kann man leicht ändern)

    mein Script sieht jetzt also so aus:

    <?php
    // --------------------------------------------------------- 
    
    ini_set('display_errors','On'); 
    error_reporting(E_ALL);
    
    header("Content-Type: text/html; charset=utf-8");
    
    header("Cache-Control: no-store, no-cache, must-revalidate");
    header("Cache-Control: post-check=0, pre-check=0", false);
    header("Pragma: no-cache");
    
    $cachefile = 'data/_bestand2012.csv'; 
    
    ## $limit = (1024*500);  // ---- max Größe in Byte pro Datei 
    
    $zeilen = 1000;    // ---- max Daten-Zeilen pro Datei 
    
    $csvheader = true; 
    
    // ----------------------------------------------------------- 
    
    function csv_to_array($csvurl,$length=0,$delimiter=";",$enclosure="\"",$csvhead=true) {
    
    $csvdata = array(); 
    $ReadHandle = fopen($csvurl, 'r');
    
    if ($csvhead === true) { 
    	$headrow = fgetcsv($ReadHandle, $length, $delimiter, $enclosure); 
    } 
    
    while($line = fgetcsv($ReadHandle, $length, $delimiter, $enclosure)) { 
    	
    	if ($csvhead === true) { 
    		foreach ($headrow as $key=>$heading) {
    		$row[$heading] = (isset($line[$key])) ? $line[$key] : '';
    		}
    		$csvdata[] = $row;
    	} 
    	else { 
    		$csvdata[] = $line;	
    	} 
    		
    }
    fclose($ReadHandle);
    
    return $csvdata; 
    
    }
    
    // ----------------------------------------------------------- 
    
    function show_testdata($filename, $details=0) { 
    	
    	$csvurl = $filename; 
    	$length = 0; 
    	$delimiter = ";"; 
    	$enclosure = "\""; 
    	$csvhead = true; 
    	
    	$testdata = csv_to_array($csvurl,$length,$delimiter,$enclosure,$csvhead); 
    	
    	$tanz = count($testdata); 
    	
    	print "<h2>".$filename."</h2>\n"; 
    	print "<p>Anzahl: ".$tanz."</p>\n"; 
    	
    	if ($details == 1) { 
    	print "<hr />\n"; 
    	print "<pre>\n"; 
    	print_r($testdata); 
    	print "</pre>\n"; 
    	print "<hr />\n"; 
    	}
    
    }
    
    
    // ----------------------------------------------------------- 
    
    
    if ($csvheader === true) { 
    $handle_kopf = @fopen($cachefile, "r");
    $headrow = fgets($handle_kopf); 
    fclose($handle_kopf);
    }
    else { 
    $headrow = '';
    }
    
    ## print "<pre>\n"; 
    ## print_r($headrow); 
    ## print "</pre>\n"; 
    
    
    
    // ----------------------------------------------------------- 
    
    
    if (!empty($_GET['id'])) { 
    
    $file = fopen($cachefile, 'rt');
    
    $filebase = 'data/_'.$listid.'_sub_%d.csv'; // Sub-File Dateiname
    
    // ------------------------------------------------------- 
    
    
    ## $content = '';
    				
    // ---- Content mit CSV Kopfzeile (ab Datei Nr.2) 
    if ($csvheader && $_GET['id'] != 1) { $content = $headrow; } else { $content = ''; } 
    
    // ------------------------------------------------------- 
    
    $nextfile = 1;
    
    if(isset($_GET['start']) && isset($_GET['id'])) {
        fseek($file, $_GET['start']);
        $nextfile = $_GET['id'];
    }
    
    // ------------------------------------------------------- 
    
    
    $z=0; 
    
    while(!feof($file)) {
    
    if ($csvheader === true && $nextfile != 1) { // ---- Länge mit Kopf-Zeile (ab Datei Nr.2) 
    ## $golimit = ($limit + mb_strlen($headrow, 'utf8'));
       $gozeile = ($zeilen - 1); 
    } 
    else { 
    ## $golimit = $limit; 
       $gozeile = $zeilen; 
    }
    
        $content .= fgets($file);
    	$z++; 
    	
    ## if(mb_strlen($content, 'utf8') > $golimit) { 
       if($z > $gozeile) { 
       
    	$filename = sprintf($filebase, $nextfile++);
    	
    	echo "<br />\n";
    	echo "<br />SUB-FILE: ".$filename."\n";
    	
    	file_put_contents($filename, $content);
    	
    	$fsize = filesize($filename); 
    	$fsize_kb = round($fsize / 1024, 2); 
    	$fsize_mb = round($fsize / 1048576, 2); 
    	
    	echo "<br />Size: ".$fsize." Byte --- ".$fsize_kb." KB --- ".$fsize_mb." MB \n";
    	
    	
    	if(!feof($file)) { 
    		  $url2nextid = '' . $_SERVER['PHP_SELF'] . '?start=' . ftell($file) . '&id=' . $nextfile . ''; 
    		
    		  ## echo('<br /> NEXT: <a href="' . $url2nextid . '">continue ID:'.$nextfile.'</a>'."\n");
    		  echo('<meta http-equiv="refresh" content="0.2; URL=' . $url2nextid . '">'."\n");
    		
    		  show_testdata($filename,'0'); 	// --- ohne Details, nur Anzahl der Zeilen 
    		  ## show_testdata($filename,'1');  	// --- mit Detail-Ausgabe der Daten ... langsamer!!!
    		  exit();
    		}
    		
    	} 
    	// --- Ende if LIMIT ---
    	
    } 
    // --- Ende while !feof ---
    
    
    if(feof($file)) { 
    echo("<br /> Fertig ... Gesamt: <strong>".($nextfile-1)."</strong> Sub-Files erstellt. <a href=\"" . $_SERVER['PHP_SELF'] . "\">HOME</a>\n");
    exit();
    }
    
    fclose($file); 
    
    
    // ------------------------------------------------------- 
    
    echo "<br />\n";
    echo "<br />\n";
    echo "<br /> done \n";
    echo "<br />\n";
    
    
    }
    else { 
    echo "<br />\n";
    echo "<br /> START: <a href=\"" . $_SERVER['PHP_SELF'] . "?start=0&id=1\">continue ID:1</a>"."\n";
    echo "<br />\n";
    }
    
    
    echo "<br />\n";
    echo "<br />\n";
    echo "<br />\n";
    
    
    
    // ------------------------------------------------------- 
    ?>


    und es funktioniert :)

    aber vielleicht hat ja jemand noch Verbesserungs-Vorschläge oder findet einen Bug ?!

  14. z***********n

    guteseiten schrieb:
    und es funktioniert :)


    nicht ganz, die letzte Sub-Datei wird so nicht mit Sicherheit erstellt !!!

    anstatt so:
    ## if(mb_strlen($content, 'utf8') > $golimit) {
       if($z > $gozeile) {


    muss es so:
    ## if(feof($file) || mb_strlen($content, 'utf8') > $golimit) {
       if(feof($file) || $z > $gozeile) {


    weil es nicht sicher ist, dass die Zeilen genau aufgehen,
    also die letzte Sub-Datei hat sehr wahrscheinlich weniger als das Limit pro Datei

    daher muss man auch "schreiben" wenn Datei-Ende (feof) erreicht ist,
    also bei letzter Sub-Datei auch dann, wenn das Limit noch nicht erreicht ist

    Beispiel:

    Wenn Du 325 Zeilen hast und ein Limit von 100 Zeilen pro Sub-Datei
    dann werden 3 Sub-Dateien geschrieben
    aber die 4. Datei (mit nur 25 Zeilen) soll ja auch erstellt werden
    und mit if($z > $gozeile) { ... } wird im 4. Durchlauf diese Bedingung ja nie erreicht
    weil ja nur noch 25 Zeilen übrig sind, daher auch bei feof schreiben ....
    :)


    Beitrag zuletzt geändert: 14.6.2012 10:01:36 von zimmerbrunnen
  15. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!