Php read binary files

PHP read binary file in real binary

Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers , the binary file was generated in C using a structure similar to what i have posted in the main question. I need to unpack it in PHP, idea is that user would upload it online. – Vlad Vladimir Hercules Aug 9 ’16 at 20:40 ,The above will write each packed structure into the file binary.bin, the size will be exactly 18 bytes. To get a better grasp on alignment/packing you can check out this so post: Structure padding and packing,The binary file is full of line breaks and I was able to decode the first line of it, which returned correct: type, version, model, number and a class. I think I have also decoded two next variable, but i am not sure of it because StartTime returns some gibberish.

I’m not really sure what you are trying to achieve here. If you have a binary file generated from the above c code then you could read and upack its content like this:

// get size of the binary file $filesize = filesize('filename.bin'); // open file for reading in binary mode $fp = fopen('filename.bin', 'rb'); // read the entire file into a binary string $binary = fread($fp, $filesize); // finally close the file fclose($fp); // unpack the data - notice that we create a format code using 'C%d' // that will unpack the size of the file in unsigned chars $unpacked = unpack(sprintf('C%d', $filesize), $binary); // reset array keys $unpacked = array_values($unpacked); // this variable holds the size of *one* structure in the file $block_size = 3; // figure out the number of blocks in the file $block_count = $file_size/$block_size; // you now should have an array where each element represents a // unsigned char from the binary file, so to display Day, Month and Year for ($i = 0, $j = 0; $i < $block_count; $i++, $j+=$block_size) < print 'Day: ' . $unpacked[$j] . '
'; print 'Month: ' . $unpacked[$j+1] . '
'; print 'Year: ' . $unpacked[$j+2] . '

'; >

Of course you could also create an object to hold the data:

