reading binary code of a file...in PHP - php

How can I read the binary code(to get the 1s and 0s) of a file.
$filename = "something.mp3";
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
I tried this but it shows some strange characters... I presume that this is the formated binary? I was hoping to get the 1's and 0's instead.
Also I am not looking only .mp3 files it could be anything .e.g: .txt , .doc , .mp4, .php, .jpg, .png etc....

Files are stored on the computer in binary form indeed, but the 1s and 0s are stored together in groups of 8 (called bytes). Now, traditionally, each byte may be represented by an ASCII character because of the fact that there are 256 possible values that can be represented in a byte - which happens to coincide with the total number of different ASCII characters available (this was not a coincidence but actually by design).
That being said, what you are getting back from the fread function is what you're supposed to get: i.e. the contents of the file.
If you want to see the 1s an 0s you will need to print each byte that your receive into it's base 2 representation. You can achieve that using a function such as base_convert or by writing your own.
$filename = "something.mp3";
$handle = fopen($filename, "rb");
$fsize = filesize($filename);
$contents = fread($handle, $fsize);
fclose($handle);
// iterate through each byte in the contents
for($i = 0; $i < $fsize; $i++)
{
// get the current ASCII character representation of the current byte
$asciiCharacter = $contents[$i];
// get the base 10 value of the current characer
$base10value = ord($asciiCharacter);
// now convert that byte from base 10 to base 2 (i.e 01001010...)
$base2representation = base_convert($base10value, 10, 2);
// print the 0s and 1s
echo($base2representation);
}
NOTE
If you have a string of 1s and 0s (the base 2 representation of a character) you can convert it back to the character like so:
$base2string = '01011010';
$base10value = base_convert($base2string, 2, 10); // => 132
$ASCIICharacter = chr($base10value); // => 'Z'
echo($ASCIICharacter); // will print Z

Here you go, the 1s and the 0s:
$filename = "something.mp3";
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
for ($i = 0; $i < strlen($contents); $i++) {
$binary = sprintf("%08d", base_convert(ord($contents[$i]), 10, 2));
echo $binary . " ";
}
fclose($handle);

Why not use the PHP function decbin?
for($i = 0; $i < $fsize; $i++){
$base10value = ord($contents[$i]);
echo decbin($base10value);
}

Related

PHP: unpack 32 bit integers from binary stream of data

I have a 1024 bit long binary stream of data which I'd like to convert to an array of 32-bit integers (e.i. 32 numbers).
From this question I used this code:
$filename = "myFile.sav";
$handle = fopen($filename, "rb");
$fsize = filesize($filename);
$contents = fread($handle, $fsize);
$byteArray = unpack("N*",$contents);
print_r($byteArray);
And even though it formats itself as "N", var_dump then prints out an array of 256 8-bit long integers. (I want 32 32-bit long numbers). What am I doing wrong?
EDIT: its not actually 256 8-bit numbers, but 256 gibberish values
It seems that your file contains the binary representation of your integers. Given any string representation of bits, the bindec function will convert them properly to integer:
$content = "1000110010110110100100101011000100100000101011010101101110101101011101110011001110010010111101001011111000111000101110011110011100110110000111001110000011001101011100111011110000001110111100100110110001000111111001010101100011100101010111000011010101010010001101101100011001101110001001000101110111011001001101111000110101010001101010000101110000100010000110110111000110001110000010000111001100100111110011000101000110100011111100100011110100101010101101011011101100111000101011110111111010001110000011101001011101111010101010011010011010011101100011111111000110000110000000000101110110010100010011010001110101101100110110001011010010010000011000111101110000100100001101100010101011000110010110110111100111010010101110000101011101010010101110100111100111110011000100001010111110010001010100001010001011101101110010011001010000101011110101100001100001111011101010100001001101100100110001101000000110111000111001100001000110000011011100000100011100100110101101000101111011110001100110010001111111010101110111111010110010111001";
$parts = str_split($content, 32);
for ($i = 0; $i < count($parts); ++$i) {
$parts[$i] = bindec($parts[$i]);
}
print_r($parts);

PHP working with huge numbers

