Datei ab bestimmter Zeile (mit LImit) auslesen
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
anfang
brauche
code
datei
dateiname
datum
ende
file
header
kopf
lauf
limit
memory
problem
setzen
speichern
start
url
zeiger
zeile
-
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?
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
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 -
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 -
Okay ich habe nicht beachtet das du das offset der Zeilen nicht kennen kannst.
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 -
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 -
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 ?
-
guteseiten schrieb:
Versuch es so:
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 ?<?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. -
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) ??
-
guteseiten schrieb:
Schon richtig, allerdings heißt das nicht, dass die Datei auch als ganzes in den Arbeitsspeicher geladen wird, sondern immer nur teilweise.
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
Das wo du hingegen Probleme bekommen könntest ist mit der Auführungszeit...
Hast du es bereits ausprobiert und hat es dabei nicht funktioniert? -
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
-
guteseiten schrieb:
Du hast 2 Möglichkeiten:
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
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'); ?>
-
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 ?!
-
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 -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage