(一時的に、テストの目的で)Cソースコードに含めたいバイナリファイルがあるので、ファイルの内容を次のようなC文字列として取得します。
\x01\x02\x03\x04
これは、おそらくod
またはhexdump
ユーティリティを使用することによって可能ですか?必須ではありませんが、文字列が16入力バイトごとに次の行に折り返され、各行の先頭と末尾に二重引用符が含まれている場合は、さらに便利です。
文字列に埋め込まれたnull(\x00
)したがって、これらのバイトが文字列を早期に終了しないように、コードで文字列の長さを指定する必要があります。
あなたはほとんどがhexdump
であなたが望むことをすることができます、しかし私は引用符と単一のバックスラッシュをフォーマットに取得する方法を理解できませんストリング。ですから、sed
を使用して少し後処理を行います。おまけとして、各行を4つのスペースでインデントしました。 :)
hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/.*/ "&"/'
編集
Cengiz Canが指摘したように、上記のコマンドラインは短いデータラインにうまく対応していません。だからここに新しい改良版があります:
hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x //g; s/.*/ "&"/'
Malvineousがコメントで言及しているように、-v
verboseオプションをhexdump
に渡して、同じバイトの長い実行が*
に短縮されないようにする必要もあります。
hexdump -v -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x //g; s/.*/ "&"/'
xxd
にはこのためのモードがあります。 -i
/--include
オプションは:
cインクルードファイルスタイルでの出力。 xxdがstdinから読み取らない限り、完全な静的配列定義が書き込まれます(入力ファイルにちなんで名前が付けられます)。
これをファイルにダンプして#include
d、そして他の文字配列と同じようにfoo
にアクセス(またはリンク)します。また、配列の長さの宣言も含まれます。
出力は80バイトに折り返され、基本的に手動で記述したものに似ています。
$ xxd --include foo
unsigned char foo[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
0x21, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x76, 0x65,
0x72, 0x79, 0x20, 0x63, 0x75, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x21, 0x20,
0x57, 0x65, 0x6c, 0x6c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x0a
};
unsigned int foo_len = 47;
xxd
は、少し奇妙なことに、vim
ディストリビューションの一部であるため、すでに持っている可能性があります。そうでない場合は、ここで入手できます。vim
ソースから独自にツールを構築することもできます。
xxd
は適切ですが、結果は非常に冗長になり、多くのストレージスペースを必要とします。
objcopy
を使用して、実質的に同じことを達成できます。例えば.
objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 foo foo.o
次に、foo.o
をプログラムにリンクし、次の記号を使用します。
00000550 D _binary_foo_end
00000550 A _binary_foo_size
00000000 D _binary_foo_start
これは文字列リテラルではありませんが、コンパイル時に文字列リテラルが変わるのと基本的に同じです(実際には文字列literalsが存在しないことを考慮してください)実行時;実際、他の回答のいずれも実際にはコンパイル時でも文字列リテラルを提供せず)、ほとんど同じ方法でアクセスできます。
unsigned char* ptr = _binary_foo_start;
int i;
for (i = 0; i < _binary_foo_size; i++, ptr++)
putc(*ptr);
欠点は、オブジェクトファイルに互換性を持たせるためにターゲットアーキテクチャを指定する必要があることです。これは、ビルドシステムでは簡単ではない場合があります。
あなたが正確にあなたが求めたものでなければなりません:
hexdump -v -e '"\\" "x" 1/1 "%02X"' file.bin ; echo
これは私が書いた短いユーティリティであり、本質的に同じことを行います(元は Stack Overflow に投稿されていました)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 80
int main(void)
{
FILE *fout = fopen("out.txt", "w");
if(ferror(fout))
{
fprintf(stderr, "Error opening output file");
return 1;
}
char init_line[] = {"char hex_array[] = { "};
const int offset_length = strlen(init_line);
char offset_spc[offset_length];
unsigned char buff[1024];
char curr_out[64];
int count, i;
int line_length = 0;
memset((void*)offset_spc, (char)32, sizeof(char) * offset_length - 1);
offset_spc[offset_length - 1] = '\0';
fprintf(fout, "%s", init_line);
while(!feof(stdin))
{
count = fread(buff, sizeof(char), sizeof(buff) / sizeof(char), stdin);
for(i = 0; i < count; i++)
{
line_length += sprintf(curr_out, "%#x, ", buff[i]);
fprintf(fout, "%s", curr_out);
if(line_length >= MAX_LENGTH - offset_length)
{
fprintf(fout, "\n%s", offset_spc);
line_length = 0;
}
}
}
fseek(fout, -2, SEEK_CUR);
fprintf(fout, " };");
fclose(fout);
return EXIT_SUCCESS;
}
Pythonを使用している場合は、それを変数「buff」にロードして、次のようなものを使用します。
buff2 = buff.encode("hex")
print ("0x"+", 0x".join([buff2[i:i+2] for i in range(0,len(buff2),2)]))