# Why isn't a binary file shown as 0s and 1s?

In my Mac OS, we know the files under /bin all are binary files.:

crafts-MBP:bin ldl$pwd /bin crafts-MBP:bin ldl$ ls
[       csh     ed          launchctl   mv      rmdir   tcsh
bash    date    expr        link        pax     sh      test
cat     dd      hostname    ln          ps      sleep   unlink
chmod   df      kill        ls          pwd     stty    wait4path
cp      echo    ksh         mkdir       rm      sync    zsh


When I open it using vi editor:

crafts-MBP:bin ldl$vi ps Ïúíþ^G^@^@^A^C^@^@<80>^B^@^@^@^P^@^@^@°^F^@^@<85>^@ ^@^@^@^@^@^Y^@^@^@H^@^@^@__PAGEZERO^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^Y^@^@^@(^B^@^@__TEXT^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^G^@^@^@^E^@^@^@^F^@^@^@^@^@^@^@__text^@^@^@^@^@^@^@^@^@^@__TEXT^@^@^@^@^@^@^@^@^@^@P^V^@^@^A^@^@^@\;^@^@^@^@^@^@P^V^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^D^@<80>^@^@^@^@^@^@^@^@^@^@^@^@__stubs^@^@^@^@^@^@^@^@^@__TEXT^@^@^@^@^@^@^@^@^@^@¬Q^@^@^A^@^@^@<92>^A^@^@^@^@^@^@¬Q^@^@^A^@^@^@^@^@^@^@^@^@^@^@^H^D^@<80>^@^@^@^@^F^@^@^@^@^@^@^@__stub_helper^@^@^@__TEXT^@^@^@^@^@^@^@^@^@^@@S^@^@^A^@^@^@®^B^@^@^@^@^@^@@S^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^D^@<80>^@^@^@^@^@^@^@^@^@^@^@^@__const^@^@^@^@^@^@^@^@^@__TEXT^@^@^@^@^@^@^@^@^@^@ðU^@^@^A^@^@^@P^A^@^@^@^@^@^@ðU^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@__cstring^@^@^@^@^@^@^@__TEXT^@^@^@^@^@^@^@^@^@^@@W^@^@^A^@^@^@Ó^G^@^@^@^@^@^@@W^@^@^@^@^@^@^@^@^@^@^@^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@__unwind_info^@^@^@__TEXT^@^@^@^@^@^@^@^@^@^@^T_^@^@^A^@^@^@ä^@^@^@^@^@^@^@^T_^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^Y^@^@^@x^B^@^@__DATA^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@0^@^@^@^@^@^@^@^@^@^@^@^@^@^@0^@^@^@^@^@^@^G^@^@^@^C^@^@^@^G^@^@^@^@^@^@^@__nl_symbol_ptr^@__DATA^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^P^@^@^@^@^@^@^@^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^F^@^@^@C^@^@^@^@^@^@^@^@^@^@^@__got^@^@^@^@^@^@^@^@^@^@^@__DATA^@^@^@^@^@^@^@^@^@^@^P^@^@^A^@^@^@0^@^@^@^@^@^@^@^P^@^@^C^@^@^@^@^@^@^@^@^@^@^@^F^@^@^@E^@^@^@^@^@^@^@^@^@^@^@__la_symbol_ptr^@__DATA^@^@^@^@^@^@^@^@^@^@@^@^@^A^@^@^@^X^B^@^@^@^@^@^@@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^G^@^@^@K^@^@^@^@^@^@^@^@^@^@^@__const^@^@^@^@^@^@^@^@^@__DATA^@^@^@^@^@^@^@^@^@^@b^@^@^A^@^@^@ ^@^@^@^@^@^@^@b^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@__data^@^@^@^@^@^@^@^@^@^@__DATA^@^@^@^@^@^@^@^@^@^@<80>b^@^@^A^@^@^@³!^@^@^@^@^@^@<80>b^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@__common^@^@^@^@^@^@^@^@__DATA^@^@^@^@^@^@^@^@^@^@8<84>^@^@^A^@^@^@@^@^@^@^@^@^@^@^@^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@__bss^@^@^@^@^@^@^@^@^@^@^@__DATA^@^@^@^@^@^@^@^@^@^@x<84>^@^@^A^@^@^@^Y^@^@^@^@^@^@^@^@^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^Y^@^@^@H^@^@^@__LINKEDIT^@^@^@^@^@^@^@<90>^@^@^A^@^@^@^@@^@^@^@^@^@^@^@<90>^@^@^@^@^@^@P8^@^@^@^@^@^@^G^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@"^@^@<80>0^@^@^@^@<90>^@^@<90>^A^@^@<90><91>^@^@x^@^@^@^@^@^@^@^@^@^@^@^H<92>^@^@p^D^@^@x<96>^@^@ ^@^@^@^B^@^@^@^X^@^@^@^X<97>^@^@L^@^@^@^P<9e>^@^@ ^C^@^@^K^@^@^@P^@^@^@^@^@^@^@^A^@^@^@^A^@^@^@^A^@^@^@^B^@^@^@J^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@Ø<9b>^@^@<8e>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^N^@^@^@ ^@^@^@^L^@^@^@/usr/lib/dyld^@^@^@^@^@^@^@^[^@^@^@^X^@^@^@.þLóÎá2^Dªáµ9¦S<8a>+2^@^@^@ ^@^@^@^A^@^@^@^@^N ^@^@^N  you see there shows so many @^ and some English signal, such as: __stub_helper. Why it is not shown in terms of 0 and 1? ## 4 Answers There are two interpretations of the word binary. • In terms of number system, it refers to a base 2 number system which uses two symbols, 0 and 1. • When speaking of a file, it refers to a file containing non-textual data (executables, libraries, data files etc.). A binary file that can be run as a process is called an executable binary. A file being binary file doesn't simply mean that it will be displayed simply in terms of 0's and 1's. There are layers of abstractions at work as to how files are handled by a computer. Showing a binary file in terms of 0 and 1 would make the output unnecessarily lengthy, and is not the most optimal approach. A binary file is shown in a text editor according to the default encoding set for that editor. Also, if an editor is configured to show binary output, it will also display every file, even plain text ones, in terms of 0's and 1's. Everything ultimately boils down to binary when stored in a computer. To view a file in the most basic form of 0's and 1's, you'll need to use a special editor mode which is capable of displaying the binary data of a file. One such way is using the built-in xxd command in macOS. Type the following command-line in Terminal: xxd -b filename $ xxd -b a.out | head
00000000: 11001111 11111010 11101101 11111110 00000111 00000000  ......
00000006: 00000000 00000001 00000011 00000000 00000000 10000000  ......
0000000c: 00000010 00000000 00000000 00000000 00001111 00000000  ......
00000012: 00000000 00000000 11000000 00000100 00000000 00000000  ......
00000018: 10000101 00000000 00100000 00000000 00000000 00000000  .. ...
0000001e: 00000000 00000000 00011001 00000000 00000000 00000000  ......
00000024: 01001000 00000000 00000000 00000000 01011111 01011111  H...__
0000002a: 01010000 01000001 01000111 01000101 01011010 01000101  PAGEZE
00000030: 01010010 01001111 00000000 00000000 00000000 00000000  RO....
00000036: 00000000 00000000 00000000 00000000 00000000 00000000  ......


It will display the binary dump of filename on standard output. This works equally for both binary and text files.

A more compact and commonly used form, which is preferred over binary is hexadecimal, which uses a base 16 number system (0-9, A-F). To show the contents of file filename in hexadecimal, just run the xxd command without any options with just the filename as argument in Terminal:

xxd filename

\$ xxd  a.out | head
00000000: cffa edfe 0700 0001 0300 0080 0200 0000  ................
00000010: 0f00 0000 c004 0000 8500 2000 0000 0000  .......... .....
00000020: 1900 0000 4800 0000 5f5f 5041 4745 5a45  ....H...__PAGEZE
00000030: 524f 0000 0000 0000 0000 0000 0000 0000  RO..............
00000040: 0000 0000 0100 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 0000 0000 0000 0000 1900 0000 d801 0000  ................
00000070: 5f5f 5445 5854 0000 0000 0000 0000 0000  __TEXT..........
00000080: 0000 0000 0100 0000 0010 0000 0000 0000  ................
00000090: 0000 0000 0000 0000 0010 0000 0000 0000  ................

• I use 0xED.app. suavetech.com/0xed – historystamp Jul 18 at 19:01
• For the sake of absolute clarity, it may be worth stating explicitly: every file on your computer is comprised of 0's and 1's. – Wowfunhappy Jul 18 at 23:31
• the ls file should be a file with code in it, how can I show the code text? – 244boy Jul 19 at 3:40
• @244boy The ls file is compiled code, to see the source code you need the actual source files. A lot of code is on opensource.apple.com, don‘t know whether ls is there as well. – nohillside Jul 19 at 4:14
• @nohillside ls appears to be at opensource.apple.com/source/file_cmds/file_cmds-272.220.1/ls and derived from FreeBSD – Jacob Krall Jul 19 at 17:50

Nearly all modern computers deal with bytes, instead of the individual bits. A single byte, as you may know, can store any of 256 different values; from eight zeroes to eight ones.

When you open the binary file in a text editor, it is showing you these byte-sized chunks instead of each individual bit. The symbols it picks are determined by your editor's default encoding. Often, one character in your editor corresponds to one byte in the actual file, though there are special cases.

If you see a string of readable text, such as __stub_helper, it means that particular text is stored as-is within the binary file.

The special cases I mentioned before are so-called control characters that are displayed with an escape code. Escape codes, as seen here, begin with ^ and are followed by a single additional character. This pair, such as ^@ are taken together to represent a single byte. In fact, the symbol ^@ is the value zero, meaning the bits at that location would be eight zeroes.

The reason that your text editor displays the binary file in this manner is that it simply displays all files in this manner. If you were to use a hex editor, it would display any and all files in hexadecimal instead. In fact, there's no fundamental difference between the contents of a binary file and the contents of a text file -- it's the metadata and file headers that let your computer know which is which.

Start vi in binary mode - then you can run xxd to get hex view, binary view and edit the file as you would. (Of course most of these are read-only, but that's not about the editor and more the permissions/SIP).

vi -b /bin/ps


Then to convert the buffer to bits of 1 and 0

:%!xxd -b


Then you can see all the Mach-0 executable binary goodness, right from within the editor. If you drop the b, you get the more typical hexidecimal representation that's more space efficient encoding and you don't see the values mapped as ASCII derived characters where so many values end up as ^@^@^@ when you start from a plain text centric default.

• Also, you don’t have to start vi in binary mode, it just helps with some minor settings. The :%! portion works on the entire buffer - piping it to xxd -b  doing the heavy lifting within the editor for you. – bmike Jul 19 at 1:32

The simplest answer to your question is: For efficiency. As others have said in their answers, files are displayed using a more compact notation than raw binary code, because raw binary code is unfathomably inefficient as a means of communicating data.

Take the ps program you displayed using vi. I'm not sure about the MacOS version of the command, but on my Fedora 30 system /bin/ps is a dynamically-linked executable (meaning, some of its code is loaded from other files elsewhere on the disk) which nevertheless has a file size of around 158k, or to be precise a file size of 157224 bytes.

Since each byte of memory contains 8 bits, you would need a string of eight 1 or 0 digits to display each individual byte of the /bin/ps file. Which means that, if you were to display the entire contents of the file as a string of just 1 or 0, that string would be 1257792 (that's one and a quarter million) digits long.

And that's a relatively small file! Think about the contents of a Blu-Ray disc, which can easily come in at many dozens of gigabytes. An 80 Gigabyte movie would have a pure-binary representation requiring 640 billion 1 / 0 digits.

• Efficiency is not the topic here IMHO. A byte is a byte, what we are looking at are different representations on the screen. Whether the value 65 (decimal) is shown as ’A’, 0x41 or 00100001 doesn‘t change the fact that it only needs one byte on disk (or in memory). – nohillside Jul 21 at 12:01
• @nohillside Oh, but visual efficiency is exactly the topic .I mean, despite the fact that (agreed) the three representations you mentioned have exactly the same size on disk, you only have to look at them to see how much they vary in representation — and the question was, "Why isn't the file shown as ones and zeroes?" – FeRD Jul 21 at 12:04
• They are shown as the are because vi doesn‘t care about file type, it just throws the bytes at the screen (so to speak). If you open text files with a hex editor you also won‘t see the text itself but only the hex values. – nohillside Jul 21 at 12:09
• @user3439894 Partially :-) The point was more that vi not automagically converting into a binary editor when opening a non-text file is basically the same as a (pure) hex editor not automatically turning into vi when opening a text file. Both tools have a purpose, and try to make the best out of whatever file a user throws at them. – nohillside Jul 21 at 13:17