|
在linux下用vim打開jpg文件,使用%!xxd進(jìn)行16進(jìn)制顯示時,文件頭顯示為"3f3f
3f3f 0011 0804"文件尾端顯示為 "3f3f 0a";而同樣的操作在windows下,就顯示為"ffd8 ffc0 0011 0804"和 "ffd9 0a",這才是正確的jpeg文件頭和文件尾標(biāo)志。 很蹊蹺 ! 初時,我以為是jpeg在windows和linux下是不同的文件頭,后來把jpg后綴去掉,就一個純文件,現(xiàn)象依舊。考慮可能不是操作系統(tǒng)的差異了。 重新使用ghex打開jpeg數(shù)據(jù)查看,發(fā)現(xiàn)顯示正常,為"ffd8 ffc0 0011 0804"和 "ffd9 0a",正確。 估計應(yīng)該是vim的問題了。 3f的ascii碼是?,那表示vim對文件頭、尾沒有正常解析,是不是和vim解析文件時用的編碼格式有關(guān)系呢? 打開.vimrc配置項,屏蔽掉下面這句話: set fileencodings=utf-8,gb2312,gbk,gb18030,ucs-bom 再用vim打開jpeg文件,顯示"ffd8 ffc0 0011 0804"和 "ffd9 0a", 顯示正確。 原來,為了支持識別和顯示中文,我規(guī)定了vim的fileencodings, 當(dāng)vim打開文件時,會使用規(guī)定的編碼格式對數(shù)據(jù)進(jìn)行解析,可惜jpeg的文件頭FFD8、尾FFD9 不是任何一個中文的編碼,vim找不到對應(yīng)的中文字,就顯示為??,即:3f3f。 至此,困惑全部打開。
通常來說文件分為文本和二進(jìn)制文件兩大類,文本文件的編輯很容易,Windows下的notepad、UltraEdit都很好用,二進(jìn)制文件的編輯在Windows下也有很多工具,UltraEdit也不錯,但是Linux下呢?今天終于發(fā)現(xiàn)了一個好方法,但是最終出處找不到了。
首先創(chuàng)建一個二進(jìn)制文件:
注意echo 一定要跟上 -n 選項,否則會被自動加上一個換行行,再用vim打開 test.bin
vim 的 -b 選項是告訴 vim 打開的是一個二進(jìn)制文件,不指定的話,會在后面加上 0x0a ,即一個換行符。
在命令模式下鍵入:
如果 vim 后面沒有加 -b 選項就會出現(xiàn)可惡的 0x0a:
如果有 -b 選項就不會有這種情況:
然后進(jìn)入編輯模式改,改就是了,我將A、B對應(yīng)的41、42改成61、62,將a、b對應(yīng)的61、62改成41、42。
回到命令模式輸入:
此時可以發(fā)現(xiàn)AB和ab的位置互換了。
最后在命令模式中輸入 :wq 保存退出即可。
-----------------------------------------------------------------------------------------------------------
vim可以很方便地編輯二進(jìn)制文件,個人認(rèn)為它比emacs的二進(jìn)制編輯方式更好用。vim中二進(jìn)制文件的編輯是先通過外部程序xxd來把文件dump成其二進(jìn)制的文本形式,然后就可以按通常的編輯方式對文件進(jìn)行編輯,編輯完成后再用xxd 轉(zhuǎn)化為原來的形式即可。 可分如下幾步進(jìn)行: (1) 首先以二進(jìn)制方式編輯這個文件: vim -b datafile (2) 現(xiàn)在用 xxd 把這個文件轉(zhuǎn)換成十六進(jìn)制: :%!xxd 文本看起來像這樣: 0000000: 1f8b 0808 39d7 173b 0203 7474 002b 4e49 ....9..;..tt.+NI 0000010: 4b2c 8660 eb9c ecac c462 eb94 345e 2e30 K,.`.....b..4^.0 0000020: 373b 2731 0b22 0ca6 c1a2 d669 1035 39d9 7;'1.".....i.59. 現(xiàn)在你可以隨心所欲地閱讀和編輯這些文本了。 Vim 把這些信息當(dāng)作普通文本來對待。修改了十六進(jìn)制部分并不導(dǎo)致可顯示字符部分的改變,反之亦然。 (3) 最后,用下面的命令把它轉(zhuǎn)換回來: :%!xxd -r 只有十六進(jìn)制部分的修改才會被采用。右邊可顯示文本部分的修改忽略不計。 xxd是linux的一個命令,vim可以通過”!”來調(diào)用外部命令,其功能就是進(jìn)行十六進(jìn)制的dump或者反之。 VIM 編輯二進(jìn)制文件 (vim手冊載錄)*23.4* 二進(jìn)制文件 你可以用 Vim 來編輯二進(jìn)制文件。Vim 本非為此而設(shè)計的,因而有若干局限。但你能讀取一個文件,改動一個字符,然后把它存盤。結(jié)果是你的文件就只有那一個字符給改了,其它的就跟原來那個一模一樣。 要保證 Vim 別把它那些聰明的竅門用錯地方,啟動 Vim 時加上 ”-b” 參數(shù): vim -b datafile 這個參數(shù)設(shè)定了 'binary' 選項。其作用是排除所有的意外副作用。例如,'textwidth' 設(shè)為零,免得文本行給擅自排版了。并且,文件一律以 Unix 文件格式讀取。 二進(jìn)制模式可以用來修改某程序的消息報文。小心別插入或刪除任何字符,那會讓程序運(yùn)行出問題。用 “R” 命令進(jìn)入替換模式。 文件里的很多字符都是不可顯示的。用 Hex 格式來顯示它們的值: :set display=uhex 另外,也可以用命令 “ga” 來顯示光標(biāo)下的字符值。當(dāng)光標(biāo)位于一個 <Esc> 字符上時,該命令的輸出看起來就像這樣: <^[> 27, Hex 1b, Octal 033 文件中也許沒那么多換行符。你可以關(guān)閉 'wrap' 選項來獲得總覽的效果: :set nowrap 字節(jié)位置要發(fā)現(xiàn)你在文件中的當(dāng)前字節(jié)位置,請用這個命令: g CTRL-G 其輸出十分冗長: Col 9-16 of 9-16; Line 277 of 330; Word 1806 of 2058; Byte 10580 of 12206 最后兩個數(shù)字就是文件中的當(dāng)前字節(jié)位置和文件字節(jié)總數(shù)。這已經(jīng)考慮了 'fileformat' 選項導(dǎo)致?lián)Q行符字節(jié)不同的影響。 要移到文件中某個指定的字節(jié),請用 “go” 命令。例如,要移到字節(jié) 2345: 2345go 使用 XXD一個真正的二進(jìn)制編輯器用兩種方式來顯示文本: 二進(jìn)制和十六進(jìn)制格式。你可以在 Vim 里通過轉(zhuǎn)換程序 “xxd” 來達(dá)到這效果。該程序是隨 Vim 一起發(fā)布的。 首先以二進(jìn)制方式編輯這個文件: vim -b datafile 現(xiàn)在用 xxd 把這個文件轉(zhuǎn)換成十六進(jìn)制: :%!xxd 文本看起來像這樣: 0000000: 1f8b 0808 39d7 173b 0203 7474 002b 4e49 ....9..;..tt.+NI
0000010: 4b2c 8660 eb9c ecac c462 eb94 345e 2e30 K,.`.....b..4^.0
0000020: 373b 2731 0b22 0ca6 c1a2 d669 1035 39d9 7;'1.".....i.59.
現(xiàn)在你可以隨心所欲地閱讀和編輯這些文本了。 Vim 把這些信息當(dāng)作普通文本來對待。修改了十六進(jìn)制部分并不導(dǎo)致可顯示字符部分的改變,反之亦然。 最后,用下面的命令把它轉(zhuǎn)換回來: :%!xxd -r 只有十六進(jìn)制部分的修改才會被采用。右邊可顯示文本部分的修改忽略不計。
--------------------------------------------------------------------------------------------------------
xxd使用手冊
目錄:
★ 命令行參數(shù)簡介 ★ xxd使用中的注意事項 ★ xxd使用舉例 . 從偏移0x10開始顯示,也就是缺省情況下的第一行不顯示 . 顯示倒數(shù)0x30個字節(jié)(缺省情況下倒數(shù)3行) . 顯示120字節(jié),連續(xù)顯示,每行20字節(jié) . 顯示120字節(jié),每行12字節(jié) . 顯示0x6c偏移開始的12個字節(jié) . 創(chuàng)建一個65537字節(jié)大小的文件,除了最后一個字節(jié)是'A',其余都是0x00 . 使用autoskip選項 . 創(chuàng)建只包含一個'A'字節(jié)的文件 . 復(fù)制輸入文件到輸出文件,且給輸出文件前部增加100字節(jié)的0x00 . 二進(jìn)制文件打補(bǔ)丁 . Read single characters from a serial line ★ 命令行參數(shù)簡介 xxd -h xxd [options] [infile [outfile]] xxd -r [options] [infile [outfile]] xxd可以創(chuàng)建給定文件或標(biāo)準(zhǔn)輸入的hexdump,也可以還原一個hexdump成以前的二進(jìn) 制文件。如果沒有指定文件或指定文件名為-,則采用標(biāo)準(zhǔn)輸入。如果沒有指定輸出 文件或指定文件名為-,則采用標(biāo)準(zhǔn)輸出。 -a toggle autoskip: A single '*' replaces nul-lines. Default off. -b 采用2進(jìn)制顯示,而不是默認(rèn)的16進(jìn)制 xxd -l 32 -b scz.sh 0000000: 00100011 00100001 00100000 00101111 01100010 01101001 #! /bi 0000006: 01101110 00101111 01110011 01101000 00001010 00100011 n/sh.# 000000c: 00001010 00100011 00100000 11001000 10100001 11010110 .# ... 0000012: 11110111 11001001 11101000 10110001 10111000 10111010 ...... 0000018: 11000101 00001010 00100011 00100000 01100011 01100001 ..# ca 000001e: 01110100 00100000 t -c cols 默認(rèn)16,-i指定時采用12,-p指定時采用30,-b指定時采用6,最大256 -c8、-c 8、-c 010是等價的,其他選項類似。 xxd -c 8 -l 32 -g 1 scz.sh 0000000: 23 21 20 2f 62 69 6e 2f #! /bin/ 0000008: 73 68 0a 23 0a 23 20 c8 sh.#.# . 0000010: a1 d6 f7 c9 e8 b1 b8 ba ........ 0000018: c5 0a 23 20 63 61 74 20 ..# cat -E 不用ASCII顯示,而采用EBCDIC編碼,不影響16進(jìn)制顯示 xxd -E -l 32 -g 1 scz.sh 0000000: 23 21 20 2f 62 69 6e 2f 73 68 0a 23 0a 23 20 c8 ......>........H 0000010: a1 d6 f7 c9 e8 b1 b8 ba c5 0a 23 20 63 61 74 20 .O7IY...E..../.. -g bytes 比較下面三種顯示方式,缺省bytes為2,指定-b時采用1。 xxd -l 32 -g 0 scz.sh 0000000: 2321202f62696e2f73680a230a2320c8 #! /bin/sh.#.# . 0000010: a1d6f7c9e8b1b8bac50a232063617420 ..........# cat xxd -l 32 -g 1 scz.sh 0000000: 23 21 20 2f 62 69 6e 2f 73 68 0a 23 0a 23 20 c8 #! /bin/sh.#.# . 0000010: a1 d6 f7 c9 e8 b1 b8 ba c5 0a 23 20 63 61 74 20 ..........# cat xxd -l 32 -g 2 scz.sh 0000000: 2321 202f 6269 6e2f 7368 0a23 0a23 20c8 #! /bin/sh.#.# . 0000010: a1d6 f7c9 e8b1 b8ba c50a 2320 6361 7420 ..........# cat -h 顯示幫助信息 -i 以C語言數(shù)組形式顯示,如果輸入來自stdin,則有所區(qū)別 unsigned char scz_sh[] = { 0x23, 0x21, 0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0xc8, 0xa1, 0xd6, 0xf7, 0xc9, 0xe8, 0xb1, 0xb8, 0xba, 0xc5, 0x0a, 0x23, 0x20, 0x63, 0x61, 0x74, 0x20 }; unsigned int scz_sh_len = 32; 注意區(qū)分下面兩條命令執(zhí)行效果的不同 xxd -l 12 -i < scz.sh 0x23, 0x21, 0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x0a, 0x23 xxd -l 12 -i scz.sh unsigned char scz_sh[] = { 0x23, 0x21, 0x20, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x0a, 0x23 }; unsigned int scz_sh_len = 12; -l len 只顯示<len>這么多字節(jié) -p 以連續(xù)的16進(jìn)制表示顯示,比較下面的不同顯示效果 xxd -u -l 32 scz.sh 0000000: 2321 202F 6269 6E2F 7368 0A23 0A23 20C8 #! /bin/sh.#.# . 0000010: A1D6 F7C9 E8B1 B8BA C50A 2320 6361 7420 ..........# cat xxd -u -l 32 -p scz.sh 2321202F62696E2F73680A230A2320C8A1D6F7C9E8B1B8BAC50A23206361 7420 -r reverse operation: convert (or patch) hexdump into binary. If not writing to stdout, xxd writes into its output file without truncating it. Use the combination -r -p to read plain hexadecimal dumps without line number information and without a particular column layout. Additional Whitespace and line-breaks are allowed anywhere. 這個選項要用的話,一定要提前測試 -seek offset When used after -r : revert with <offset> added to file positions found in hexdump. -s [+][-]seek start at <seek> bytes abs. (or rel.) infile offset. + indicates that the seek is relative to the current stdin file position (meaningless when not reading from stdin). - indicates that the seek should be that many characters from the end of the input (or if combined with + : before the current stdin file position). Without -s option, xxd starts at the current file position. -u 采用大寫16進(jìn)制字母顯示,缺省采用小寫16進(jìn)制字母 -v 顯示版本信息 ★ xxd使用中的注意事項 xxd -r has some builtin magic while evaluating line number information. If the ouput file is seekable, then the linenumbers at the start of each hexdump line may be out of order, lines may be missing, or overlapping. In these cases xxd will lseek(2) to the next position. If the output file is not seekable, only gaps are allowed, which will be filled by null- bytes. xxd -r never generates parse errors. Garbage is silently skipped. When editing hexdumps, please note that xxd -r skips everything on the input line after reading enough columns of hexadecimal data (see option -c). This also means, that changes to the printable ascii (or ebcdic) columns are always ignored. Reverting a plain (or postscript) style hexdump with xxd -r -p does not depend on the correct number of columns. Here an thing that looks like a pair of hex-digits is interpreted. xxd -s +seek may be different from xxd -s seek , as lseek(2) is used to "rewind" input. A '+' makes a difference if the input source is stdin, and if stdin's file position is not at the start of the file by the time xxd is started and given its input. The following examples may help to clarify (or further confuse!)... Rewind stdin before reading; needed because the `cat' has already read to the end of stdin. % sh -c 'cat > plain_copy; xxd -s 0 > hex_copy' < file Hexdump from file position 0x480 (=1024+128) onwards. The `+' sign means "relative to the current position", thus the `128' adds to the 1k where dd left off. % sh -c 'dd of=plain_snippet bs=1k count=1; xxd -s +128 > hex_snippet' < file Hexdump from file position 0x100 ( = 1024-768) on. % sh -c 'dd of=plain_snippet bs=1k count=1; xxd -s +-768 > hex_snippet' < file However, this is a rare situation and the use of `+' is rarely needed. the author prefers to monitor the effect of xxd with strace(1) or truss(1), whenever -s is used. ★ xxd使用舉例 .. 從偏移0x10開始顯示,也就是缺省情況下的第一行不顯示 xxd -s 0x10 scz.sh .. 顯示倒數(shù)0x30個字節(jié)(缺省情況下倒數(shù)3行) xxd -s -0x30 -g 1 scz.sh .. 顯示120字節(jié),連續(xù)顯示,每行20字節(jié) xxd -l 120 -p -c 20 scz.sh .. 顯示120字節(jié),每行12字節(jié) xxd -l 120 -c 12 -g 1 scz.sh .. 顯示0x6c偏移開始的12個字節(jié) xxd -l 12 -c 12 -g 1 -s 0x6c scz.sh .. 創(chuàng)建一個65537字節(jié)大小的文件,除了最后一個字節(jié)是'A',其余都是0x00 echo 10000: 41 | xxd -r > scz.txt od -A x -t x1 scz.txt 000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 010000 41 010001 .. 使用autoskip選項 xxd -a scz.txt 0000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ * 0010000: 41 A 注意,缺省情況下autoskip功能是關(guān)閉的,但od看樣子缺省就是打開的。 .. 創(chuàng)建只包含一個'A'字節(jié)的文件 echo '010000: 41' | xxd -r -s -0x10000 > scz_1 注意對比這些效果 echo '010: 41 42 43 44 45 46' | xxd -r -s 0 > scz_1 echo '010: 41 42 43 44 45 46' | xxd -r -s -0x10 > scz_1 等價于 echo '0: 41 42 43 44 45 46' | xxd -r -s 0 > scz_1 echo '010: 41 42 43 44 45 46' | xxd -r -s -0x12 > scz_1 執(zhí)行的時候報錯,xxd: sorry, cannot seek backwards. echo '010: 41 42 43 44 45 46' | xxd -r -s 0x10 > scz_1 等價于 echo '020: 41 42 43 44 45 46' | xxd -r -s 0 > scz_1 .. 復(fù)制輸入文件到輸出文件,且給輸出文件前部增加100字節(jié)的0x00 xxd scz_1 | xxd -r -s 100 > scz_2 od -A x -t x1 scz_2 000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 000060 00 00 00 00 41 000065 .. 二進(jìn)制文件打補(bǔ)丁 echo '0: 41 42 43 44 45 46' | xxd -r -s 0 > scz_1 od -A x -t x1 scz_1 echo '4: 47 48' | xxd -r - scz_1 od -A x -t x1 scz_1 .. Use xxd as a filter within an editor such as vim(1) to hexdump a region marked between `a' and `z'. :'a,'z!xxd .. Use xxd as a filter within an editor such as vim(1) to recover a binary hexdump marked between `a' and `z'. :'a,'z!xxd -r .. Use xxd as a filter within an editor such as vim(1) to recover one line of a hexdump. Move the cursor over the line and type: !!xxd -r .. Read single characters from a serial line xxd -c1 < /dev/term/b & stty < /dev/term/b -echo -opost -isig -icanon min 1 echo -n foo > /dev/term/b |
|
|