Get binary from file php

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 < $block_count; $i++, $j+=$block_size] {
   $Birth[] = new DATE_OF_BIRTH[
       $unpacked[$j], 
       $unpacked[$j+1], 
       $unpacked[$j+2]
   ];
}

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

$Birth = [];    

for [$i = 0; $i < $block_count; $i++] {
  // slice one read structure from the array
  $slice = array_slice[$unpacked, $i * $block_size, $block_size];

  // combine the extracted array containing Day, Month and Year
  // with the appropriate keys
  $slice = array_combine[array['Day', 'Month', 'Year'], $slice];

  $Birth[] = $slice;
}

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] {
  FILE* fp = fopen["binary.bin", "wb"];
  fwrite[persons, sizeof[persons], 1, fp];
  fclose[fp];
  return 0;
}

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

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 . '
'; }

[PHP 4, PHP 5, PHP 7, PHP 8]

freadBinary-safe file read

Description

fread[resource $stream, int $length]: string|false

  • length bytes have been read
  • EOF [end of file] is reached
  • a packet becomes available or the socket timeout occurs [for network streams]
  • if the stream is read buffered and it does not represent a plain file, at most one read of up to a number of bytes equal to the chunk size [usually 8192] is made; depending on the previously buffered data, the size of the returned data may be larger than the chunk size.

Parameters

stream

A file system pointer resource that is typically created using fopen[].

length

Up to length number of bytes read.

Return Values

Returns the read string or false on failure.

Examples

Example #1 A simple fread[] example

Example #2 Binary fread[] example

Warning

On systems which differentiate between binary and text files [i.e. Windows] the file must be opened with 'b' included in fopen[] mode parameter.

Example #3 Remote fread[] examples

Warning

When reading from anything that is not a regular local file, such as streams returned when reading remote files or from popen[] and fsockopen[], reading will stop after a packet is available. This means that you should collect the data together in chunks as shown in the examples below.

Notes

Note:

If you just want to get the contents of a file into a string, use file_get_contents[] as it has much better performance than the code above.

Note:

Note that fread[] reads from the current position of the file pointer. Use ftell[] to find the current position of the pointer and rewind[] to rewind the pointer position.

See Also

  • fwrite[] - Binary-safe file write
  • fopen[] - Opens file or URL
  • fsockopen[] - Open Internet or Unix domain socket connection
  • popen[] - Opens process file pointer
  • fgets[] - Gets line from file pointer
  • fgetss[] - Gets line from file pointer and strip HTML tags
  • fscanf[] - Parses input from a file according to a format
  • file[] - Reads entire file into an array
  • fpassthru[] - Output all remaining data on a file pointer
  • fseek[] - Seeks on a file pointer
  • ftell[] - Returns the current position of the file read/write pointer
  • rewind[] - Rewind the position of a file pointer
  • unpack[] - Unpack data from binary string

Edward Jaramilla

14 years ago

I couldn't get some of the previous resume scripts to work with Free Download Manager or Firefox.  I did some clean up and modified the code a little.

Changes:
1. Added a Flag to specify if you want download to be resumable or not
2. Some error checking and data cleanup for invalid/multiple ranges based on //tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
3. Always calculate a $seek_end even though the range specification says it could be empty... eg: bytes 500-/1234
4. Removed some Cache headers that didn't seem to be needed. [add back if you have problems]
5. Only send partial content header if downloading a piece of the file [IE workaround]



The problem is that sometimes end of streaming is not marked by EOF nor a fixed mark, that's why this looped forever. This caused me a lot of headaches...
I solved it using the stream_get_meta_data function and a break statement as the following shows:



Hope this will save a lot of headaches to someone.

[Greetings, from La Paz-Bolivia]

mail at 3v1n0 dot net

14 years ago

This is an hack I've done to download remote files with HTTP resume support. This is useful if you want to write a download script that fetches files remotely and then sends them to the user, adding support to download managers [I tested it on wget]. To do that you should also use a "remote_filesize" function that you can easily write/find.

matt at matt-darby dot com

14 years ago

I thought I had an issue where fread[] would fail on files > 30M in size. I tried a file_get_contents[] method with the same results. The issue was not reading the file, but echoing its data back to the browser.

Basically, you need to split up the filedata into manageable chunks before firing it off to the browser:



Hope this helps someone!

aubfre at hotmail dot com

15 years ago

Changing the value of $length may yield to different download speeds when serving a file from a script.

I was not able to max out my 10mbps connection when 4096 was used. I found out that using 16384 would use all the available bandwidth.

When outputing binary data with fread, do not assume that 4096 or 8192 is the optimal value for you. Do some benchmarks by downloading files through your script.

randym

11 years ago

Concerning [problems with UTF-8 and] downloading Zip files I found that simply adding 3 lines of code before starting the fread to the buffer for delivery in all browsers solved the problem.



... see where placed in the function below:

david at identd dot dyndns dot org

12 years ago

Note to IIS admins:

When using PHP via the FastCGI ISAPI extension, there is a script timeout of approximately 1hr that cannot be adjusted. When using PHP via CGI, there is a script timeout that is based upon the value of the CGITimeout configuration option. This value must be set extremely high if you plan to serve large files. An explanation of how to configure this option can be found here: //www.iisadmin.co.uk/?p=7 If you do not modify this setting you can expect the above scripts to fail silently once it has hit the default value [30 minutes in my case].

Anonymous

14 years ago

It might be worth noting that if your site uses a front controller with sessions and you send a large file to a user; you should end the session just before sending the file, otherwise the user will not be able to continue continue browsing the site while the file is downloading.

Anonymous

13 years ago

This code is buggy

When you read a file whose size is a multiple of the readsize [8192 here], then the loop is executed when there are no more data to read. Here, the result of fread[] is not checked, and so the instruction

is executed once with no data from fread[]. In this very case, it is not important, but in some situation it could be harmful.

The good way to read a file block by block is :

dvsoftware at gmail dot com

17 years ago

I was trying to implement resume support in download script, and i have finnaly succeded. here is the script:

Chủ Đề