Чтение бинарных данных. Как ?

Есть xml-документ. И в этом xml-документе есть такой узел:
PHP:
<peaks precision="32"
    byteOrder="network"
    contentType="m/z-int"
    compressionType="none"
    compressedLen="0" >QtH8O0QFhIhC5C3qRL8gqkLoGtJEG8WgQuwiPUNtPgRDAx3QROpGdEMGEBZDlgAAQxMW6kPFrGRDFh2DQ10srkMe9i9DmqWNQycozENu4bVDOv4zQ4UNu0Na77pEhT2+Q17niUNcshZDZi+yRAcCD0Nw6p1DnGj4Q4tzoESxe3xDi/NFQ+6hXUOMctNDawnZQ5ZxXERPEGpDpZtiQ8w35UOpb0xEnaHOQ6nuR0OcqB9DsnBHQ94ATEOzfRtEMJUNQ7P9eENVwgBDtGwgQ46gq0O0fiBEMSczQ7T+ZkOVBLVDtX3rQ+RmR0O1/gdDdWi6Q7Z9eEOigzNDx2sIQ+sw6EPQHZ5Dj4HHQ9BrsUO8JrZD22nkQ1BTqkPlZodDdzVVRAWxD0NwZTY=</peaks>
А в спецификации к этому документу сказано, что peaks - this element contains the m/z intensity pairs as base64 encoded binary data. This element can store raw as well as processed m/z - intensity pairs. The following attributes are defined for the peaks element:
- precision (required): the precision (in bits) of the binary floating point numbers encoded in the
element. This attribute can either have value 32 or 64.
- byteOrder (required): the byte order for the binary floating point numbers must be network.
- pairOrder (required): the order of the m/z - intensity pairs must be m/z-int.
- xsi:nil (optional): if there are no m/z – intensity pairs, but we want to have a scan element
anyway, the xsi:nil=”1” attribute can be set. It is important to remember to set the this attribute,
since an empty peaks will not meet the criteria of base64Binary type in the validation step.

The peaks element uses the following pattern ([A-Za-z0-9/\+=])* to restrict the xs:base64Binary
type. As a consequence the all base64 encoded binary data string must consist of one single line
without spaces!

Ну, допустим из base64 я раскодировать могу :)
PHP:
$peak = <<<PEAK
QtH8O0QFhIhC5C3qRL8gqkLoGtJEG8WgQuwiPUNtPgRDAx3QROpGdEMGEBZDlgAAQxMW6kPFrGRDFh2DQ10srkMe9i9DmqWNQycozENu4bVDOv4zQ4UNu0Na77pEhT2+Q17niUNcshZDZi+yRAcCD0Nw6p1DnGj4Q4tzoESxe3xDi/NFQ+6hXUOMctNDawnZQ5ZxXERPEGpDpZtiQ8w35UOpb0xEnaHOQ6nuR0OcqB9DsnBHQ94ATEOzfRtEMJUNQ7P9eENVwgBDtGwgQ46gq0O0fiBEMSczQ7T+ZkOVBLVDtX3rQ+RmR0O1/gdDdWi6Q7Z9eEOigzNDx2sIQ+sw6EPQHZ5Dj4HHQ9BrsUO8JrZD22nkQ1BTqkPlZodDdzVVRAWxD0NwZTY=
PEAK;

$bin = base64_decode($peak);
А что дальше ? Я так полагаю, что нужно использовать unpack(), но как ? Я во все этой бинарной мути вообще ничего не понимаю...
 
fixxxer
Спасибо. Вот так работает:
PHP:
$peak = <<<PEAK
QHHEN7agOp5APASSQAkEi0CfzPcNH6MzQDwMzMAMn/ZAoNxdoUSIxkA6VVVgA8u9QKGQVLq2SdRANQqqn/w0Qw==
PEAK;

$bin = base64_decode($peak);

$count = strlen($bin) / 8;
for ($i = 0; $i < $count; $i = $i + 2) {

    $mz  = substr($bin, $i * 8, 8);
    $int = substr($bin, ($i + 1) * 8, 8);

    echo array_shift(unpack('d', strrev($mz))), ' ', array_shift(unpack('d', strrev($int))), "\n";
}
Но для этих данных было указано precision="64", а не 32. Для 32 возможно нужно указывать 'f', а не 'd'. Не знаю. Вот что выводит:
PHP:
zeleniy@zeleniy-HP-Pro-3400:~/workspace/kvtml$ php peak.php 
284.2636019 28.0178566
2035.241261 28.04999924
2158.182871 26.33333397
2248.165487 21.04166603
Вурдалак
m/z - это отношение массы к заряду
int - интенсивность
Соотвественно то что вывел скрипт в первой колонке указано m/z, во второй int. Это пары значений.
Вообще этот фрагмент xml - кусок из mzXML. mzXML хранит данные о результатах работы масс спектрометра :)
 

Вурдалак

Продвинутый новичок
Во имя инкапсуляции, мне достаточно знать, что это пара (double, double). :)
 

fixxxer

К.О.
Партнер клуба
с 32 битными флоатами, боюсь, придется поизвращаться с ручным построением флоата, как то так

http://coding.derkeiler.com/Archive/PHP/alt.php/2004-11/0375.html

вообще я бы такое написал сишным экстеншеном, это, блин, проще =)

правда, есть вопрос, что с этим делать дальше. Может и интами можно обойтись.
 

fixxxer

К.О.
Партнер клуба
А вот хз. На конкретной архитектуре может и так, но вообще нет никакой гарантии.
f float (machine dependent size and representation)
d double (machine dependent size and representation)
Надо проверять, в общем, на целевой архтектуре, под которую под пишется (ну то есть на amd64 ога =)

Но в целом я неприятно удивлен отсутствием явного указания типа флоата и байт ордера в pack. С union-ами и/или кастингом в сях как-то все намного проще =)
 
Сверху