LSpreee: Nochmal Binärdaten

Beitrag lesen

Fragen sind nummeriert ?#1, ?#2, ...

Ich verwende jetzt keine Dummydaten mehr, sondern habe eine Binärdatei[1] geöffnet[2]. Ich habe parallel eine ASCII Datei[1] erhalten, die den Inhalt der Binärdatei enthält, um zu testen, ob ich die Binärdatei richtig entpacke.
Der Aufbau ist so: erst kommt ein Integerwert und dann folgen in Anzahl dieses Integers Floats.

Mit unpack("L*", $data_bin) sehe ich

1 => int 4
  2 => int 600
  3 => int 4
  4 => int 8

wobei ich die 600 lt. Ascii-Datei erwartet habe. Die "4"er sind Phantasie.

Wenn ich mir die gleiche Datei mit unpack("d*", $data_bin) ansehe, erhalte ich:

1 => float 1.2731974745811E-311
  2 => float 1.6975966329698E-313
  3 => float 0.68123407969334
  4 => float 1.6975966331675E-313
  5 => float 0.58200506209549

wobei ich die Werte unter 3 und 5,7,9,... als erste Werte nach der 600 erwartet habe, lt. Ascii-Datei (4,6,8,... sind Phantasie). Das ist schonmal super und ein Teilerfolg.

Die Phantasiewerte erkläre ich mir momentan damit, dass evtl 64Bit == 8Byte für die Floats und Integers reserviert wurden, L aber nur 4Byte abfragt. (?#2: Richtig?)

Alle anderen Formate bringen mir momentan nicht meine erwarteten Floats, also nur d. ?#3: Wie lang ist d genau? Auch 4Bytes?

---

Nun würde ich gerne eine Maske schreiben, die mir die Daten perfekt entpackt.

Ganz gut passt:

$out = unpack('L2ints/d*floats', $data_bin);

Ergebniss:

array
    'ints1' => int 4
    'ints2' => int 600
    'floats1' => float 1.6975966329698E-313
    'floats2' => float 0.68123407969334
    'floats3' => float 1.6975966331675E-313
    'floats4' => float 0.58200506209549

oder
$out = unpack("L4ints/d*floats", $data_bin);

array
    'ints1' => int 4
    'ints2' => int 600
    'ints3' => int 4
    'ints4' => int 8
    'floats1' => float 0.68123407969334
    'floats2' => float 1.6975966331675E-313
    'floats3' => float 0.58200506209549
    'floats4' => float 1.6975966331675E-313
    'floats5' => float 0.64692148179895
    'floats6' => float 1.6975966331675E-313
    'floats7' => float 0.72734202673086

Ähnliches mit L3 oder L5 zerhaut mir die Daten und ich erhalte keinen Wert mehr von meinen erwarteten Floats.

?#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...

Und schließlich:
?#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?

Liebe Grüße,
LSpreee

##################################################

[1] Habe ich mal bei Dropbox hochgeladen.
[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);

----------------------------------------------------------

Mit diesem Code habe ich mal die Datei grob untersucht und nach geeigneten Formatanweisern gesehen. Für die Ints kommen mehrere in Frage, für die Floats passt nur d*

  
function getunpack($format,$data){  
  $results = unpack($format, $data); $i=0;		  
  echo "<br><br>results with format $format<br><hr>";  
  foreach($results as $key=>$result) {		  
    if($i == 5) break; $i++;  
    echo $key;  
    var_dump($result);		  
  }  
  return $results;  
}  
echo $filename = "./BULKOUT_1_GMT2000.BULKBINOUT";  
$data_bin      = file_get_contents($filename);  
  
$try = array("a","A","h","H","c","C","s","S","n","v","i","I","l","L","N","V","f","d","x");  
  
foreach($try as $trythis) $out = getunpack("$trythis*", $data_bin);