Wow. Deine Hilfe ist unbezahlbar. Soviele Sachen, für die ich ewig gebraucht hätte. Ich bin Dir sehr dankbar!
Die 8 gehört bereits zum ersten Wert. Wenn du dir mal die Datei in einem Hex-Editor anschaust, siehst du x04, x00, x00, x00, gefolgt von x58, x02, x00, x00 und nochmal x04, x00, x00, x00. Das x58 x02 ergibt richtigrum gedreht 258 hex = 600 dez. Mein Editor zeigt 16 Byte pro Zeile und eine Zeilennummer, nein, eigentlich eine Adresse an. Die Adresse der letzten Zeile ist 00002580, passt also zu dem 258/600. Zu sehen ist außerdem, dass in der Zeile 4 Byte fehlen, also besteht ein Eintrag aus den letzten 4 Byte einer Zeile plus 12 Byte der nachfolgenden Zeile. Auf die erste Zeile angewendet, gehört also deine 8 bereits zum ersten Wert.
Das ist eine sehr gute Herleitung.
Und nun versagen meine Erklärungsversuche teilweise. Ein Float hat entweder 32 oder 64 Bit, also 4 oder 8 Byte. Ein Wert in deiner Datei sind aber 16 Byte und wenn man da hinschaut, sind die 8 Bytes eines Float vorn und hinten mit 08 00 00 00 eingerahmt. Und der eigentliche Sinn davon erschließt sich mir nicht.
Irgendwas in der Art scheint da los zu sein. Wenn ich es mir überlege, scheint die Regel zu sein, dass jeder Wert von Interesse (die 600 und die folgenden Doubles) geklammert ist von der Bytelänge als Integer.
4 600 4
8 irgendein Double 8
8 irgendein Double 8
8 irgendein Double 8
...
Dann gehts ja auch auf?!? Komische Formatierung. Danke für die Investigation!
Und das auch bei der Angabe der Anzahl der Floatwerte.
Sagtest Du ja sogar schon... :)
Diese Vor- und Nachspänne bringen dir keine Punkte, denn die Längen des Zählwertes und der Nutzwerte sind fest. Es sei denn, das ändert sich von Datei zu Datei, aber auch dann wäre nur ein Vorspann nötig.
Genau so mache ich das wohl. Prüfen, und wenn ungleich 8, dann abbrechen. Oder kann ich dann Format f* benutzen? In der Dokumentation steht leider "machine dependent size and representation", weswegen ich nicht ganz sicher bin, ob d immer 64bit und f immer 32bit bedeutet. Das ganze wird später auf evtl. anderer Plattform laufen!
?#4
: Warum wandert der erste korrekte Floatwert von Position 5 bei L2 auf Position 4 bei L4? Ich hätte erwartet, dass er bei Position 5 bleibt und nur mehr Phantasiewerte dazwischen stehen...Dürfte bereits geklärt sein.
?#5
: Wie kann ich durch einen geeigneten Formatanweiser 64Bit lesen, da ich annehme der Autor hat die Floats in 64 kodiert. Gibt es da was in php 5.3.5? Oder kann ich die Lücken bedenkenlos wegschmeißen, auch in Hinblick auf ein späteres evtl. neg. Vorzeichen?Es sind keine 64-Bit-Floats. Es bleiben 32 Bit mit 32 Bit Müll dazwischen.
Hm. Habs jetzt aber eher so verstanden, dass alle meine Floats 64bit sind :) Muss der Satz nicht heissen (abgesehen davon, dass meine Frage davor falsch war): "Es gibt keine 128bit FLoats, es bleiben 64 bit mit 2*16bit Müll
:)
[2]
?#1
: Was ist besser?
$file_hdl = fopen($filename,"rb");
$data_bin = fread($file_hdl, filesize($filename));
fclose($file_hdl);
> >
> > oder
> >
> > `$data_bin = file_get_contents($filename);`{:.language-php}
>
> Da du unpack() den gesamten Batzen übergibst, ist letzeres effizienter zu notieren. fread() ist nur bei häppchenweisem Lesen von Vorteil.
Hier habe ich jetzt mal als kleinen Beitrag einen Performance-Test gemacht. Da ich ja eigentlich sowas wie unpack("I4/(d1/I2)\*, $data\_bin) gebraucht hätte (also mit einer etwas komplizierteren Maske) habe ich das auch mal mit fread umgesetzt. Hier der Code:
~~~php
<?php
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
echo $filename = "./BULKOUT_1_GMT2000.BULKBINOUT";
$time_start = microtime_float();
for($i = 0; $i <=2000; $i++){
$data_bin = file_get_contents($filename);
$out = unpack("I4ints/d*floats", $data_bin);
$out = array_values($out); // delete alphanum keys
$out = array_splice($out, 4); // delete first 4 elements
foreach($out as $key=>$o){ // delete every second element
if(($key%2)!=0) unset($out[$key]);
}
}
echo "<br>process lasted ".(round(microtime_float() - $time_start,4))." seconds";
var_dump($out);
$time_start = microtime_float();
for($i = 0; $i <=2000; $i++){
$out = array();
$file_hdl = fopen($filename,"rb");
$data_bin = fread($file_hdl, 16);
$head = unpack("I*", $data_bin);
for($j = 1; $j<=600; $j++){
$data_bin = fread($file_hdl, 8);
$back = unpack("d1", $data_bin);
$out[] = current($back);
$data_bin = fread($file_hdl, 8);
}
fclose($file_hdl);
}
echo "<br>process lasted ".(round(microtime_float() - $time_start,4))." seconds";
var_dump($out);
?>
$out sind beides mal gleich.
Ergebnis: ratet mal. 4,5 Sekunden zu 14 Sekunden. Und vorne liegt file_get_contents!!!
LG,
LSpreee