ddを使わずにAB入れ替え

ddを使わずに上下1Byte入れ替えをするプログラムを考えてみます。
まずは実験用のバイナリ生成。

takk@deb9:~/tmp$ seq 10 | perl -ne 'print chr'>in.bin
takk@deb9:~/tmp$ hd in.bin
00000000  01 02 03 04 05 06 07 08  09 0a                    |..........|
0000000a
takk@deb9:~/tmp$ 

まずはPerlから。pack/unpack使います。

takk@deb9:~/tmp$ cat -n swab.pl
     1	open(FH,"<".shift);
     2	while(read(FH,$dat,2)){
     3		print pack("S",unpack("n",$dat));
     4	}
takk@deb9:~/tmp$ 

手っ取り早いのはエンディアン変換です。unpackでテキストに変換し、packで戻すときに上下1Byte入れ替えします。

実行結果です。

takk@deb9:~/tmp$ perl swab.pl in.bin | hd
00000000  02 01 04 03 06 05 08 07  0a 09                    |..........|
0000000a
takk@deb9:~/tmp$ 

次はruby。rubyでもエンディアン変換するだけです。

takk@deb9:~/tmp$ cat -n swab.rb
     1	a=File.binread('in.bin').unpack('v*')
     2	print a.pack('n*')
takk@deb9:~/tmp$ 

実行結果。

takk@deb9:~/tmp$ ruby swab.rb | hd
00000000  02 01 04 03 06 05 08 07  0a 09                    |..........|
0000000a
takk@deb9:~/tmp$ 

でも結局、PerlでもRubyでもバイナリをそのまま処理してません。変換が入ってます。

直接処理するには、やはりC言語でしょうか。

takk@deb9:~/tmp$ cat -n swab.c
     1	#include <stdio.h>
     2	
     3	int main(int argc, char* argv[])
     4	{
     5		int c,pre=-1;
     6		FILE *fp;
     7		fp=fopen(argv[1],"r");
     8	
     9		while((c=fgetc(fp)) != -1){
    10			if(pre != -1){
    11				printf("%c%c",c,pre);
    12				pre=-1;
    13			}else
    14				pre=c;
    15		}
    16		if(pre != -1)
    17			printf("%c",pre);
    18	
    19		return 0;
    20	}
    21	
takk@deb9:~/tmp$ 

スクリプトと違いプログラムは長くなってしまいますが、余計な変換が入らない分スッキリしています。
結果です。

takk@deb9:~/tmp$ gcc swab.c
takk@deb9:~/tmp$ ./a.out in.bin | hd
00000000  02 01 04 03 06 05 08 07  0a 09                    |..........|
0000000a
takk@deb9:~/tmp$ 

コメント

タイトルとURLをコピーしました