I am writing an application that can stream videos. It requires the filesize of the video, so I use this code:
$filesize = sprintf("%u", filesize($file));
However, when streaming a six gig movie, it fails.
Is is possible to get a bigger interger value in PHP? I don't care if I have to use third party libraries, if it is slow, all I care about is that it can get the filesize properly.
FYI, $filesize is currently 3017575487 which is really really really really far from 6000000000, which is roughly correct.
I am running PHP on a 64 bit operating system.
Thanks for any suggestions!
The issue here is two-fold.
Problem 1
The filesize function returns a signed integer, with a maximum value of PHP_INT_MAX. On 32-bit PHP, this value is 2147483647 or about 2GB. On 64-bit PHP can you go higher, up to 9223372036854775807. Based on the comments from the PHP filesize page, I created a function that will use a fseek loop to find the size of the file, and return it as a float, which can count higher that a 32-bit unisgned integer.
function filesize_float($filename)
{
$f = fopen($filename, 'r');
$p = 0;
$b = 1073741824;
fseek($f, 0, SEEK_SET);
while($b > 1)
{
fseek($f, $b, SEEK_CUR);
if(fgetc($f) === false)
{
fseek($f, -$b, SEEK_CUR);
$b = (int)($b / 2);
}
else
{
fseek($f, -1, SEEK_CUR);
$p += $b;
}
}
while(fgetc($f) !== false)
{
++$p;
}
fclose($f);
return $p;
}
To get the file size of the file as a float using the above function, you would call it like this.
$filesize = filesize_float($file);
Problem 2
Using %u in the sprintf function will cause it to interpret the argument as an unsigned integer, thus limiting the maximum possible value to 4294967295 on 32-bit PHP, before overflowing. Therefore, if we were to do the following, it would return the wrong number.
sprintf("%u", filesize_float($file));
You could interpret the value as a float using %F, using the following, but it will result in trailing decimals.
sprintf("%F", filesize_float($file));
For example, the above will return something like 6442450944.000000, rather than 6442450944.
A workaround would be to have sprintf interpret the float as a string, and let PHP cast the float to a string.
$filesize = sprintf("%s", filesize_float($file));
This will set $filesize to the value of something like 6442450944, without trailing decimals.
The Final Solution
If you add the filesize_float function above to your code, you can simply use the following line of code to read the actual file size into the sprintf statement.
$filesize = sprintf("%s", filesize_float($file));
As per PHP docuemnation for 64 bit platforms, this seems quite reliable for getting the filesize of files > 4GB
<?php
$a = fopen($filename, 'r');
fseek($a, 0, SEEK_END);
$filesize = ftell($a);
fclose($a);
?>

PHP Reads wrong data

