2

How do I do something as simple as (in PHP) this code in C:

char buffer[5] = "testing";
FILE* file2 = fopen("data2.bin", "wb");
fwrite(buffer, sizeof buffer, 1, file2);
fclose(file2);

Whenever I try to write a binary file in PHP, it doesn't write in real binary.

Example:

$ptr = fopen("data2.bin", 'wb');

fwrite($ptr, "testing");

fclose($ptr);

I found on internet that I need to use pack() to do this...

What I expected:

testing\9C\00\00
or
7465 7374 696e 679c 0100 00

What I got:

testing412

Thanks

Maurício Giordano
  • 3,116
  • 4
  • 32
  • 60

1 Answers1

5

You're making the classic mistake of confusing data with the representation of that data.

Let's say you have a text file. If you open it in Notepad, you'll see the following:

hello
world

This is because Notepad assumes the data is ASCII text. So it takes every byte of raw data, interprets it as an ASCII character, and renders that text to your screen.

Now if you go and open that file with a hex editor, you'll see something entirely different1:

68 65 6c 6c 6f 0d 0a 77 6f 72 6c 64          hello..world

That is because the hex editor instead takes every byte of the raw data, and displays it as a two-character hexadecimal number.

1 - Assuming Windows \r\n line endings and ASCII encoding.


So if you're expecting hexadecimal ASCII output, you need to convert your string to its hexadecimal encoding before writing it (as ASCII text!) to the file.

In PHP, what you're looking for is the bin2hex function which "Returns an ASCII string containing the hexadecimal representation of str." For example:

$str = "Hello world!";
echo bin2hex($str);      // output:  48656c6c6f20776f726c6421

Note that the "wb" mode argument doesn't cause any special behavior. It guarantees binary output, not hexadecimal output. I cannot stress enough that there is a difference. The only thing the b really does, is guarantee that line endings will not be converted by the library when reading/writing data.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 1
    Thanks! But why PHP doesn't do that already? In C, if I put "wb" as argument on fopen, it saves everything in binary... But in PHP it seems that it is just ignored. – Maurício Giordano Jul 04 '13 at 04:27
  • 1
    @MaurícioGiordano No, C absolutely does not do what you just described. Please compile and run your C code from the question, and open the result in a *text editor*. You'll see ASCII. The `"wb"` mode does **not** do what you think it does. – Jonathon Reinhart Jul 04 '13 at 04:28
  • But it doesn't save in ASCII, because if I open with Notepad, it shows strange characters... – Maurício Giordano Jul 04 '13 at 04:29
  • 1
    Sample: char buffer[7] = "testing"; int number = 412; FILE* file2 = fopen("data2", "wb"); fwrite(buffer, 1, sizeof(buffer), file2); fwrite(&number, 1, sizeof(number), file2); fclose(file2); – Maurício Giordano Jul 04 '13 at 04:30
  • 1
    Right, you're writing an **integer** `412` to the file. So if you look at just that part in a hex editor, you're going to see `9c 01 00 00`, which is a 4-byte little-endian integer shown as four 1-byte hexadecimal numbers. If you wrote the **string** `"`char str[] = "412"`, you would see something totally different. – Jonathon Reinhart Jul 04 '13 at 04:34
  • 3
    You should really play around with this stuff until it makes *perfect sense*, as it is very fundamental to how computers and binary data work. – Jonathon Reinhart Jul 04 '13 at 04:36