Peter : Große Dateien aufspringen mit PHP / Shell

Hallo,

ich stehe vor dem Problem das ich zum Zweck der weiteren Bearbeitung mit PHP Dateien (Text/Binär) aufteilen m da ich denke das es besser ist mit PHP 12 x 2MB Daten zu verarbeiten als einmal 24MB.

Hierbei verwende ich derzeit den Shell-Befehl "split" - Aufbau und Aufruf durch PHP (exec).

Die aufzuteilenden Dateien liegen aber nicht in dem gleichen Verzeichnis wie die php Datei, was dazu führt das ich nach der Verwendung von split die erzeugten Dateifragmente wieder verschieben muss da ja der split Befehl leider die Datei aus anderen bzw. Unterverzeichnissen lädt aber die Fragmente auf der Ebene der php-Datei erzeugt.

Meine Fragen sind daher:

  • Ist meine grundsätzliche Herangehensweise korrekt?
  • Gibt es bessere Lösungen
  • Kann ich split dazu bringen in das "richtige" Verzeichnis die Fragmente zu speichern?

Vielen Dank Peter

  1. Lieber Peter,

    da ich denke das es besser ist mit PHP 12 x 2MB Daten zu verarbeiten als einmal 24MB.

    welchen Anlass hast Du zu dieser Überzeugung?

    Welcher Art sind die Dateien und wie "verarbeitest" Du diese?

    Ich bin mir so absolut nicht sicher, dass Du überhaupt irgendetwas splitten musst!

    Liebe Grüße,

    Felix Riesterer.

    1. Hallo nochmal,

      im weiterem Programmablauf muss ich die mir nicht vorher bekannten Dateien wie schon geschrieben weiter bearbeiten (u.a. umwandlung in Hex bein Binär-Dateien, Modifikationen dann innerhalb Hex usw.). Dieses erfolgt durchgängig mit PHP, wobei innerhalb der einzelnen Bearbeitungsschritte die ursprüngliche Datei (bzw. derzeit deren Fragmente) jeweils vollständig in den Speicher geladen werden.

      Die Herangehensweise die Ursprungsdatei aufzusplitten resultiert aus der mir nicht bekannten Dateigröße, lediglich die Maximalgröße ist mit 200 MB vorgegeben. Ich denke das es im Hinblick auf die mir zur verfügung stehenden Systemresourcen sinnvoller ist, nacheinander wie schon geschrieben besser z.B. 80 x 2MB-Dateien zu bearbeiten als einmal 160MB zu laden. Ich habe bzgl. der Bearbeitszeit keine Vorgaben, so das diese kein Kriterium für mich ist.

      VG Peter

      1. Hi,

        im weiterem Programmablauf muss ich die mir nicht vorher bekannten Dateien wie schon geschrieben weiter bearbeiten

        dann gib doch mal ein Beispiel, mit dem es etwas klarer wird.

        (u.a. umwandlung in Hex bein Binär-Dateien, Modifikationen dann innerhalb Hex usw.).

        Das ergibt nämlich keinen Sinn. Dateiinhalte sind nicht in "binär" oder "hex"; das sind nur Formen der Darstellung. Oder ist es Text, der Werte in Binär-Schreibweise darstellt?
        Also wie sehen die Originaldaten aus (kurzer Auszug, bitte), und was soll damit passieren?

        Dieses erfolgt durchgängig mit PHP, wobei innerhalb der einzelnen Bearbeitungsschritte die ursprüngliche Datei (bzw. derzeit deren Fragmente) jeweils vollständig in den Speicher geladen werden.

        Genau da liegt der Hase im Pfeffer. Vollständig in den Speicher laden ist vermutlich gar nicht nötig.

        Ich denke das es im Hinblick auf die mir zur verfügung stehenden Systemresourcen sinnvoller ist, nacheinander wie schon geschrieben besser z.B. 80 x 2MB-Dateien zu bearbeiten als einmal 160MB zu laden.

        Ich denke, dass es im Hinblick auf die Systemressourcen sinnvoller ist, den Dateiinhalt schön linear in kleinen Häppchen zu bearbeiten.

        Ciao,
         Martin

        PS: Wie kommst du bei dem Thema auf die Tags datenbank und menschelei?

        --
        Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
        - Douglas Adams, The Hitchhiker's Guide To The Galaxy
      2. Lieber Peter,

        Die Herangehensweise die Ursprungsdatei aufzusplitten resultiert aus der mir nicht bekannten Dateigröße, lediglich die Maximalgröße ist mit 200 MB vorgegeben.

        Du kannst ein Fragment der Datei in den Arbeitsspeicher einlesen, ohne neue Teildateien anzulegen. Für diesen Zweck kennt PHP eine Menge an passenden Dateifunktionen.

        Ich denke das es im Hinblick auf die mir zur verfügung stehenden Systemresourcen sinnvoller ist, nacheinander wie schon geschrieben besser z.B. 80 x 2MB-Dateien zu bearbeiten als einmal 160MB zu laden.

        Wenn Du damit "in den Arbeitsspeicher laden" meinst, dann stimme ich Dir zu. Aber woher kommt die Notwendigkeit Deines Ursprungspostings? Kennst Du die PHP-Funktionen für das Dateihandling noch nicht? Und warum um Himmelswillen ist Dein Ursprungsposting mit den Tags "Datenbank" und "Menschelei" versehen? Heute ist nicht der erste April!

        Liebe Grüße,

        Felix Riesterer.

      3. Hallo Peter,

        hast Du Dich in PHP (ab Version 5.5) schon einmal mit dem Thema "Generatoren" (klickmich für info) beschäftigt? Es sieht mir nämlich so aus, als könnte deine Aufgabenstellung davon großartig profitieren. Mit Generatoren kann man Verarbeitungspipelines aufbauen, weil nämlich ein Generator B einen Generator A iterieren kann. Vor allem kannst Du das auch dynamisch zusammenstecken.

        Generator 1: File Reader

        Wenn es eine Binärdatei ist: Generator 2: Bin2Hex Konverter, bekommt Generator 1 als Eingabe

        Generator 3: Weitere Verarbeitung, bekommt Generator 1 oder 2 als Eingabe, je nach dem ob Binär oder nicht.

        Nach dem Du deine Generatorkette aufgebaut hast, verarbeitest Du das Ergebnis des letzten Generators mit einer foreach Schleife. PHP kümmert sich darum, dass die einzelnen Generatoren nach Bedarf eine Runde bis zum nächsten yield drehen.

        Auf diese Weise hast Du, je nach dem wieviele Bytes du im Generator 3 gleichzeitig bearbeiten musst, nie mehr als ein paar hundert Bytes im Speicher.

        Rolf

  2. Moin,

    ich stehe vor dem Problem das ich zum Zweck der weiteren Bearbeitung mit PHP Dateien (Text/Binär) aufteilen m da ich denke das es besser ist mit PHP 12 x 2MB Daten zu verarbeiten als einmal 24MB.

    da kann ich mich Felix nur anschließen: Möglicherweise ist das Splitten gar nicht nötig. Es kommt sehr darauf an, was deine Verarbeitung genau ist. Solange du beispielsweise nur linear durch die Dateien wanderst und bestimmte Muster suchst, ist die Dateigröße völlig irrelevant. Wenn du natürlich versuchst, den kompletten Dateiinhalt in den Arbeitsspeicher zu laden ...

    Im Gegenteil, das Splitten kann sogar zusätzliche Probleme mit sich bringen - dann nämlich, wenn gerade ein Muster, das du eigentlich erkennen willst, an der Dateigrenze getrennt wurde.

    Die aufzuteilenden Dateien liegen aber nicht in dem gleichen Verzeichnis wie die php Datei, was dazu führt das ich nach der Verwendung von split die erzeugten Dateifragmente wieder verschieben muss da ja der split Befehl leider die Datei aus anderen bzw. Unterverzeichnissen lädt aber die Fragmente auf der Ebene der php-Datei erzeugt.

    Hast du mal versucht, dem PREFIX-Parameter den gewünschten Zielpfad voranzustellen? Ich nicht, aber es wäre in meinen Augen irgendwie logisch. Notfalls machst du eben vor dem split-Aufruf ein cd.

    • Ist meine grundsätzliche Herangehensweise korrekt?

    Kommt drauf an.

    • Gibt es bessere Lösungen

    Bestimmt. Gibt es fast immer. ;-)

    So long,
     Martin

    --
    Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
    - Douglas Adams, The Hitchhiker's Guide To The Galaxy
  3. Hallo,

    wenn du die Dateien wirklich immer im Speicher hast, teile ich deine Meinung betr. der Aufsplittung - auch bzw. gerade im Hinblick darauf das der belegte Speicher bei sauberer Programmierung nach der Laufzeit sofort wieder frei ist.

    Mit "cd" wirst du nicht weiter kommen, da ein jeder exec-Aufruf eine seperate Shell-Sitzung verwendet. Die Lösung ist aber recht trivial: chdir() ist die Funktion die du suchtst. Wechsel einfach vor Aufruf (exec) per chdir() in das Verzeichnis wo die Dateien liegen, danach dein split...

    PS: Ist übrigens weder DB noch Menschelei :-)

    Gruss Georg

    1. Hi,

      wenn du die Dateien wirklich immer im Speicher hast, teile ich deine Meinung betr. der Aufsplittung - auch bzw. gerade im Hinblick darauf das der belegte Speicher bei sauberer Programmierung nach der Laufzeit sofort wieder frei ist.

      da verstehe ich nicht ganz, was du damit sagen willst.

      Mit "cd" wirst du nicht weiter kommen, da ein jeder exec-Aufruf eine seperate Shell-Sitzung verwendet.

      Klar, aber ein "cd $ziel; split ..." ist nur ein Shell-Aufruf.

      Die Lösung ist aber recht trivial: chdir() ist die Funktion die du suchtst.

      So geht's auch - damit wird das Arbeitsverzeichnis für den gesamten PHP-Prozess geändert.

      PS: Ist übrigens weder DB noch Menschelei :-)

      Das haben Felix und ich auch schon festgestellt. Und über den Begriff aufspringen im Topic habe ich mich auch gewundert, hab's aber nicht weiter kommentiert.

      Ciao,
       Martin

      --
      Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
      - Douglas Adams, The Hitchhiker's Guide To The Galaxy
      1. Nun,

        da der Threadersteller ja nicht rausrücken will, was konkret er mit den Dateien vorhat, gehe ich von folgenden Tatsachen entspr. seiner Posts aus:

        • Die Art und Größe der Dateien ist bis auf die Max-Size von 200 MB unbekannt
        • Er will den Code nicht durchsuchen, sondern "modifizieren" (was und wie immer er damit vorhat)
        • Bei Nicht-Txt will er die Dateien u.a. in einem Hex-Format wandeln (ich vermute bin2hex)
        • Es gibt danach noch mehrere "Arbeitsschritte", wobei die "Dauer" egal ist
        • Er nutzt PHP, was wohl entweder mangels Kenntniss einer Hochsprache oder dem Umstand der Benutzerinteraktion (Browseranwendung) geschuldet ist
        • für den Rest benötige ich meine Glaskugel, die ist aber gerade in der Reinigung...

        Das bedeutet ja für mich:

        • er muss die Datei laden (spätestens bei bin2hex) ist die Datei komplett im Arbeitsspeicher
        • wenn er eine 160MB bearbeiten will, hält PHP die Datei vollständig bis zum Abschluss selbige vor, was zur Folge hat das hier sehr schnell die (Resourcen-)Grenzen erschöpft sein werden.
        • sollte es tatsächlich eine Web-App sein, könnte es ja vorkommen das nicht eine Datei, sondern x Dateien zeitgleich/zeitnah bearbeitet werden sollen (mein Horrerzenario dann: 20 x 200 MB - und das mit PHP)

        Daraus resultiert der für mich logische Schluss besser einzelne kleine Dateihäppchen nacheinander abzuarbeiten als die Systemresourcen mit "Monsterfiles" zuzustopfen.

        Wg. dem Exec: Ja, sofern er zu dem Zeitpunkt des Aufrufs alle benötigten Befehle "zusammen" hat, wäre "cd ... ; befehl1...; befehl2" machbar, aber der TO hat ja nicht gerade mit Informationen um sich geschmissen ;-)

        Ich glaube ich lese abundzu zuviel hier und in anderen Foren und habe die "recht individuelle" Nutzbarkeit der Sprache bei manchen Posts schon so verinnerlicht das ich mir über manche Umstände wie unsinnige Titel, offensichtliche Verwirrung des TO usw. schon gar keine Gedanken mehr mache.

        Gruss Georg

        1. Hallo,

          da der Threadersteller ja nicht rausrücken will, was konkret er mit den Dateien vorhat, gehe ich von folgenden Tatsachen entspr. seiner Posts aus:

          • Die Art und Größe der Dateien ist bis auf die Max-Size von 200 MB unbekannt
          • Er will den Code nicht durchsuchen, sondern "modifizieren" (was und wie immer er damit vorhat)

          Modifizieren impliziert aber meistens ein Durchsuchen, weil man ja die zu modifizierenden Stellen erkennen muss.

          Das bedeutet ja für mich:

          • er muss die Datei laden (spätestens bei bin2hex) ist die Datei komplett im Arbeitsspeicher

          Wieso das? Das kann man auch abschnittweise machen.

          • wenn er eine 160MB bearbeiten will, hält PHP die Datei vollständig bis zum Abschluss selbige vor, was zur Folge hat das hier sehr schnell die (Resourcen-)Grenzen erschöpft sein werden.

          Nicht unbedingt. Originaldatei zum Lesen öffnen, Zieldatei zum Schreiben öffnen, und streamorientiert lesen bzw. schreiben. Damit brauche ich zwar den doppelten Plattenplatz, aber der ist meist nicht der limitierende Faktor. Dafür brauche ich aber nur einen relativ kleinen Puffer im Arbeitsspeicher.

          So long,
           Martin

          --
          Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
          - Douglas Adams, The Hitchhiker's Guide To The Galaxy
          1. Wieso das? Das kann man auch abschnittweise machen.

            • wenn er eine 160MB bearbeiten will, hält PHP die Datei vollständig bis zum Abschluss selbige vor, was zur Folge hat das hier sehr schnell die (Resourcen-)Grenzen erschöpft sein werden.

            Nicht unbedingt. Originaldatei zum Lesen öffnen, Zieldatei zum Schreiben öffnen, und streamorientiert lesen bzw. schreiben. Damit brauche ich zwar den doppelten Plattenplatz, aber der ist meist nicht der limitierende Faktor. Dafür brauche ich aber nur einen relativ kleinen Puffer im Arbeitsspeicher.

            Damit hast du natürlich recht, ich denke das nur der TO weiß was und wie er was machen will. Wenn er wirklich etwas ändern (an definierbaren Positionen) will, käme er sogar nicht darum herum.

            Gruss Georg

  4. Die Verwendung von split() ist unsinnig. Binärdateien enthalten bytes aller wertigkeiten und es ist nicht möglich, ein Zeichen bzw. eine Bytesequenz zu bestimmen an welcher das splitten erfolgen sollte.

    MfG

    1. Hi,

      Die Verwendung von split() ist unsinnig.

      diese Aussage ist unsinnig.

      Binärdateien enthalten bytes aller wertigkeiten und es ist nicht möglich, ein Zeichen bzw. eine Bytesequenz zu bestimmen an welcher das splitten erfolgen sollte.

      Genau deshalb splittet man in einem solchen Fall ja ohne Rücksicht auf den Dateiinhalt an festen, üblicherweise gleichbleibenden Byte-Offsets.

      Ob und wie man die einzelnen Fragmente dann noch sinnvoll verarbeiten kann, steht auf einem anderen Blatt. Es gibt Dateiformate (vor allem im Multimedia-Bereich), bei denen das ohne allzu große Nachteile möglich ist, etwa bei mp3-Dateien. Man würde wahrscheinlich an der Trennstelle einen mp3-Datenblock verlieren, aber der Rest ist noch ohne weiteres abspielbar.

      Und wenn das Splitten gar nur der Zerlegung in "handliche" Brocken dient, spielt die Trennstelle gar überhaupt keine Rolle, weil man die Fragmente hinterher wieder verlustfrei zusammenfügen kann - so wie man das früher gemacht hat, wenn man große Dateien auf mehrere Disketten packen wollte. Erinnert sich noch jemand an die Dinger? ;-)

      So long,
       Martin

      --
      Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
      - Douglas Adams, The Hitchhiker's Guide To The Galaxy
      1. Genau deshalb splittet man in einem solchen Fall ja ohne Rücksicht auf den Dateiinhalt an festen, üblicherweise gleichbleibenden Byte-Offsets.

        Richtig. Aber nicht mit split(), sondern mit einer Funktion die byteorientiert arbeitet.

        MfG

        1. Hi,

          Genau deshalb splittet man in einem solchen Fall ja ohne Rücksicht auf den Dateiinhalt an festen, üblicherweise gleichbleibenden Byte-Offsets.

          Richtig. Aber nicht mit split(), sondern mit einer Funktion die byteorientiert arbeitet.

          von einer PHP-Funktion split() war nie die Rede, sondern vom GNU-Tool split.

          split -b 2M infile part
          

          So long,
           Martin

          --
          Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
          - Douglas Adams, The Hitchhiker's Guide To The Galaxy
        2. Genau deshalb splittet man in einem solchen Fall ja ohne Rücksicht auf den Dateiinhalt an festen, üblicherweise gleichbleibenden Byte-Offsets.

          Richtig. Aber nicht mit split(), sondern mit einer Funktion die byteorientiert arbeitet.

          du meinst, so wie das von OP genannte split?

      2. Hallo,

        Und wenn das Splitten gar nur der Zerlegung in "handliche" Brocken dient, spielt die Trennstelle gar überhaupt keine Rolle, weil man die Fragmente hinterher wieder verlustfrei zusammenfügen kann - so wie man das früher gemacht hat, wenn man große Dateien auf mehrere Disketten packen wollte. Erinnert sich noch jemand an die Dinger? ;-)

        Disketten? Ich habe die Teile geliebt! Endlich keine blödsinnigen Tapes mehr spulen, keine schmerzenden Finger vom manuellen Wickeln, herrlich! Die großen konnte man zudem sehr gut als Frisbee-Ersatz nutzen, auch bei heißen Sommertagen als Ersatz- bzw. Ventilationshilfe sehr gut zu gebrauchen. Die kleinen waren dagegen im Winter einfach Top wenn mal wieder kein Eiskratzer zur Hand war oder der blöde Deckel von der Kassettenhülle mal wieder abgebrochen ist und schmerzhaft in der Hand steckte...

        BTW.: Wenn ich eine Datei unabhängig des Inhaltes in gleichgroße Häppchen aufteilen will, dann ist split wohl doch die richtige Wahl.

        Gruss Georg

        1. Hi,

          Erinnert sich noch jemand an die Dinger? ;-)

          Disketten? Ich habe die Teile geliebt! Endlich keine blödsinnigen Tapes mehr spulen, keine schmerzenden Finger vom manuellen Wickeln, herrlich!

          die Tape-Ära habe ich nur noch mit dem C64 miterlebt (mit handelsüblichen Compact-Cassetten), aber selbst da konnte ich mir relativ bald ein Diskettenlaufwerk leisten.

          Die großen konnte man zudem sehr gut als Frisbee-Ersatz nutzen, auch bei heißen Sommertagen als Ersatz- bzw. Ventilationshilfe sehr gut zu gebrauchen.

          Mit "groß" meinst du die 8"-Floppies? *fg*

          Die kleinen waren dagegen im Winter einfach Top wenn mal wieder kein Eiskratzer zur Hand war oder der blöde Deckel von der Kassettenhülle mal wieder abgebrochen ist und schmerzhaft in der Hand steckte...

          Auf die Idee bin ich nie gekommen. Aber in den Jahren, als sowohl 5¼"- als auch 3½"-Disketten noch populär waren, habe ich das größere Format vorgezogen. 1.44MB passte auf beide (auch wenn das bei 5¼" nicht üblich war), aber die größeren hatten eine Reihe von Vorteilen:

          • höhere Datensicherheit durch geringere Datendichte (gleiche Datenmenge auf fast doppelter Fläche)
          • weniger Platzbedarf im Schrank durch die ultradünne Form
          • ein Häufchen 5¼"-Disketten macht wesentlich weniger Lärm, wenn's mal runterfällt

          So long,
           Martin

          --
          Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
          - Douglas Adams, The Hitchhiker's Guide To The Galaxy
          1. Mit "groß" meinst du die 8"-Floppies? *fg*

            Beide ;-), ging mit der 8 natürlich besser (mehr Luft) als mit der 5.25 aber es ging :-)

            ...habe ich das größere Format vorgezogen. 1.44MB passte auf beide (auch wenn das bei 5¼" nicht üblich war)

            1,44 auf einer 5.25? Ich dachte immer da war bei 1,2 Schluss (man lernt nie aus)

            • höhere Datensicherheit durch geringere Datendichte (gleiche Datenmenge auf fast doppelter Fläche)
            • weniger Platzbedarf im Schrank durch die ultradünne Form
            • ein Häufchen 5¼"-Disketten macht wesentlich weniger Lärm, wenn's mal runterfällt

            Stimmt eindeutig, allerdings konnte man mit den 3,5ern besser auf kurzer Distanz (Schreibtisch -> Türrahmen in der der Chef steht) treffen und dank der komprimierten Masse war der Effekt besser...

            Wenn ich mir so den Text durchlese, merke ich wie alt ich doch bin :-()

            Gruss Georg

            1. Hi,

              ...habe ich das größere Format vorgezogen. 1.44MB passte auf beide (auch wenn das bei 5¼" nicht üblich war)

              1,44 auf einer 5.25? Ich dachte immer da war bei 1,2 Schluss (man lernt nie aus)

              Ja, 1.20MB war das Standardformat auf 5¼", aber 1.44MB ging auch noch gerade so. Die 3½"-Disks konnte man sogar bis 1.68MB "pimpen". Usache für den Unterschied ist, dass die 3½"-Disks mit 5 Umdrehungen/sec (300/min) rotierten, die 5¼"-Scheiben aber mit 6 Umdrehungen/sec (360/min). So war eine Spur bei gleichem Bit-Takt zeitlich um 1/6 kürzer.

              Ich habe damals (noch unter DOS) eine Zeitlang mit diversen Non-Standard-Formaten experimentiert. Interessanterweise hat DOS sich standhaft geweigert, solche Sonderformate zu erzeugen; wenn sie dann aber mit anderen Tools (notfalls selbstgeschriebenen) mal existierten, konnte DOS problemlos damit umgehen, weil sämtliche Geometriedaten im Parameterblock (Sektor 0) standen.

              Und Microsoft war zu der Zeit hinterhältig: Word für Windows 2.0 (AFAIR) wurde damals noch auf Disketten als Installationsmedium ausgeliefert, weil CDs im Computerbereich noch selten waren. Microsoft hat allerdings, um Disketten zu sparen, die Disks mit 1.68MB formatiert. Zum Installieren war das gar kein Problem. Allerdings haben sie im Handbuch gleich im ersten Kapitel auch empfohlen, von den Installationsdisketten Sicherheitskopien zu machen. Aber kein Wort darüber, mit welchem Programm es überhaupt möglich war, solche Sonderformate zu kopieren.
              Eins der wenigen war damals das Shareware-Tool VGA-Copy.

              Wenn ich mir so den Text durchlese, merke ich wie alt ich doch bin :-()

              "Je älter man wird, desto besser war man früher."
               - Janine Kunze

              So long,
               Martin

              --
              Nothing travels faster than the speed of light with the possible exception of bad news, which obeys its own special laws.
              - Douglas Adams, The Hitchhiker's Guide To The Galaxy