I'm reading a binary file in PHP:
$File = fopen('simplefile', 'rb');
// Random stuff
fseek($File, $APosition);
for($I = 0; $I < 10; $I ++ ){
var_dump(unpack('V', fread($File, 4)));
}
fclose($File);
However this does not give correct output for that position (it is giving 6357101 not 4294967295 as expected - I've checked using a hex editor).
However, this work and gives the correct values:
$File = fopen('simplefile', 'rb');
// Random stuff
fseek($File, $APosition);
for($I = 0; $I < 10; $I ++ ){
fseek($File, ftell($File)); // What is this line doing?
var_dump(unpack('V', fread($File, 4)));
}
fclose($File);
This however, I don't understand as surely fseek($File, ftell($File)); does absolutely nothing? What is that line doing and how can I read the correct values without errors?
This segment of the file is just 0xFF repeated several hundred times.
I set up a file of all FF bytes, and the loop correctly reads -1 ten times, which is 4294967295 unsigned. I can't reproduce the value you get.
The value you are getting, 6357101, corresponds to the bytes 6D 00 61 00. That is the characters 'ma' encoded in UTF-16, although it could also mean other things.
I think the file or the content of the file is not what you think it is, or you are reading from the wrong place.
fseek($File, ftell($File)); // What is this line doing?
It should do nothing. If it doesn't do nothing I can only speculate that perhaps the file is corrupt on disk, or your copy of PHP is borked, or your computer has gone quietly mad.
If you dont use that line, that mean, you are still reading the first 4 Bytes in Loop. You need do seek.
sometxtfile.txt
aaaabbbbcccc
Without that line it ould be like:
This will return aaaaaaaaaaaa:
$File = fopen('sometxtfile.txt', 'rb');
echo fread($File, 4);
echo fread($File, 4);
echo fread($File, 4);
With that line it is like:
This will return aaaabbbbcccc:
$File = fopen('sometxtfile.txt', 'rb');
echo fread($File, 4);
fseek($File, ftell($File));
echo fread($File, 4);
fseek($File, ftell($File));
echo fread($File, 4);
fseek($File, ftell($File));
See PHP documentation for further info.

Writing Hex data to a file

i am trying a piece of code.
<?php
$tmp = ord('F'); //gives the decimal value of character F (equals 70)
$tmp = $tmp - 55; //gives 15 - decimal equivalent of 0x0F
$tmp = dechex($tmp); // converts 15 to 0x0F
$fp = fopen("testing.data","wb+");
fwrite($fp,$tmp);
fclose($fp);
?>
When i open the file called testing.data in a hex editor, i see 2 bytes written. The 2 bytes are 0x36 and 0x33.
I am expecting that only 1 byte i.e. 0x0f will be written to the file. This doesn't happen.
Please help me out with this.
If you want to write the byte 0x0f to the file, simply write the character with that ASCII code. You effectively want to undo ord, and the reverse function is chr:
<?php
$tmp = ord('F'); //gives the decimal value of character F (equals 70)
$tmp = $tmp - 55; //gives 15 - decimal equivalent of 0x0F
$tmp = chr($tmp); // converts 15 to a character
$fp = fopen("testing.data","wb+");
fwrite($fp,$tmp);
fclose($fp);
?>
You are writing the string representation of the number 0x0F to the file (which will use 1 byte per character).
In PHP you would use the pack function to create binary strings.
$bindata = pack('n', 0x0F);
file_put_contents('testing.data', $bindata);

PHP read binary file in real binary

I searched google for my problem but found no solution.
I want to read a file and convert the buffer to binary like 10001011001011001.
If I have something like this from the file
bmoov���lmvhd�����(tF�(tF�_�
K�T��������������������������������������������#���������������������������������trak���\tkh
d����(tF�(tF������� K������������������������������������������������#������������$edts��
How can I convert all characters (including also this stuff ��) to 101010101000110010 representation??
I hope someone can help me :)
Use ord() on each byte to get its decimal value and then sprintf to print it in binary form (and force each byte to include 8 bits by padding with 0 on front).
<?php
$buffer = file_get_contents(__FILE__);
$length = filesize(__FILE__);
if (!$buffer || !$length) {
die("Reading error\n");
}
$_buffer = '';
for ($i = 0; $i < $length; $i++) {
$_buffer .= sprintf("%08b", ord($buffer[$i]));
}
var_dump($_buffer);
$ php test.php
string(2096) "00111100001111110111000001101000011100000000101000100100011000100111010101100110011001100110010101110010001000000011110100100000011001100110100101101100011001010101111101100111011001010111010001011111011000110110111101101110011101000110010101101110011101000111001100101000010111110101111101000110010010010100110001000101010111110101111100101001001110110000101000100100011011000110010101101110011001110111010001101000001000000011110100100000011001100110100101101100011001010111001101101001011110100110010100101000010111110101111101000110010010010100110001000101010111110101111100101001001110110000101000001010011010010110011000100000001010000010000100100100011000100111010101100110011001100110010101110010001000000111110001111100001000000010000100100100011011000110010101101110011001110111010001101000001010010010000001111011000010100010000000100000011001000110100101100101001010000010001001010010011001010110000101100100011010010110111001100111001000000110010101110010011100100110111101110010010111000110111000100010001010010011101100001010011111010000101000001010001001000101111101100010011101010110011001100110011001010111001000100000001111010010000000100111001001110011101100001010011001100110111101110010001000000010100000100100011010010010000000111101001000000011000000111011001000000010010001101001001000000011110000100000001001000110110001100101011011100110011101110100011010000011101100100000001001000110100100101011001010110010100100100000011110110000101000100000001000000010010001011111011000100111010101100110011001100110010101110010001000000010111000111101001000000111001101110000011100100110100101101110011101000110011000101000001000100010010100110000001110000110010000100010001011000010000001100100011001010110001101100010011010010110111000101000011011110111001001100100001010000010010001100010011101010110011001100110011001010111001001011011001001000110100101011101001010010010100100101001001110110000101001111101000010100000101001110110011000010111001001011111011001000111010101101101011100000010100000100100010111110110001001110101011001100110011001100101011100100010100100111011"
On thing you could do is to read the file into a string variable, then print the string in your binary number representation with the use of sprintfDocs:
$string = file_get_contents($file);
for($l=strlen($string), $i=0; $i<$l; $i++)
{
printf('%08b', ord($string[$i]));
}
If you're just looking for a hexadecimal representation, you can use bin2hexDocs:
echo bin2hex($string);
If you're looking for a nicer form of hexdump, please see the related question:
How can I get a hex dump of a string in PHP?
Reading a file word-wise (32 bits at once) would be faster than byte-wise:
$s = file_get_contents("filename");
foreach(unpack("L*", $s) as $n)
$buf[] = sprintf("%032b", $n);

Categories