-6

I'd like to make a binary file using PHP, i want to use that binary file to store a series of integers such as

66 23 44 55 80 258 

in form of binary to save some memory space since it supposed to be much smaller compared to text files. What i'm asking is how to write a binary file using PHP? I know that you can make a text file using file_put_contents() but how to write a binary one?

martynas
  • 12,120
  • 3
  • 55
  • 60
  • 1
    If you store each of these numbers in a 32 bits binary number, it will actually consume more space, since you need 4 bytes per binary number – Arnaud Le Blanc Apr 23 '14 at 19:10
  • 1
    What is the proposed format of your binary file? I doubt it would be much smaller than just a csv file. It may even be larger. – webbiedave Apr 23 '14 at 19:10
  • http://www.php.net/manual/en/function.chr.php, http://www.php.net/manual/en/function.pack.php – CBroe Apr 23 '14 at 19:11
  • link to similar question hope it ll help. http://stackoverflow.com/q/1845197/2695857 – dkakoti Apr 23 '14 at 19:11
  • My problem is well, how to write a binary file using a PHP. I know you can write a text file using file_put_contents() but i don't know how to make a binary file. @arnaud576875 Isn't each of these numbers bits can be limited depending on the highest number? Since the highest number is 258 i'm thinking of using only 9 bit per number so i'd need only 9*6=42 bit to store those numbers – Devon Ericko Sulistio Apr 23 '14 at 19:12
  • 1
    Unless you're doing some sort of embedded programming [and given that it's PHP that's likely not the case] you are *way* overthinking this. Shaving of a few bits and bytes at this point is going to cost you more time and effort than it is likely to ever save. http://pivotallabs.com/preemptive-optimization/ – Sammitch Apr 23 '14 at 19:18
  • The size of an integer in PHP is 32 or 64 bits, depending on your platform (and specified by PHP_INT_SIZE). Assuming 32 bits, that means that each number is gonna need 4 bytes in your file. Storing as text you will only need 2 bytes per number (3 for your 3 digit number), plus an extra byte per number - 1 for a separator character. You will use less space storing them as a CSV text file. – ElGavilan Apr 23 '14 at 19:19
  • I'm doing this for my LZW implemented compression program, i figured that it'd probably easier to put the dictionary indexes in a binary file than on a text file as a ascii chars – Devon Ericko Sulistio Apr 23 '14 at 19:20
  • I'm thinking of converting all of the integers to boolean (0 and 1), so that i can use lesser bits. So if i have a 258, it'll be converted into 100000010 which is only 9 bits – Devon Ericko Sulistio Apr 23 '14 at 19:22
  • @DevonErickoSulistio sure it'll take less space (6 integers @ 9 bits each = 54 bits vs. 6 integers @ 32 bits each = 196 bits), but is it really going to be easier to write the code that takes those 54 bits and extracts 6 9bit values from it? Not to mention the overhead of converting those values back and forth. – Kryten Apr 23 '14 at 19:24
  • That's a risk i'm willing to take i guess...alll i need is to know how to write those 54 bit into a binary file so i can use them for my program and i can't seem to find how to do that using PHP – Devon Ericko Sulistio Apr 23 '14 at 19:26
  • @DevonErickoSulistio if you convert 258 into, say, 9 discrete booleans, then you will end up with 9 bytes of data. I would go along with previous suggestions of storing your data as chars in a string, they only take up 8 bits each (UTF-8). Like someone said earlier, you are way overthinking this. – ElGavilan Apr 23 '14 at 19:31
  • Isn't that's only applies for text file? I read from a paper that if i use a binary file i can store each of the booleans as a boolean, in short i would need to use only 1 bit for 1 boolean not 1 byte – Devon Ericko Sulistio Apr 23 '14 at 19:35
  • At the lowest level all data in your file will be stored as a series of bytes (8 bits each). The number of bytes that are consumed will depend on the data type that is being stored. If you store an int, you will use 4 or 8 bytes (32 or 64 bits). If you store an ASCII char you will use 1 byte (8 bits). If you store a boolean, you will again use 1 byte or 8 bits, since that is the lowest common denominator. If you want to store 8 boolean values, you are better off storing them as a single char (8 bits) and setting/reading the value of each individual bit in that char. – ElGavilan Apr 23 '14 at 19:46
  • Also, if you're writing an LZW implementation you should probably be using something other than PHP. – ElGavilan Apr 23 '14 at 19:50
  • Hmm that's a nice idea you have, i'd probably use your idea as an alternative, but i think i'm still gonna look for a way to write them as binary bits for a while... – Devon Ericko Sulistio Apr 23 '14 at 19:55
  • I just showed you a way to do that... – ElGavilan Apr 23 '14 at 20:05

1 Answers1

2

Here is a solution:

$fHandle=fopen("sampleFile","wb");//opens for writing

//pack (signed) short ints(16 bit) in binary string (see documentation for more options)
//signed short should do for int's in range –32768 to 32767 and unsigned - 0 to 65,535
$byteArray = pack("s*", 32, 12, 14, 18, 1066);

fwrite($fHandle, $byteArray);//write data to the file
fclose($fHandle);

When you read the file:

$fHandle=fopen("sampleFile", "rb");
$bArray=fread($fHandle, filesize("sampleFile"));
$intArray=unpack("s*", $ba2);//unpack it with the same mode as you pack()'d it

echo $intArray[0];//should give 32
echo $intArray[1];//should give 12
echo $intArray[4];//should give 1066

edit: changed some strings in order to correct punctuation mistakes

user1328370
  • 401
  • 1
  • 3
  • 6