Ankündigung

Einklappen
Keine Ankündigung bisher.

StreamWriter

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • StreamWriter

    Falls dies nicht der passende Thread sein sollte bitte ich einen Mod, es entsprechend zu verschieben.
    -----------------------------------------------------

    Ich arbeite gerade an einem StreamWriter in PHP, also an einer Klasse die es einem leicht machen sollte Daten in Dateien abzulegen und anschließend mit dem entsprechenden Gegen-Klasse dem StreamReader wieder auszulesen.

    Derzeit arbeite ich an der StreamWriter-Klasse und da ich doch noch einiges im Thema Klassen und Fileoperationen lernen muss würde ich doch gerne mal von euch wissen, was ihr zu meiner jetzigen Klasse sagt.

    Vorallem würde mich interessieren wo es Verbesserungsbedarf Design-, bzw Codetechnisch gibt und was die Klasse eventuell noch für Methoden/ Attribute benötigt um in der "realen Welt" wirklich Anwendung finden zu können.

    Danke im Voraus. Mfg Tera3yte

    PHP-Code:
    class StreamWriter
    {
        private 
    $filename "";
        private 
    $handle NULL;
        
        public function 
    __construct(string $filenamebool $clearfile TRUE)
        {
            
    $this->filename $filename;
            
            if(
    $clearfile)
            {
                
    $this->handle fopen($filename'w');
            }
            else
            {
                
    $this->handle fopen($filename'a');
            }
        }
        
        public function 
    writeLine($datachar $splitter ';'bool $splitterAsLastChar FALSE)
        {
            
    $write "";
            
            if(
    is_array($data))
            {
                for(
    $i 0$anz count($data); $i $anz$i++)
                {               
                    
    $write .= $data[$i];
                    
                    if((
    $i+!== $anz) || ($i+=== $anz && $splitterAsLastChar))
                    {
                        
    $write .= $splitter;
                    }
                }
            }
            else
            {
                
    $write $data;
            }

            return 
    $this->write(PHP_EOL $write);
        }
        
        public function 
    write(string $data)
        {
            if(
    fwrite($this->handle$data))
            {
                return 
    TRUE;
            }
            
            return 
    FALSE;
        }
        
        public function 
    getHandle()
        {
            return 
    $this->handle;
        }
        
        public function 
    getFilename()
        {
            return 
    $this->filename;
        }

    - Laravel

  • #2
    dann fangen wir mal an
    PHP-Code:
    public function __construct(string $filenamebool $clearfile TRUE
    es wäre zu schön, leider hat aber PHP keine typehints für strings/bools etc, hack hat es und spätere versionen von PHP werden es kriegen, aktuell würde die klasse einfach nicht funktionieren

    PHP-Code:
           if($clearfile)... 
    statt eines parameters würde ich einfach nur prüfen, exestiert die datei? dann schreibe rein, wenn nicht erstelle eine, ein $forceCreate parameter würde aber auch nicht schaden

    PHP-Code:
        public function writeLine($datachar $splitter ';'bool $splitterAsLastChar FALSE
    was ist splitter? zeilenende? wieso dann ;? und nicht \n oder \r\n je nach dem welches OS
    PHP-Code:
     for($i 0$anz count($data); $i $anz$i++) 
    warum for und nicht foreach?
    PHP-Code:
     return $this->write(PHP_EOL $write); 
    an der stelle killst du die Performance von fwrite, der vorteil von fwrite ist ja dass du zeile für zeile reinschreibst und den speicher freigibst, du musst dir nicht den ganzen string merken, da hättest du genauso gut file_put_contents nutzen können statt fwrite.

    wie dem auch sei php hat bereits eine Klasse um dateien verändern zu können

    http://de2.php.net/splfileobject

    Viele Grüße
    apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

    Kommentar


    • #3
      Das ist kein PHP. PHP kennt keine Typehints für primitve Datentypen und Klassen können es nicht sein.

      Sowas bringt PHP aber auch schon von Haus aus mit: http://php.net/manual/en/class.splfileobject.php

      *edit*
      @BlackScorp $clearfile macht mehr. Wenn die Datei existiert legt das fest ob überschreiben oder angehangen wird. "an der stelle killst du die Performance von fwrite". Da ist eher das Gegenteil der Fall. Es macht ein Unterschied ob du für jedes Byte ein Schreibzugriff ausführst oder erst sammelst.

      Kommentar


      • #4
        @erc ich würde sagen es kommt auf die größe des inhalts an. ich meine fwrite ist deshalb sinnvoll da man nicht den gesamten text speichern muss. ich glaube speicher wird dadurch auf jeden fall gespart.

        oder fwrite ist einfach nur eine alte methode und file_put_contents ist neuer und eigentlich besser und fwrite wird nur benutzt weil man es anders nicht kennt..
        apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

        Kommentar


        • #5
          Zitat von tera3yte Beitrag anzeigen
          Ich arbeite gerade an einem StreamWriter in PHP, also an einer Klasse die es einem leicht machen sollte Daten in Dateien abzulegen und anschließend mit dem entsprechenden Gegen-Klasse dem StreamReader wieder auszulesen.
          Darf man fragen warum? In der PHP-Welt gibts Stream-Wrapper (hässliche(s) API, aber nunmal so eine Art Standard), SPLFileObject (mit Read-und-Write in einem) und diverse Userland-Klassen die Lesen von und Schreiben in Streams "mehr objektorientiert" abbilden:

          * http://www.phpclasses.org/package/82...f-streams.html
          * http://www.phpclasses.org/package/72...o-Java-IO.html
          * https://github.com/reactphp/stream/tree/master
          * https://github.com/hoaproject/File
          * https://github.com/guzzle/streams
          * irgendwo im Umfeld von php.de oder php-resource.de gabs auch den Versuch eines standardisierten StreamFile-Interfaces (ich finde nur den Link nicht mehr).


          Wenn du als Grund "Erkenntnisgewinn" anführst, ist das natürlich okay.

          Derzeit arbeite ich an der StreamWriter-Klasse und da ich doch noch einiges im Thema Klassen und Fileoperationen lernen muss würde ich doch gerne mal von euch wissen, was ihr zu meiner jetzigen Klasse sagt.

          Vorallem würde mich interessieren wo es Verbesserungsbedarf Design-, bzw Codetechnisch gibt und was die Klasse eventuell noch für Methoden/ Attribute benötigt um in der "realen Welt" wirklich Anwendung finden zu können.
          API-Ideen findest du (neben den oben schon genannten Klassen) hier: https://github.com/mikey179/vfsStream/wiki

          Wie du schon erklärt bekommen hast, nützt dir ein string-Typehint wenig, um die Existenz einer Datei festzustellen. Auch is_file(), is_writable(), e.t.c. helfen dir nur eingeschränkt weiter. Du arbeitest (höchstwahrscheinlich ) in einer Multitaskingumgebung. Da kann eine Datei, die eben noch da war, kurz darauf schon wieder weg sein. Gleiches gilt für Zugriffsrechte. Einfacher ist, den Rückgabewert von fopen() zu prüfen. Wenn der keine Stream-Ressource ist, kannst du, um dem Aufrufer einen Gefallen zu tun, diverse Prüfungen vornehmen und die Resultate in die Fehlermeldung einbauen.

          Außerdem hat es sich als nützlich erwiesen, alle Dateioperationen per flock() abzusichern (Lesend: LOCK_SH, Schreibend: LOCK_EX). Und bei schreibendem Zugriff auf die Datei vor dem Aufheben des Locks bitte einmal mit fflush() nachspülen.

          Du musst auch den Dateipfad nicht extra speichern. Die Stream-Ressource rückt ihn auf Anfrage heraus.

          Prinzipiell könnte das etwa so aussehen:

          PHP-Code:
          class FileSystemError extends Exception {
          }

          class 
          AccessDeniedError extends FileSystemError {
          }

          class 
          FileSystem {
              static function 
          error($path) {
                  if (!
          is_file($path)) {
                      return 
          file_exists($path)
                          ? 
          'path "%s" does not represent a file' // directory e.t.c.
                          
          'path "%s" does not exist';
                  }
                  if (!
          is_writable($path)) {
                      return 
          'writing to "%s" not allowed';
                  }
                  return 
          'whatever'// race condition?
              
          }
          }


          class 
          SimpleFileWriter {

              
          // for people who don't like exceptions ...
              
          static function open($path$reset_file false) {
                  try {
                      return new 
          self($path$reset_file);
                  }
                  catch (
          FileSystemError $ex) {
                  }
                  return 
          null;
              }

              protected 
          $stream null/// stream resource

              
          function __construct(
                  
          $path,
                  
          $reset_file false
              
          ) {
                  
          $fopen_mode $reset_file 'wb' 'ab';

                  
          // @ prevents stupid warnings
                  
          if (!is_resource($this->stream = @fopen((string) $path$fopen_mode))) {
                      throw new 
          FileSystemError(sprintf(FileSystem::error($path), $path));
                  }
                  if (!
          flock($this->streamLOCK_EX)) {
                      throw new 
          AccessDeniedError('Locking failed');
                  }

              }

              function 
          __destruct() {
                  
          fflush($this->stream); // write stream buffers to file
                  
          flock($this->streamLOCK_UN);
                  
          fclose($this->stream);
              }

              function 
          meta() {
                  return (object) 
          stream_get_meta_data($this->stream);
              }

              function 
          path() {
                  return 
          $this->meta()->uri;
              }

              function 
          write($data) {
                  
          // wie man das korrekt mit einem aussagekraeftigen Rueckgabewert
                  // implementiert, wuerde den Rahmen dieses Postings sprengen
                  
          throw new ErrorTodo('implement me stupid!');
              }

              function 
          writef(
                  
          // $fmt
                  // ...$args
              
          ) {
                  
          $args func_get_args();
                  return 
          vfprintf($this->streamarray_shift($args), $args);
              }

              
          // ...


          Dein ->writeLine() erschließt sich mir nicht so ganz. Wo wird dieses Konzept mit $splitter usw. angewendet? Interessant ist, dass du den Zeilentrenner vor den Zeileninhalt schreibst. Das kann zu Problemen führen, wenn andere Schreibfunktionen nach ->writeLine() aufgerufen werden, da dann deren Daten in der vorherigen Zeile landen. Gibts Gründe für diese Reihenfolge?

          ->getHandle() sehe ich als kritisch an. Wenn du die Stream-Resource direkt nach außen gibst, kann der Aufrufer damit diversen Unsinn anstellen, wie die Datei schließen, das Locking aufheben, den Seek-Pointer verstellen, ...
          Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

          Kommentar


          • #6
            Zitat von BlackScorp Beitrag anzeigen
            @erc ich würde sagen es kommt auf die größe des inhalts an. ich meine fwrite ist deshalb sinnvoll da man nicht den gesamten text speichern muss. ich glaube speicher wird dadurch auf jeden fall gespart.
            Damit hast du auf jedenfall Recht, aber die Funktion fwrite() ist auch nicht kostenlos. Wenn du aller paar Bytes diese Funktion aufrufst wird das teuerer sein als wenn du die Zeile auf einmal schreibst.

            Zitat von fireweasel Beitrag anzeigen
            Dein ->writeLine() erschließt sich mir nicht so ganz. Wo wird dieses Konzept mit $splitter usw. angewendet?
            Sieht nach einer "alternative" zu fputcsv() aus.

            Zitat von fireweasel Beitrag anzeigen
            Interessant ist, dass du den Zeilentrenner vor den Zeileninhalt schreibst. Das kann zu Problemen führen, wenn andere Schreibfunktionen nach ->writeLine() aufgerufen werden, da dann deren Daten in der vorherigen Zeile landen.
            Das ist die Kompromisslösung die nix taugt. Bei einer bestehenden Datei hast du entweder einen Zeilenumbruch zuviel oder zu wenig, bei einer neuen ein zuviel am Anfang.

            Kommentar


            • #7
              Zitat von BlackScorp Beitrag anzeigen
              dann fangen wir mal an
              PHP-Code:
              public function __construct(string $filenamebool $clearfile TRUE
              Das mit den Typehints weiß ich, habe diese nur für meine IDE reingeschrieben um mir ein paar Sekunden Schreibarbeit an anderer stelle zu sparen, hab leider vergessen sie wieder zu entfernen

              @fireweasel

              Ja, ich mache das ausschließlich um meine Kenntnisse im Thema PHP und OOP zu verbessern. Leider habe ich nämlich das Problem das ich mich Berufstechnisch viel mit dem Thema PHP und Webentwicklung auseinander setzen muss und leider der einzige bin der einigermaßen Ahnung in diesem Bereich hat und mir eben alles selbst beibringen muss, da keiner im Betrieb je mit PHP gearbeitet hat.

              Zitat von fireweasel Beitrag anzeigen

              PHP-Code:
              class FileSystemError extends Exception {
              }

              class 
              AccessDeniedError extends FileSystemError {
              }

              class 
              FileSystem {
                  static function 
              error($path) {
                      if (!
              is_file($path)) {
                          return 
              file_exists($path)
                              ? 
              'path "%s" does not represent a file' // directory e.t.c.
                              
              'path "%s" does not exist';
                      }
                      if (!
              is_writable($path)) {
                          return 
              'writing to "%s" not allowed';
                      }
                      return 
              'whatever'// race condition?
                  
              }

              Dieses Code-Sample finde ich noch interessant, was hat es mit dem %s auf sich? Ich gehe stark davon aus das $path dort eingetragen wird, hättest du einen Seite wo ich mich damit mal vertraut machen könnte? Welche Vorteile es zum Beispiel bringt?
              - Laravel

              Kommentar


              • #8
                Zitat von erc Beitrag anzeigen
                Sieht nach einer "alternative" zu fputcsv() aus.
                Dann wäre der Name ->writeLine() irreführend und etwas wie ->writeRecord(), ->writeCSV() ... besser. Wobei ich solche Spezialitäten in einer einfachen Stream-Writer-Klasse weglassen würde. Die kann man einer abgeleiteten Klasse einbauen.

                Zitat von tera3yte Beitrag anzeigen
                Ja, ich mache das ausschließlich um meine Kenntnisse im Thema PHP und OOP zu verbessern. Leider habe ich nämlich das Problem das ich mich Berufstechnisch viel mit dem Thema PHP und Webentwicklung auseinander setzen muss und leider der einzige bin der einigermaßen Ahnung in diesem Bereich hat und mir eben alles selbst beibringen muss, da keiner im Betrieb je mit PHP gearbeitet hat.
                Mein Beileid.

                ..., was hat es mit dem %s auf sich? Ich gehe stark davon aus das $path dort eingetragen wird, hättest du einen Seite wo ich mich damit mal vertraut machen könnte? Welche Vorteile es zum Beispiel bringt?
                http://docs.php.net/manual/en/function.sprintf.php
                Es gibt noch ein paar weitere Mitglieder der ...printf...-Familie. Die findest du auch im PHP-Handbuch. Ob es Vorteile bringt, weiß ich jetzt nicht. Ich wollte nur nicht in jeden if-Zweig sprintf() reinschreiben ... Da schien mir das halbwegs passend. Aber wenn es elegantere Lösungen gibt, hab ich kein Problem damit.
                Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

                Kommentar


                • #9
                  Zitat von fireweasel Beitrag anzeigen
                  Mein Beileid.
                  Danke Ich hoffe also ich belästige euch nicht all zu sehr mit meinen Fragen und eventuell schlecht programmierten Sachen

                  Zitat von fireweasel Beitrag anzeigen

                  http://docs.php.net/manual/en/function.sprintf.php
                  Es gibt noch ein paar weitere Mitglieder der ...printf...-Familie. Die findest du auch im PHP-Handbuch. Ob es Vorteile bringt, weiß ich jetzt nicht. Ich wollte nur nicht in jeden if-Zweig sprintf() reinschreiben ... Da schien mir das halbwegs passend. Aber wenn es elegantere Lösungen gibt, hab ich kein Problem damit.
                  Danke dafür
                  - Laravel

                  Kommentar


                  • #10
                    Bist du sicher, dass das php ist und nicht hack?

                    Kommentar

                    Lädt...
                    X