Vim Tips Wiki
(→‎Comments: probably replace script with 'xxd -i')
(Change <tt> to <code>, perhaps also minor tweak.)
(7 intermediate revisions by 6 users not shown)
Line 1: Line 1:
  +
{{TipNew
{{TipProposed
 
|id=0
+
|id=1613
|previous=0
+
|previous=1612
|next=0
+
|next=1614
|created=January 14, 2009
+
|created=2009
 
|complexity=basic
 
|complexity=basic
 
|author=
 
|author=
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
  +
Vim is not designed to edit binary files, but it is possible provided care is taken to avoid automatic formatting that might break a binary file. Vim is distributed with the <code>xxd</code> utility that provides a convenient method to dump a binary file to hex. You can edit the printable hex characters, and use <code>xxd</code> to reverse the process to write an updated binary file. It is possible to [[Improved_Hex_editing|automate the hex conversion]] but knowing how it works will give you a more versatile tool.
This function turns an xxd hexdump into the equivalent C source code.
 
   
  +
==Dumping a binary file as hex==
Source the following script, or put it in your [[vimrc]]:
 
  +
You can read a hex dump from a binary file into the current buffer. The following command inserts a hex dump of the file <code>sample.bin</code> after the line holding the cursor:
 
<pre>
 
<pre>
  +
:r !xxd sample.bin
function! Hexdump2C()
 
s/^\x\+: //
 
s/\s\s.*//
 
s/\s//g
 
s/\(..\)/\\x\1/g
 
s/.\+/"&"/
 
endfunction
 
 
</pre>
 
</pre>
   
In Vim, if the buffer contains only output from xxd, enter the following to convert the whole buffer:
+
Lines similar to the following would be inserted into the buffer:
 
<pre>
 
<pre>
  +
0000000: 0001 0203 3031 3233 0405 0607 4445 4647 ....0123....DEFG
:%call Hexdump2C()
 
 
0000010: 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f ................
 
</pre>
 
</pre>
   
  +
The left column shows the offset of the first byte on each line. The middle column shows the bytes in hex, in groups of two (in the example, the first byte is hex 00, followed by hex 01, 02, 03, 30, 31 etc). The right column shows the printable text, if any (the last byte on the first line is hex 47 which is the ASCII code for "G").
Alternatively, visually select the lines containing the xxd output, and enter:
 
<pre>
 
:call Hexdump2C()
 
</pre>
 
   
  +
You can read the <code>xxd</code> usage text into the current Vim buffer with:
==Example==
 
A small bitmap was loaded in Vim. The command
 
 
<pre>
 
<pre>
:%!xxd
+
:r !xxd --help
 
</pre>
 
</pre>
   
  +
==Generating C source for a binary file==
was executed resulting in the following:
 
  +
In a C program, you may want an array that holds data equivalent to the contents of a binary file. The following command reads a dump of file <code>sample.bin</code>, formatted as C source:
 
<pre>
 
<pre>
  +
:r !xxd -i sample.bin
0000000: 424d 9600 0000 0000 0000 7600 0000 2800 BM........v...(.
 
0000010: 0000 0100 0000 f8ff ffff 0100 0400 0000 ................
 
0000020: 0000 2000 0000 0000 0000 0000 0000 0000 .. .............
 
0000030: 0000 0000 0000 0000 0000 0000 8000 0080 ................
 
0000040: 0000 0080 8000 8000 0000 8000 8000 8080 ................
 
0000050: 0000 8080 8000 c0c0 c000 0000 ff00 00ff ................
 
0000060: 0000 00ff ff00 ff00 0000 ff00 ff00 ffff ................
 
0000070: 0000 ffff ff00 b000 0000 9000 0000 7000 ..............p.
 
0000080: 0000 0000 0000 b000 0000 9000 0000 7000 ..............p.
 
0000090: 0000 0000 0000 0d0a ........
 
 
</pre>
 
</pre>
   
  +
Using the same binary file as earlier, the result would be:
Executing
 
 
<pre>
 
<pre>
  +
unsigned char sample_bin[] = {
:%call Hexdump2C()
 
  +
0x00, 0x01, 0x02, 0x03, 0x30, 0x31, 0x32, 0x33, 0x04, 0x05, 0x06, 0x07,
  +
0x44, 0x45, 0x46, 0x47, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  +
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
  +
};
  +
unsigned int sample_bin_len = 32;
 
</pre>
 
</pre>
   
  +
==Editing binary files==
results in the following:
 
  +
Use the <code>-b</code> option to set binary mode before editing a binary file, for example:
 
<pre>
 
<pre>
  +
vim -b myfile.bin
"\x42\x4d\x96\x00\x00\x00\x00\x00\x00\x00\x76\x00\x00\x00\x28\x00"
 
"\x00\x00\x01\x00\x00\x00\xf8\xff\xff\xff\x01\x00\x04\x00\x00\x00"
 
"\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x80"
 
"\x00\x00\x00\x80\x80\x00\x80\x00\x00\x00\x80\x00\x80\x00\x80\x80"
 
"\x00\x00\x80\x80\x80\x00\xc0\xc0\xc0\x00\x00\x00\xff\x00\x00\xff"
 
"\x00\x00\x00\xff\xff\x00\xff\x00\x00\x00\xff\x00\xff\x00\xff\xff"
 
"\x00\x00\xff\xff\xff\x00\xb0\x00\x00\x00\x90\x00\x00\x00\x70\x00"
 
"\x00\x00\x00\x00\x00\x00\xb0\x00\x00\x00\x90\x00\x00\x00\x70\x00"
 
"\x00\x00\x00\x00\x00\x00\x0d\x0a"
 
 
</pre>
 
</pre>
   
  +
If wanted, you can display nonprintable characters in hex, and you can wrap lines:
==Comments==
 
*I'm trying to extend this to include "char *buf =" and finish with a semicolon. Executing "%s/\_.\+/char *buf = &;/" results in what I want, but the following prepends "char *buf" to every line. Why? Also, how can I put the semicolon ''before'' the last newline?
 
 
<pre>
 
<pre>
  +
:setlocal display=uhex
function! Hexdump2C()
 
  +
:setlocal wrap
s/^\x\+: //
 
s/\s\s.*//
 
s/\s//g
 
s/\(..\)/\\x\1/g
 
s/.\+/"&"/
 
s/\_.\+/char *buf = &;/
 
endfunction
 
 
</pre>
 
</pre>
   
  +
In normal mode, type <code>g</code> then Ctrl-G to display the byte number at the cursor, or type a byte number then <code>go</code> to jump to that byte (for example, <code>123go</code> will jump to byte number 123). The first byte in the file has byte number 1.
Could anyone help?
 
   
  +
The following command replaces the buffer with a hex dump:
----
 
xxd itself can create output in C file style. Try the following:
 
 
<pre>
 
<pre>
:%!xxd -i %
+
:%!xxd
 
</pre>
 
</pre>
  +
[[User:GerhardHochholzer|GerhardHochholzer]] 12:36, 4 February 2009 (UTC)
 
  +
You can edit the hex bytes, then convert the file back to binary with the command:
----
 
:Oops -- I forgot to read the docs! Thanks Gerhard. So what should we do with this tip? Perhaps replace its content (remove the script) with a short statement of wanted outcome, and a couple of examples (yours and <tt>:r !xxd -i file.bin</tt>)? --[[User:JohnBeckett|JohnBeckett]] 04:27, 5 February 2009 (UTC)
 
----
 
Perhaps this is a matter of taste. "xxd -i" uses a char array whereas your function uses a string constant.<br />
 
But i try to give an answer to your question about your function and prepending "char *buf" to each line: This happens because you call your function with a range (the percent sign is the range for the whole file) and your function doesn't handle the range itself, so the function is executed for each line. See
 
 
<pre>
 
<pre>
  +
:%!xxd -r
:help :call
 
:help function-range-example
 
 
</pre>
 
</pre>
  +
So your function may look like this:
 
  +
The above command reverses the hex dump by converting the hex bytes to binary (the printable text in the right column is ignored).
<pre>
 
  +
function! Hexdump2C() range
 
  +
==See also==
:silent execute a:firstline . "," . a:lastline . 's/^\x\+: //'
 
  +
*[[VimTip1518|Improved hex editing]]
:silent execute a:firstline . "," . a:lastline . 's/\s\s.*//'
 
  +
:silent execute a:firstline . "," . a:lastline . 's/\s//g'
 
  +
==References==
:silent execute a:firstline . "," . a:lastline . 's/\(..\)/\\x\1/g'
 
  +
*{{help|23.4}}
:silent execute a:firstline . "," . a:lastline . 's/.\+/"&"/'
 
  +
:silent execute a:firstline . "," . a:lastline . 's/\_.\+/char *buf = &;/'
 
 
==Comments==
endfunction
 
</pre>
 
[[User:GerhardHochholzer|GerhardHochholzer]] 07:16, 6 February 2009 (UTC)
 
----
 
Thanks again Gerhard. Just to clarify, I'm the janitor here ... I'm just trying to clean up tips. An anon user uploaded the script, and I tweaked it a little. Since there is no essential difference between what 'xxd -i' does, and what this tip set out to achieve, my feeling is that the scripts should be removed, and a brief explanation of what xxd does inserted. --[[User:JohnBeckett|JohnBeckett]] 11:05, 6 February 2009 (UTC)
 
----
 

Revision as of 06:38, 13 July 2012

Tip 1613 Printable Monobook Previous Next

created 2009 · complexity basic · version 7.0


Vim is not designed to edit binary files, but it is possible provided care is taken to avoid automatic formatting that might break a binary file. Vim is distributed with the xxd utility that provides a convenient method to dump a binary file to hex. You can edit the printable hex characters, and use xxd to reverse the process to write an updated binary file. It is possible to automate the hex conversion but knowing how it works will give you a more versatile tool.

Dumping a binary file as hex

You can read a hex dump from a binary file into the current buffer. The following command inserts a hex dump of the file sample.bin after the line holding the cursor:

:r !xxd sample.bin

Lines similar to the following would be inserted into the buffer:

0000000: 0001 0203 3031 3233 0405 0607 4445 4647  ....0123....DEFG
0000010: 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f  ................

The left column shows the offset of the first byte on each line. The middle column shows the bytes in hex, in groups of two (in the example, the first byte is hex 00, followed by hex 01, 02, 03, 30, 31 etc). The right column shows the printable text, if any (the last byte on the first line is hex 47 which is the ASCII code for "G").

You can read the xxd usage text into the current Vim buffer with:

:r !xxd --help

Generating C source for a binary file

In a C program, you may want an array that holds data equivalent to the contents of a binary file. The following command reads a dump of file sample.bin, formatted as C source:

:r !xxd -i sample.bin

Using the same binary file as earlier, the result would be:

unsigned char sample_bin[] = {
  0x00, 0x01, 0x02, 0x03, 0x30, 0x31, 0x32, 0x33, 0x04, 0x05, 0x06, 0x07,
  0x44, 0x45, 0x46, 0x47, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
unsigned int sample_bin_len = 32;

Editing binary files

Use the -b option to set binary mode before editing a binary file, for example:

vim -b myfile.bin

If wanted, you can display nonprintable characters in hex, and you can wrap lines:

:setlocal display=uhex
:setlocal wrap

In normal mode, type g then Ctrl-G to display the byte number at the cursor, or type a byte number then go to jump to that byte (for example, 123go will jump to byte number 123). The first byte in the file has byte number 1.

The following command replaces the buffer with a hex dump:

:%!xxd

You can edit the hex bytes, then convert the file back to binary with the command:

:%!xxd -r

The above command reverses the hex dump by converting the hex bytes to binary (the printable text in the right column is ignored).

See also

References

Comments