开发者

Command-line to reverse byte order/change endianess

I'm hacking around in some scripts trying to parse some data written by Javas DataOutputStream#writeLong(...). Since java always seems to write big开发者_开发百科 endian, I have a problem feeding the bytes to od. This is due to the fact that od always assumes that the endianess matches the endianess of the arch that you are currently on, and I'm on a little endian machine.

I'm looking for an easy one-liner to reverse the byte order. Let's say that you know that the last 8 bytes of a file is a long written by the aforementioned writeLong(...) method. My current best attempt to print this long is

tail -c 8 file | tac | od -t d8

, but tac only seems to work on text (fair enough). I've found some references to dd conv=swab, but this only swaps bytes in pairs, and cannot reverse these eight bytes.

Does anyone know a good one-liner for this?


You could use objcopy:

$ objcopy -I binary -O binary --reverse-bytes=num inputfile.bin outputfile.bin

where num is either 2 or 4.


Resorted to Perl in the end. Used a one-liner which I found at PERL One Liners:

tail -c 8 file | perl -0777e 'print scalar reverse <>' | od -t d8

The 0777 separator char was a bit puzzling to me, but this page at debian admin seems to suggest that it is a placeholder for 'no record separator', triggering a complete reverse byte-per byte.

Other suggestions are welcome.

EDIT: Found another command in a comment to tac.c, which I downloaded from GNU coreutils:

Copy each FILE, or the standard input if none are given or when a FILE name of "-" is encountered, to the standard output with the order of the records reversed. The records are separated by instances of a string, or a newline if none is given. By default, the separator string is attached to the end of the record that it follows in the file.

Options: -b, --before The separator is attached to the beginning of the record that it precedes in the file. -r, --regex The separator is a regular expression. -s, --separator=separator Use SEPARATOR as the record separator.

To reverse a file byte by byte, use (in bash, ksh, or sh): tac -r -s '.\| ' file


Used dd, Luke!

dd if=sourcefile of=resultfile conv=swab


Note the next version of GNU coreutils (>= 8.23) will add the --endian={little,big} option to the od command


I came up with this Perl one-liner to convert 4-byte integers from one endianness to another:

$ perl -e 'open F,shift; do { read(F,$a,4); print scalar reverse($a);} while(!eof(F));' bigend.bin > littlend.bin

That probably works fine on real Linux machines, but Cygwin bit me in the end, treating the binary file as text and inserting a 0x0D (aka CR) before each 0x0A byte (aka newline). But if you pipe to cat -, it seems to leave it alone. This works for me:

$ perl -e 'open F,shift; do { read(F,$a,4); print scalar reverse($a);} while(!eof(F));' bigend.bin | cat - > littlend.bin


BASH:

od -b -v -w8 | while read pfx b8 ; do [ "$b8" ] && echo -n 12345678 | tr 87654321 \\${b8// /\\} ; done

To be a bit more robust depending on the output style of od, it may need to compress spaces ( insert "| sed 's/ */ /g'" after the w8).


xxd has two flags -e and -g for your purpose.

    -e          little-endian dump (incompatible with -ps,-i,-r).
    -g          number of octets per group in normal output. Default 2 (-e: 4).

This way, you can do:

tail -c 8 file | xxd -e -g8
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