命令行反转字节顺序/更改字节顺序

问题描述 投票:0回答:9

我正在编写一些脚本,试图解析 Java 编写的一些数据

DataOutputStream#writeLong(...)
。由于 java 似乎总是写大端,所以我在向
od
提供字节时遇到问题。这是因为
od
始终假设字节序与您当前所在的 arch 的字节序相匹配,而我使用的是小型字节序机器。

我正在寻找一种简单的单行代码来反转字节顺序。假设您知道文件的最后 8 个字节是由上述

writeLong(...)
方法写入的长字节。我目前打印这么长的最佳尝试是

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

,但是

tac
似乎只适用于文本(很公平)。我找到了一些对
dd conv=swab
的引用,但这只能成对交换字节,而不能反转这八个字节。

有人知道这方面的好一句台词吗?

java swap endianness dataoutputstream
9个回答
13
投票

你可以使用 objcopy:

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

其中 num 为 2 或 4。


11
投票

用过dd,卢克!

dd if=sourcefile of=resultfile conv=swab

9
投票

最终求助于Perl。使用了我在 PERL One Liners:

找到的单衬管
tail -c 8 file | perl -0777e 'print scalar reverse <>' | od -t d8

0777
分隔符字符对我来说有点令人困惑,但是 debian admin 的 this 页面似乎表明它是“无记录分隔符”的占位符,触发每个字节的完整反向字节。

欢迎其他建议。

编辑:在 tac.c 的评论中找到另一个命令,我从 GNU coreutils 下载了它:

复制每个文件,或者复制标准输入(如果没有给出)或者当 遇到FILE名“-”,到标准输出用 记录顺序颠倒。记录由以下分隔符分隔 字符串的实例,如果没有给出则为换行符。默认情况下, 分隔符字符串附加到记录的末尾 文件中如下。

选项: -b, --before 分隔符附加到开头 文件中它前面的记录的名称。 -r, --regex 分隔符是正则表达式。 -s, --separator=分隔符 使用 SEPARATOR 作为记录分隔符。

要逐字节反转文件,请使用(在 bash、ksh 或 sh 中): tac -r -s '.\| ' 文件


3
投票

注意下一个版本的 GNU coreutils (>= 8.23) 将在 od 命令中添加 --endian={little,big} 选项


2
投票

我想出了这个 Perl 单行代码来将 4 字节整数从一种字节顺序转换为另一种字节顺序:

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

这在真正的 Linux 机器上可能工作得很好,但 Cygwin 最终咬了我,将二进制文件视为文本,并在每个 0x0A 字节(又名换行符)之前插入 0x0D(又名 CR)。但如果你用管道输送到

cat -
,似乎就不管它了。这对我有用:

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

2
投票

猛击:

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

为了根据

od
的输出样式更加稳健,可能需要压缩空格(在
"| sed 's/  */ /g'"
之后插入
w8
)。


1
投票

xxd
有两个标志
-e
-g
用于您的目的。

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

这样,你可以:

tail -c 8 file | xxd -e -g8

0
投票

一种简单的 Python 方法,每 4 个字节反转一次。使用较新的 Python 3.8+ 海象运算符:

import sys
while word := sys.stdin.buffer.read(4):
    sys.stdout.buffer.write(bytes(reversed(word)))

上面的内容很简单理解,但是如果你想要更紧凑的oneliner,可以将上面的脚本修改为:

python3 -c $'import sys\nwhile word := sys.stdin.buffer.read(4):\n sys.stdout.buffer.write(bytes(reversed(word)))'

注意

$''
符号假设您正在使用 bash。它允许您在 Python 命令中使用换行符。

作为示例,在标准输入上交换一些字符:

# echo ABCDEFGH | python3 -c $'import sys\nwhile word := sys.stdin.buffer.read(4):\n sys.stdout.buffer.write(bytes(reversed(word)))'
DCBAHGFE

0
投票

我发现这个命令对于将 4 字节交换为 endieness 效果很好

xxd -e 输入.bin | xxd -r > 输出_bs.bin

© www.soinside.com 2019 - 2024. All rights reserved.