如何将二进制文件转换为声明具有该内容的C/C++数组的文本?

jjjwad0x  于 2023-05-16  发布在  C/C++
关注(0)|答案(9)|浏览(179)

我需要在我的C/C源代码中包含一个二进制文件的内容,作为声明一个初始化为该文件内容的数组的文本。我不希望在运行时动态读取文件。我想执行一次该操作,然后使用生成的数组声明文本。
如何将二进制文件转换为数组的C/C
声明文本,该数组已初始化为文件的内容?

ars1skjm

ars1skjm1#

在Debian和其他Linux发行版上,默认情况下安装了xxd工具(沿着vim),给定-i选项,它可以执行您想要的操作:

matteo@teodeb:~/Desktop$ echo Hello World\! > temp
matteo@teodeb:~/Desktop$ xxd -i temp 
unsigned char temp[] = {
  0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21,
  0x0a
};
unsigned int temp_len = 13;
7fhtutme

7fhtutme2#

如果你在一个类似 * nix的系统上,使用xxd工具的公认答案是很好的。下面是一个“一行程序”,适用于任何在路径上具有python可执行文件的系统:

python -c "import sys;a=sys.argv;open(a[2],'wb').write(('const unsigned char '+a[3]+'[] = {'+','.join([hex(b) for b in open(a[1],'rb').read()])+'};').encode('utf-8'))" <binary file> <header file> <array name>

< binary file >是要转换为C头文件的文件名,< header file >是头文件的名称,是< array name >希望数组具有的名称。
上面的单行Python命令与下面的Python程序(可读性更强)大致相同:

import sys

with open(sys.argv[2],'wb') as result_file:
  result_file.write(b'const char %s[] = {' % sys.argv[3].encode('utf-8'))
  for b in open(sys.argv[1], 'rb').read():
    result_file.write(b'0x%02X,' % b)
  result_file.write(b'};')
yuvru6vn

yuvru6vn3#

可以找到一个简单的工具here

#include <stdio.h>
#include <assert.h>

int main(int argc, char** argv) {
    assert(argc == 2);
    char* fn = argv[1];
    FILE* f = fopen(fn, "rb");
    printf("char a[] = {\n");
    unsigned long n = 0;
    while(!feof(f)) {
        unsigned char c;
        if(fread(&c, 1, 1, f) == 0) break;
        printf("0x%.2X,", (int)c);
        ++n;
        if(n % 10 == 0) printf("\n");
    }
    fclose(f);
    printf("};\n");
}
nbnkbykc

nbnkbykc4#

我检查了所有可用的选项,并决定制作自己的小程序来进行转换:
https://github.com/TheLivingOne/bin2array/blob/master/bin2array.c
它的工作速度比bin 2c甚至xxd都要快得多,这对于较大的文件很重要,特别是如果你想将转换嵌入到你的构建系统中。例如,对于我机器上的50 Mb文件:
bin2c.py > 20秒
简单的Python脚本-大约10秒
xxd -约3秒
bin 2array-约0.4秒
此外,它产生更紧凑的输出,并添加对齐数组,如果你想把32或64位值。

s4n0splo

s4n0splo5#

现在有几个应用程序,也许在提出这个问题的时候还没有。因此,我想在这里列出我所知道的当前潜在解决方案。
可执行文件和库:

  • Binary to Header(原生和Python命令行可执行文件)
  • File To C Array(GUI工具,但包含库)
  • Bin2C(仅限Windows,GUI界面工作,但我无法从命令行转换)
  • file2c(BSD和移植到一些Linux发行版)

在线工具(与问题无关,但可能对其他人有用):

wwtsj6pe

wwtsj6pe6#

此工具在C语言的开发人员命令提示符下编译。它向终端生成输出,显示所创建的“array_name.c”文件中的内容。请注意,某些终端可能会显示“\B”字符。

#include <stdio.h>
    #include <assert.h>

    int main(int argc, char** argv) {
    assert(argc == 2);
    char* fn = argv[1];

    // Open file passed by reference
    FILE* f = fopen(fn, "rb");
    // Opens a new file in the programs location
    FILE* fw = fopen("array_name.c","w");

    // Next two lines write the strings to the console and .c file
    printf("char array_name[] = {\n");
    fprintf(fw,"char hex_array[] = {\n");

    // Declare long integer for number of columns in the array being made
    unsigned long n = 0;

    // Loop until end of file
    while((!feof(f))){
        // Declare character that stores the bytes from hex file
        unsigned char c;

        // Ignore failed elements read
        if(fread(&c, 1, 1, f) == 0) break;
        // Prints to console and file, "0x%.2X" ensures format for all
        // read bytes is like "0x00"
        printf("0x%.2X,", (int)c);
        fprintf(fw,"0x%.2X,", (int)c);

        // Increment counter, if 20 columns have been made, begin new line
        ++n;
        if(n % 20 == 0){
            printf("\n");
            fprintf(fw,"\n");
        }
    }

    // fseek places cursor to overwrite extra "," made from previous loop
    // this is for the new .c file. Since "\b" is technically a character
    // to remove the extra "," requires overwriting it.
    fseek(fw, -1, SEEK_CUR);

    // "\b" moves cursor back one in the terminal
    printf("\b};\n");
    fprintf(fw,"};\n");
    fclose(f);
    fclose(fw);
}
whlutmcx

whlutmcx7#

这是一个二进制文件到C数组生成器的python源代码,与Albert's answer中的程序完全相同。

import sys
from functools import partial

if len(sys.argv) < 2:
  sys.exit('Usage: %s file' % sys.argv[0])
print("char a[] = {")
n = 0
with open(sys.argv[1], "rb") as in_file:
  for c in iter(partial(in_file.read, 1), b''):
    print("0x%02X," % ord(c), end='')
    n += 1
    if n % 16 == 0:
      print("")
print("};")
oipij1gg

oipij1gg8#

这个问题是老的,但让我建议简单的工具,可以作为替代...
您可以使用基于GUI的工具,称为流体。它实际上用于设计FLTK工具包的接口,但也可以从二进制文件生成C++的无符号字符数组。从muquit下载

0wi1tuuw

0wi1tuuw9#

可以使用ld。参考https://github.com/termux/termux-packages/issues/16429#issuecomment-1541466535。我将其重新组织为an article

相关问题