Ankündigung

Einklappen
Keine Ankündigung bisher.

Buffer

Einklappen

Neue Werbung 2019

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

  • Buffer

    Gibt es in PHP eine Möglichkeit, alleine aufgrund eines übergebenen Strings zu ermitteln, aus wie vielen Bytes ein Zeichen besteht?

    Es geht darum, dass ich einen StreamBuffer geschrieben habe (Klasse BufferedOutputStream):

    PHP-Code:
    <?php
       error_reporting
    (~0);
       
       interface 
    Flushable
       
    {
          function 
    flush();
       }
       
       interface 
    OutputStream
       
    {
       }
       
       abstract class 
    FilteredOutputStream implements OutputStream
       
    {
          protected 
    $target;
       }
       
       class 
    BufferedOutputStream extends FilteredOutputStream implements Flushable
       
    {
          private 
    $size;
          private 
    $buffer '';
          
          
    /**
           * @param OutputStream $target
           * @param int $size PHP_INT_MAX / 2 > size > 0 in Byte
           */
          
    function __construct(OutputStream $target$size 1024)
          {
             if(
    $size PHP_INT_MAX 2)
                throw new 
    Exception('size');
                
             
    $this->target $target;
             
    $this->size $size;
          }
          
    /**
           * @param string $data
           * @throws Exception Aktueller Buffer + $data sprengen die Buffergröße.
           */
          
    function write($data)
          {
             
    $sizeBuffer strlen($this->buffer);
             
    $sizeData strlen($data);
             
             
    // Beispiel:
             //    Jedes Byte wird durch ein x dargestellt.
             //    Der Buffer hat hier max. 5 Bytes:
             //       xxxxx|xxxxx
             //       ++---
             //    + zeigt an, wie viel vom Buffer bereits belegt ist ($sizeBuffer).
             //    - zeigt den freien Platz vom Buffer an ($this->size - $sizeBuffer).
             //    Daneben gibt es weitere 5 x.
             //    $data darf diese 5 x plus den - Stellen lang sein, dann kann
             //    $data korrekt gespeichert bzw. zum Teil oder vollständig mit den + Stellen
             //    an write weitergericht werden.
             
             
    if($sizeData $this->size $sizeBuffer)
                throw new 
    Exception('data');
                
             if(
    $sizeBuffer $sizeData $this->size)
             {
                
    // Buffer auffüllen
                
    $this->buffer.= $data;
             }
             else
             {
                
    // Alte Bufferdaten und neuen Daten schreiben. Ev. einen Teil von data buffern.
                
    $len $this->size $sizeBuffer;
                
    $this->target->write($this->buffer.substr($data0$len)); // Buffer + forderen data-Teil schreiben
                
    $this->buffer substr($data$len); // Rest von data buffern
             
    }
          }
          
    /**
           * Reicht flush weiter.
           */
          
    function flush()
          {
             if(
    $this->buffer != '')
             {
                
    $this->target->write($this->buffer);
             }
          }
          
    /**
           * Liefert die Buffergröße.
           * @return int
           */
          
    function size()
          {
             return 
    $this->size;
          }
       }
       
       class 
    DataOutputStream extends FilteredOutputStream implements Flushable // Dummy-Datei zum Testen
       
    {
          
    /**
           * @param OutputStream $target
           */
          
    function __construct(OutputStream $target)
          {  
             
    $this->target $target;
          }
          
    /**
           * @param int $data
           */
          
    function write($data)
          {
             
    $this->target->write((string)$data);
          }
          function 
    flush()
          {
             
    $this->target->flush();
          }
       }
       
       class 
    ScreenOutputStream implements OutputStream // Dummy-Datei zum Testen
       
    {
          
    /**
           * @param string $data
           */
          
    function write($data)
          {
             echo 
    $data;
          }
       }
       
       
    $sout = new ScreenOutputStream(); // Ausgabe auf Bildschirm
       
    $bout = new BufferedOutputStream($sout5); // buffern
       
    $dout = new DataOutputStream($bout); // int -> string
       
    $dout->write(12);
       echo 
    'x';
       
    $dout->write(3456);
       echo 
    'x';
       
    $dout->flush();
    ?>
    In der Buffer-Klasse arbeite ich mit substr, also auf Byte-Ebene. Jetzt weiß ich aber nicht, bei welchem Byte ich schneiden darf. Das hängt vom Zeichensatz ab.

    Kann mir wer weiterhelfen?


  • #2
    Verwende [MAN]mb_substr[/MAN]?

    Kommentar


    • #3
      In BufferedOutputStream gebe ich in size die Anzahl der Bytes (nicht Zeichen) an. Wie muss denn dann der mb_substr-Befehl zum Unterteilen lauten?

      Kommentar


      • #4
        edit: nvm, verlesen

        http://php.net/manual/en/function.mb-strlen.php für die Stringlänge
        Relax, you're doing fine.
        RTFM | php.de Wissenssammlung | Datenbankindizes | Dateien in der DB?

        Kommentar


        • #5
          Ich glaube, jetzt ist mir die Lösung eingefallen. Brauch doch nur strlen / mb_strlen rechnen, dann weiß ich, aus wie vielen Bytes 1 Zeichen besteht, oder?

          Kommentar


          • #6
            Zitat von veryhot Beitrag anzeigen
            dann weiß ich, aus wie vielen Bytes 1 Zeichen besteht, oder?
            Je nach Zeichenkodierung gibt es aber keine feste Länge pro Zeichen.
            Zitat von nikosch
            Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

            Kommentar


            • #7
              Zitat von veryhot Beitrag anzeigen
              Ich glaube, jetzt ist mir die Lösung eingefallen. Brauch doch nur strlen / mb_strlen rechnen, dann weiß ich, aus wie vielen Bytes 1 Zeichen besteht, oder?
              Ja, dann weißt du wie viele Bytes ein Zeichen durchschnittlich hat. Also z.B. 1,1 bei einem deutschen Text.

              Du kannst strlen() ja anwenden auf den mit mb_substr() bearbeiteten String. Also z.B. so:
              PHP-Code:
              <?php
              header
              ('Content-Type: text/html; charset=utf-8');
              $s "Frühstück";
              $len 8;
              $sub mb_substr($s0$len'utf-8');

              echo 
              "Die ersten $len Zeichen von '$s' ('$sub') haben ".strlen($sub)." Bytes";
              // Die ersten 8 Zeichen von 'Frühstück' ('Frühstüc') haben 10 Bytes

              Kommentar


              • #8
                Ich glaube, ich habe die Lösung jetzt dank eurer Hilfe. Ich muss das aber zuerst ausprobieren. Dauert etwas.

                Kommentar


                • #9
                  PHP-Code:
                  <?php
                     error_reporting
                  (~0);
                     
                     
                  header('content-type: text/html; charset=utf-8');
                     
                  mb_internal_encoding('UTF-8');
                     
                     interface 
                  Flushable
                     
                  {
                        function 
                  flush();
                     }
                     
                     interface 
                  OutputStream
                     
                  {
                     }
                     
                     abstract class 
                  FilteredOutputStream implements OutputStream
                     
                  {
                        protected 
                  $target;
                     }
                     
                     class 
                  BufferedOutputStream extends FilteredOutputStream implements Flushable
                     
                  {
                        private 
                  $size;
                        private 
                  $buffer '';
                        
                        
                  /**
                         * @param OutputStream $target
                         * @param int $size PHP_INT_MAX / 2 > size > 0 in Byte
                         */
                        
                  function __construct(OutputStream $target$size 1024)
                        {
                           if(
                  $size PHP_INT_MAX 2)
                              throw new 
                  Exception('size');
                              
                           
                  $this->target $target;
                           
                  $this->size $size;
                        }
                        
                  /**
                         * @param string $data
                         * @throws Exception Aktueller Buffer + $data sprengen die Buffergröße.
                         */
                        
                  function write($data)
                        {
                           
                  // Beispiel:
                           //    Jedes Byte wird durch ein x dargestellt.
                           //    Der Buffer hat hier max. 5 Bytes:
                           //       xxxxx|xxxxx
                           //       ++---
                           //    + zeigt an, wie viel vom Buffer bereits belegt ist ($sizeBuffer).
                           //    - zeigt den freien Platz vom Buffer an ($this->size - $sizeBuffer).
                           //    Daneben gibt es weitere 5 x.
                           //    $data darf diese 5 x plus den - Stellen lang sein, dann kann
                           //    $data korrekt gespeichert bzw. zum Teil oder vollständig mit den + Stellen
                           //    an write weitergericht werden.
                           
                  $lenData strlen($data);
                           
                  $availableLen $this->size strlen($this->buffer);
                           if(
                  $lenData $availableLen)
                           {
                              
                  // data komplett in Buffer
                              
                  $this->buffer.= $data;
                           }
                           elseif(
                  $lenData == $availableLen)
                           {
                              
                  // alles rausschreiben, Buffer löschen
                              
                  $this->target->write($this->buffer.$data);
                              
                  $this->buffer '';
                           }
                           else
                           {
                              
                  // einen Teil rausschreiben, einen Teil buffern
                              
                  $len 1;
                              while(
                  strlen(mb_substr($data0$len)) <= $availableLen)
                              {
                                 ++
                  $len;
                              }
                              --
                  $len;
                              
                              
                  $rightData mb_substr($data$len);
                              if(
                  strlen($rightData) > $this->size)
                                 throw new 
                  Exception('data');

                              
                  $this->target->write($this->buffer.mb_substr($data0$len));
                              
                  $this->buffer $rightData;
                           }
                        }
                        
                  /**
                         * Reicht flush weiter.
                         */
                        
                  function flush()
                        {
                           if(
                  $this->buffer != '')
                           {
                              
                  $this->target->write($this->buffer);
                           }
                        }
                        
                  /**
                         * Liefert die Buffergröße.
                         * @return int
                         */
                        
                  function size()
                        {
                           return 
                  $this->size;
                        }
                     }
                     
                     class 
                  ScreenOutputStream implements OutputStream // Dummy-Datei zum Testen
                     
                  {
                        
                  /**
                         * @param string $data
                         */
                        
                  function write($data)
                        {
                           echo 
                  $data;
                        }
                     }
                     
                     
                  $sout = new ScreenOutputStream(); // Ausgabe auf Bildschirm
                     
                  $bout = new BufferedOutputStream($sout9); // buffern
                     
                  $bout->write('Ħħ');
                     echo 
                  'x';
                     
                  $bout->write('ĨĩĪīĬ');
                     echo 
                  'x';
                     
                  $bout->flush();
                  ?>
                  Richtig so?

                  Kommentar

                  Lädt...
                  X