Problematik
Dateigrößen lassen sich mit PHP sehr einfach über die Funktion filesize() ermitteln. Ausgaben wie:
"<img src=\"$picture_file\" alt=\"$description\"><br>" . fileSize($picture_file) . " Bytes"
sind dementsprechend einfach zu erzeugen. Bei größeren Zahlen wird die nackte Zahl allerdings leicht unleserlich, und vertraute Größenbereiche wie Kilobyte oder Megabyte fehlen ganz. Eine einfacher zu lesende Größenangabe lässt sich jedoch einfach über die hier vorgestellte Funktion automatisieren.
Code
function formatFileSize($n) { $units = array("Bytes","KBytes","MBytes","GBytes","TBytes","PBytes"); $c = 0; while ($n >= 1024 and $c < count($units)) { $c += 1; $n = $n / 1024; } return(number_format($n, ($c ? 2 : 0), ",", ".") . " " .$units[$c]); }
Erläuterung
Von den Funktionen für besser lesbare Dateigrößenangaben, die in den User-Kommentaren zur PHP-Funktion number_format() vorgestellt werden, ist die hier mit einer kleinen Ergänzung übernommene Lösung wohl die intelligenteste.
Die Funktion bekommt eine nackte Byte-Zahl ($n) übergeben. Zunächst definiert sie einen Array aus den möglichen Maßangaben. Unterschieden werden sollen Byte-Angaben bis in die Größenordnung von Petabytes (das sollte für einzelne Dateien für ein paar Jahre genügen ;-)
In einer while-Schleife wird daraufhin ermittelt, welche Maßeinheit verwendet werden soll. Folgen wir zum besseren Verständnis einfach mal dem Algorithmus mit zwei Beispielen:
Angenommen, eine Datei hat eine Größe von 820 Byte. Der Funktion wird also $n = 820 übergeben. Schon die erste Prüfung gegen die Schleifenbedingung ergibt ein negatives Ergebnis (820 ist nicht größer als 1024). Damit wird die Schleife übersprungen und sofort das daran anschließende return-Statement ausgeführt. Die Schleifenzählervariable $c hat in diesem Fall noch ihren Initialwert von 0. Die Funktion number_format() erhält als ersten Parameter die zu formatierende Zahl übergeben, in unserem Fall also $n, im Beispiel also 820. Im zweiten Parameter erwartet number_format() die gewünschte Anzahl auszugebender Dezimalstellen (Nachkommastellen). Unsere Funktion übergibt an dieser Stelle einen Entweder-Oder-Ausdruck: Ist $c wahr (will heißen: Ist $c größer 0), dann sollen zwei Nachkommastellen ausgegeben werden, ansonsten (wenn $c noch 0 ist) keine Nachkommastellen. In unserem Fall ist $c noch 0, also werden keine Nachkommastellen ausgegeben. Es folgen noch zwei Angaben, wie number_format() das Dezimaltrennzeichen und das Tausendertrennzeichen darstellen soll. Wir übergeben hier die Werte, wie sie für die in Deutschland übliche Notation benötigt werden (also z.B. 1.234,56). Das return-Statement ist damit aber noch nicht komplett. Am Ende wird noch ein Leerzeichen hinzugefügt und daran anschließend ein Array-Element aus $units. Welches, das bestimmt der Schleifenzähler $c. In unserem Fall (820 Bytes) wird also $units[0] (= Bytes) ausgewählt.
Verfolgen wir nun noch, was bei einer Dateigröße von 1127645 Bytes passiert. 11227645 ist größer als 1024, und $c ist noch 0, also kleiner als die Anzahl der Elemente des Arrays $units. Die Funktion gelangt diesmal also in den Körper der while-Schleife. Dort wird zunächst der Schleifenzähler $c um 1 erhöht. Anschließend wird die übergebene Byte-Zahl durch 1024 geteilt. Hintergrund ist, dass die Maßangaben jeweils das 1024fache ihres Vorgängers darstellen: ein KiloByte hat 1024 Bytes, ein MegaByte hat 1024 KiloByte usw. 1127645 geteilt durch 1024 ergibt 1101,2158203125. Mit diesem Wert wird die while-Schleifenbedingung erneut geprüft. 1101 ist größer als 1024, $c ist 1, was weniger ist als die Anzahl der Elemente von $units. Also geht es zum zweiten Mal in den Schleifenkörper. Dort wird $c auf 2 erhöht, und auf $n wird 1101,2158203125 / 1024 angewendet, was 1,07540607452393 ergibt. Dieser Wert führt bei der nächsten Prüfung der Schleifenbedingung zum Abbruch der Schleife, weil 1,07540607452393 viel weniger als 1024 ist. Im return-Statement werden nun zwei Nachkommastellen ausgegeben, weil $c größer als 0 (und damit programmiertechnisch wahr) ist. Als Maßeinheit wird in diesem Fall $units[2] angehängt, also MBytes. Da die Funktion number_format() automatisch kaufmännisch rundet, wird am Ende der Return-Wert 1,08 MBytes erzeugt.
