Frage

fopen versagt, wenn ich versuche, in einer sehr mäßig Größe Datei in PHP zu lesen. A 6 meg file macht es zu ersticken, obwohl kleinere Dateien um 100k ganz gut sind. Ich habe gelesen, dass es manchmal notwendig ist PHP mit der -D_FILE_OFFSET_BITS=64 Flagge, um neu zu kompilieren Dateien über 20 Gigs oder etwas lächerlich, zu lesen, aber nicht ich habe keine Probleme mit einer 6 meg-Datei? Schließlich werden wollen wir Dateien lesen in die rund 100 MB sind, und es wäre schön, Lage sein, sie zu öffnen und dann durch sie Zeile für Zeile mit fgets zu lesen, wie ich in der Lage bin mit kleineren Dateien zu tun.

Was sind Ihre Tricks / Lösungen für das Lesen und Operationen auf sehr große Dateien in PHP tun?

Update: Hier ist ein Beispiel für einen einfachen Codeblock, der auf meiner 6 meg-Datei schlägt fehl - PHP scheint nicht einen Fehler zu werfen, es ist einfach falsch zurück. Vielleicht etwas extrem dumm ich tue?

$rawfile = "mediumfile.csv";

if($file = fopen($rawfile, "r")){  
  fclose($file);
} else {
  echo "fail!";
}

Ein weiteres Update: Danke alle für Ihre Hilfe, es hat sich heraus etwas unglaublich dumm sein - ein Berechtigungsproblem. Meine kleine Datei hatte aus unerklärlichen Gründen Berechtigungen lesen, wenn die größere Datei nicht. Doh!

War es hilfreich?

Lösung

Sind Sie sicher, dass es fopen ist, das heißt versagen und Ihr Skript nicht Timeout-Einstellung? Der Standardwert ist in der Regel etwa 30 Sekunden oder so, und wenn Sie Ihre Datei dauert länger als in zu lesen, kann es, dass bis stolpern.

Eine andere Sache zu prüfen, kann die Speichergrenze für Ihr Skript sein -. Die Datei in ein Array lesen kann über diese Reise, so überprüfen Sie Ihre Fehlerprotokoll für Speicherwarnungen

Wenn keine der oben genannten Ihr Problem ist, könnten Sie schauen in mit fgets die Datei lesen in line-by-line, Verarbeitung, wie Sie gehen.

$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle");
if ($handle) {
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        // Process buffer here..
    }
    fclose($handle);
}

Bearbeiten

  

PHP scheint nicht einen Fehler zu werfen, ist es nur der Wert false zurück.

Ist der Pfad korrekt in Bezug auf $rawfile zu dem das Skript ausgeführt wird? Vielleicht versucht einen absoluten Pfad hier für die Dateinamen festlegen.

Andere Tipps

Haben 2 Tests mit einer 1,3 GB-Datei und einer 9.5GB Datei.

1.3 GB

Mit fopen()

Dieses Verfahren verwendet 15555 ms für seine Berechnungen.

Es verbrachte 169 ms in Systemaufrufe.

Mit file()

Dieses Verfahren verwendet 6983 ms für seine Berechnungen.

Es verbrachte 4469 ms in Systemaufrufe.

9,5 GB

Mit fopen()

Dieses Verfahren verwendet 113559 ms für seine Berechnungen.

Es verbrachte 2532 ms in Systemaufrufe.

Mit file()

Dieses Verfahren verwendet 8221 ms für seine Berechnungen.

Es verbrachte 7998 ms in Systemaufrufe.

Es scheint file() schneller ist.

Nun, Sie könnten versuchen, die Funktion Readfile verwenden, wenn Sie nur die Datei ausgegeben werden sollen.

Wenn dies nicht der Fall ist - vielleicht sollten Sie über das Design der Anwendung denken, warum wollen Sie so große Dateien auf Web-Anfragen öffnen

Ich benutzen fopen Videodateien für das Streaming zu öffnen, einen PHP-Skript als Streaming-Video-Server, und ich hatte kein Problem mit Dateien der Größe mehr als 50/60 MB.

• Die fgets() Funktion ist in Ordnung, bis die Textdateien 20 MBytes vergangen und die Parsing-Geschwindigkeit stark reduziert.

• Die file_ get_contents() Funktion gibt gute Ergebnisse bis 40 MBytes und akzeptable Ergebnisse bis 100 MBytes, aber file_get_contents() lädt die gesamte Datei in dem Speicher , so ist es nicht scalabile.

• Die file() Funktion ist katastrophal mit großen Dateien von Text, da diese Funktion ein Array erzeugt jede Textzeile enthält, damit diese Anordnung im Speicher gespeichert ist und der Speicher verwendet wird, ist noch größer.
Eigentlich eine 200 MB-Datei ich nur mit memory_limit Satz auf 2 GB analysieren verwalten können, die für die 1+ GB Dateien ungeeignet war ich analysieren soll.

Wenn Sie Dateien analysieren müssen größer als 1 GB und die Parsing-Zeit überschritten 15 Sekunden und Sie wollen vermeiden, dass die gesamte Datei in den Speicher zu laden, müssen Sie einen anderen Weg finden.

Meine Lösung war auf analysieren Daten in beliebigen kleinen Stücken . Der Code lautet:

$filesize = get_file_size($file);
$fp = @fopen($file, "r");
$chunk_size = (1<<24); // 16MB arbitrary
$position = 0;

// if handle $fp to file was created, go ahead
if ($fp) {
   while(!feof($fp)){
      // move pointer to $position in file
      fseek($fp, $position);

      // take a slice of $chunk_size bytes
      $chunk = fread($fp,$chunk_size);

      // searching the end of last full text line
      $last_lf_pos = strrpos($chunk, "\n");

      // $buffer will contain full lines of text
      // starting from $position to $last_lf_pos
      $buffer = mb_substr($chunk,0,$last_lf_pos);

      ////////////////////////////////////////////////////
      //// ... DO SOMETHING WITH THIS BUFFER HERE ... ////
      ////////////////////////////////////////////////////

      // Move $position
      $position += $last_lf_pos;

      // if remaining is less than $chunk_size, make $chunk_size equal remaining
      if(($position+$chunk_size) > $filesize) $chunk_size = $filesize-$position;
      $buffer = NULL;
   }
   fclose($fp);
}

Der verwendete Speicher ist nur die $chunk_size und die Geschwindigkeit ist etwas kleiner als die mit file_ get_contents() erhalten. Ich denke, PHP Group meinen Ansatz, um es Parsing-Funktionen zu optimieren verwenden sollte.

*) Finden Sie die get_file_size() Funktion hier .

Wenn das Problem durch das Drücken der Speichergrenze verursacht wird, können Sie es einen höheren Wert versuchen Einstellung (dies funktioniert oder nicht, je könnte man auf dem PHP-Konfiguration).

Es wird die Speichergrenze bis 12 Mb

ini\_set("memory_limit","12M");

für mich, fopen() wurde sehr langsam mit Dateien über 1 MB ist file() viel schneller.

Ich versuche nur, Linien 100 zu einem Zeitpunkt, zu lesen und Batch-Einsätze zu schaffen, nimmt fopen() 37 Sekunden vs file() 4 Sekunden dauert. Muss, dass string->array Schritt in file() gebaut sein

Ich würde alle Dateihandhabungsoptionen versuchen, um zu sehen, was in Ihrer Anwendung am besten funktionieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top