Startseite --> Hilfen & Technische Artikel --> Codeschnipsel --> PHP: Binärdateien erkennen

PHP: Binärdateien erkennen

Wenn man beispielsweise versucht, einfache Datei-Manager zu programmieren, kann es nützlich sein, wenn man Dateien vor dem Öffnen daraufhin untersucht, ob sie Binärdaten enthalten, damit keine wirren Zeichen am Bildschirm angezeigt werden oder die Datei beschädigt wird, weil sie jemand "bearbeiten" wollte. Natürlich kann man auch es sich auch einfach machen und in dem Programm eine Liste mit Datei-Erweiterungen definieren, die typisch sind für Text- oder Binärdateien. Aber das ist zu unflexibel und auf Dauer ist es nervig, diese Liste zu verwalten.

Diese Funktionen basieren hauptsächlich auf dem Tipp "test if a file or string is text or binary" aus dem ActiveState Python Cookbook. Die Python-Funktion aus dem verlinkten Tipp wurde wiederrum anhand der Definition der Dateitest-Operatoren -B und -T von Perl erstellt. Diese Definition besagt, dass eine Datei eine Binärdatei ist, wenn sich im ersten Block der Datei zu mehr als 30% Steuerzeichen und Zeichen mit einem hohen Bit-Wert befinden oder wenn das Zeichen mit dem ASCII-Wert 0 in diesem Block vorkommt. Leere Dateien werden als Textdateien behandelt.

function is_textfile($file,$blocksize=512)
{
 $fp = fopen($file,'rb');
 flock($fp,LOCK_SH);
 $string = fread($fp,$blocksize);
 fclose($fp);

 return is_text($string);
}

function is_text($s)
{
 $text_characters = array_merge(array_map('chr',range(32,127)),array("\012","\015","\t","\b"));

 if(strpos($s,"\0") === true) return;
 if(!$s)                      return 1;

 $t = $s;

 foreach($text_characters as $text_character)
 {
  $t = str_replace($text_character,'',$t);
 }

 if(strlen($t) / strlen($s) > 0.3) return;
 return 1;
}

Das ganze besteht aus zwei Funktionen: is_text() wendet die oben beschriebene Prüfung auf irgendeine Zeichenkette an, is_textfile() liest die ersten 512 Bytes (oder je nachdem, was angegeben wurde) und gibt diese dann an is_text() weiter.

Zunächst wird das Array $text_characters erstellt. Es enthält die erlaubten Zeichen. Hierbei handelt es sich um die Zeichen mit den ASCII-Werten 32 bis 127 (Buchstaben und Ziffern), das Zeilenumbruchzeichen, der Wagenrücklauf, das Tab-Zeichen und das Backspace-Zeichen.
Anschließend wird mit strpos() überprüft, ob das Zeichen mit dem ASCII-Wert 0 in der Zeichenkette vorkommt. Ist dies der Fall, so wird die Funktion abgebrochen und die Daten als Binärdaten gekennzeichnet. Dann wird geprüft, ob die Zeichenkette überhaupt Daten enthät. Wenn sie keine Daten enthält, so werden die Daten als Textdaten gekennzeichnet und die Funktion beendet.
Nun wird die Zeichenkette in die Variable $t kopiert. Nun wird mit foreach() das Array mit den erlaubten Zeichen durchgegangen und in $t jedes dieser Zeichen entfernt (es wird mit str_replace() durch eine leere Zeichenkette ersetzt). Danach wird die Länge der neuen Zeichenkette, in der alle erlaubten Zeichen entfernt wurden durch die Länge der ursprünglichen Zeichenkette geteilt. Wenn das Ergebnis größer als 0.3 ist, so werden die Daten als Binärdaten erkannt, ansonsten handelt es sich um Textdaten.

Startseite --> Hilfen & Technische Artikel --> Codeschnipsel --> PHP: Binärdateien erkennen