class DATE_OF_BIRTH < public $Day; public $Month; public $Year; public function __construct($Day, $Month, $Year) < $this->Day = $Day; $this->Month = $Month; $this->Year = $Year; > > $Birth = []; for ($i = 0, $j = 0; $i

Another approach would be to slice it at each third element:

You should also be aware that this could become much more complicated depending on what data your structure contains, consider this small c program:

#include #include // pack structure members with a 1 byte aligment struct __attribute__((__packed__)) person_t < char name[5]; unsigned int age; >; struct person_t persons[2] = < < < 'l', 'i', 's', 'a', 0 >, 16 >, < < 'c', 'o', 'r', 'n', 0 >, 52 > >; int main(int argc, char** argv)

Then in you php code you could read each block in a loop like so:

$filesize = filesize("binary.bin"); $fp = fopen("binary.bin", "rb"); $binary = fread($fp, $filesize); fclose($fp); // this variable holds the size of *one* structure $block_size = 9; $num_blocks = $filesize/$block_size; // extract each block in a loop from the binary string for ($i = 0, $offset = 0; $i < $num_blocks; $i++, $offset += $block_size) < $unpacked_block = unpack("C5char/Iint", substr($binary, $offset)); $unpacked_block = array_values($unpacked_block); // walk over the 'name' part and get the ascii value array_walk($unpacked_block, function(&$item, $key) < if($key < 5) < $item = chr($item); >>); $name = implode('', array_slice($unpacked_block, 0, 5)); $age = implode('', array_slice($unpacked_block, 5, 1)); print 'name: ' . $name . '
'; print 'age: ' . $age . '
'; >

Answer by Adan Meadows

Example: file to binary php

$data = fopen ($image, 'rb'); $size=filesize ($image); $contents= fread ($data, $size); fclose ($data);

Answer by Bryan Dean

1 first unpack $header_format to get 'L# of Records' for every packet.(have a total of 200 packets) 2 unpack $record_format 'L# of Records' times $record_format = CField Name/' . # Grab 1 byte 'fField Type1/' . # Grab 4 bytes 'fField Type2/' . # Grab 4 bytes 'fField Type3/' . # Grab 4 bytes 'fField number/' . # Grab 4 bytes 'fdistance/' . # Grab 4 bytes 'CField id /' # Grab 1 byte 'iField Precision/' # Grab 4 bytes 'SField Data'; # Grab x bytes 3 Step 1 and 2 are for one packet from the file. 4 Repeat 1-3 until end of file is reached. 

Answer by Giavanna Ross

With BinaryStream you can handle network packets, binary files, system protocols and other low-level data.,This class can parse extract data from binary files. It can read binary data from a given file and extract data blocks of several types and sizes. Currently it supports data blocks of types like bits, characters, big and little endian short and long integers of 16, 32 and 64 bits, 32 and 64 bits float and double. The class can also read from a configuration file group data type definitions associated to given names., The library supports all major data types and allows both read and write the data. ,_BinaryStream_ — is a powerful tool for reading and writing binary files. It supports a variety of high-level data types and sometimes lets you forget that you are working with unstructured binary data.

Читайте также:  Пишем простую программу java

The easiest way to use BinaryStream — this:

use wapmorgan\BinaryStream\BinaryStream; $stream = new BinaryStream('filename.ext'); $text = $s->readString(20); 

A more complex example, where the data were located in the following order: — integer (int, 32 bit) — float (float, 32 bit) — flag byte (where each bit has its own value, 8 bits): first bit determines whether there after this byte written another data, 5-bit empty, and the last 2 bits of the data type:

- `0b00` - after this data recorded 1 character (char, 8 bits) - `0b01` - after this data recorded 10 characters (string, 10 bytes) - `0b10` - after this data time in unixtime format packaged in long integer (long, 64 bits) - `0b11` - not used at this moment. 

In order to read these data and those that depend on the flags, this example is suitable:

use wapmorgan\BinaryStream\BinaryStream; $stream = new BinaryStream('filename.ext'); $int = $stream->readInteger(32); $float = $stream->readFloat(32); $flags = $stream->readBits([ 'additional_data' => 1, '_' => 5, // pointless data 'data_type' => 2, ]); if ($flags['additional_data']) < if ($flags['data_type'] == 0b00) $char = $stream->readChar(); else if ($flags['data_type'] == 0b01) $string = $stream->readString(10); else if ($flags['data_type'] == 0b10) $time = date('r', $stream->readInteger(64)); > 

But it is unlikely to be so few data. For added convenience, you can use a group reading function. The previous example can be rewritten as follows:

use wapmorgan\BinaryStream\BinaryStream; $stream = new BinaryStream('filename.ext'); $data = $stream->readGroup([ 'i:int' => 32, 'f:float' => 32, 'additional_data' => 1, '_' => 5, 'data_type' => 2, ]); if ($data['additional_data']) < if ($data['data_type'] == 0b00) $data['char'] = $stream->readChar(); else if ($data['data_type'] == 0b01) $data['string'] = $stream->readString(10); else if ($data['data_type'] == 0b10) $data['time'] = date('r', $stream->readInteger(64)); > 

If you are reading a file in which such groups of data are repeated, you can save a group with a name, and then simply refer to it to read the next data. Let us introduce one more value for data_type: 0b11 — means that this is the last group of data in the file. An example would be:

use wapmorgan\BinaryStream\BinaryStream; $stream = new BinaryStream('filename.ext'); $stream->saveGroup('Data', [ 'i:int' => 32, 'f:float' => 32, 'additional_data' => 1, '_' => 5, 'data_type' => 2, ]); do < $data = $stream->readGroup('Data'); // Some operations with data > while ($data['data_type'] != 0b11); 

And now imagine that we have moved to a new file format that is different from the previous one and has a certain mark in the beginning of the file, which will help to distinguish the new from the old format. For example, a new label is a sequence of characters ‘A’, ‘S’, ‘C’ . We need to check the label and if it is present, parse the file according to another scheme, and if it does not, use the old version of the processor. An example to illustrate this:

use wapmorgan\BinaryStream\BinaryStream; $stream = new BinaryStream('filename.ext'); if ($stream->compare(3, 'ASC')) < // parse here new format >else < $stream->saveGroup('DataOld', [ 'i:int' => 32, 'f:float' => 32, 'additional_data' => 1, '_' => 5, 'data_type' => 2, ]); do < $data = $stream->readGroup('DataOld'); // Some operations with data > while ($data['data_type'] != 0b11); > 

Installation via composer:

composer require wapmorgan/binary-stream 

You can save list of fields definitions with a specific name and use it’s name when you need to read the same block few times. A group is defined by group configuration — list of fields, their type and size. To compose group configuration create an array: keys define type and name of fields, values — their size: — key is a name of field and may contain type of field. To specify type prepend name with a type letter and a colon. Type letters:

- `b` - bit - `i` - integer - `f` - float - `c` - char - `s` - string If type is not defined, field will be treated as a `bit`-field. Example: `flag` - `bit`-field, `s:name` - `string`-field 
value is a size or a dimension of field: - If field has `integer`, `float` or `bit` type, it defines size of field in term of bits. - If field has `char` or `string` type, it defines size in term of bytes. Example: 'flags' => 16, // bits-field (16 bits = 2 bytes) 's:name' => 10, // string-field (80 bits = 10 bytes) 

So full example of group configuration:

$group = [ 'flags' => 16, 'i:date' => 32, 'f:summ' => 32, 's:name' => 10, ]; 
Current position testing: isEnd(): boolean 
Comparation of bytes: compare($length, $bytes) 

Answer by Mario Brewer

Both binary data, like images and character data, can be written with this function since fread() is binary-safe.,PHP | file_get_contents() Function,To get the contents of a file only into a string, use file_get_contents() as it has much better performance than the code above.,Suppose a file named gfg.txt contains the following content:

string fread ( $file, $length )
Geeksforgeeks is a portal of geeks! 

Источник

Читайте также:  Python pip install numpy error

fread

Указатель ( resource ) на файл, обычно создаваемый с помощью функции fopen() .

length указывает размер прочитанных данных в байтах.

Возвращаемые значения

Возвращает прочтенную строку или FALSE в случае возникновения ошибки.

Примеры

Пример #1 Простой пример использования fread()

// получает содержимое файла в строку
$filename = «/usr/local/something.txt» ;
$handle = fopen ( $filename , «r» );
$contents = fread ( $handle , filesize ( $filename ));
fclose ( $handle );
?>

Пример #2 Пример бинарного чтения с помощью fread()

На системах, которые различают бинарные и текстовые файлы (к примеру, Windows), файл должен быть открыт с использованием буквы ‘b’ в параметре mode функции fopen() .

$filename = «c:\\files\\somepic.gif» ;
$handle = fopen ( $filename , «rb» );
$contents = fread ( $handle , filesize ( $filename ));
fclose ( $handle );
?>

Пример #3 Примеры удаленного чтения с помощью fread()

При чтении чего-либо отличного от локальных файлов, например потоков, возвращаемых при чтении удаленных файлов или из popen() и fsockopen() , чтение остановится после того, как пакет станет доступным. Это означает, что вы должны собирать данные вместе по кусочкам, как показано на примере ниже.

// Для PHP 5 и выше
$handle = fopen ( «http://www.example.com/» , «rb» );
$contents = stream_get_contents ( $handle );
fclose ( $handle );
?>

$handle = fopen ( «http://www.example.com/» , «rb» );
if ( FALSE === $handle ) exit( «Не удалось открыть поток по url адресу» );
>

while (! feof ( $handle )) $contents .= fread ( $handle , 8192 );
>
fclose ( $handle );
?>

Примечания

Замечание:

Если вы просто хотите получить содержимое файла в виде строки, используйте file_get_contents() , так как эта функция намного производительнее, чем код описанный выше.

Замечание:

Учтите, что fread() читает начиная с текущей позиции файлового указателя. Используйте функцию ftell() для нахождения текущей позиции указателя и функцию rewind() для перемотки позиции указателя в начало.

Смотрите также

  • fwrite() — Бинарно-безопасная запись в файл
  • fopen() — Открывает файл или URL
  • fsockopen() — Открывает соединение с интернет сокетом или доменным сокетом Unix
  • popen() — Открывает файловый указатель процесса
  • fgets() — Читает строку из файла
  • fgetss() — Прочитать строку из файла и отбросить HTML-теги
  • fscanf() — Обрабатывает данные из файла в соответствии с форматом
  • file() — Читает содержимое файла и помещает его в массив
  • fpassthru() — Выводит все оставшиеся данные из файлового указателя
  • ftell() — Сообщает текущую позицию чтения/записи файла
  • rewind() — Сбрасывает курсор у файлового указателя
Читайте также:  Java class editor online

Источник

Оцените статью