将文件转换为C / C ++源代码数组的脚本/工具


78

我需要一个脚本/工具来读取二进制文件并输出一个C / C ++源代码数组(代表文件内容)。有吗


(这个问题已被删除,因为它很有价值,所以我把它放回去。因为我当时在Google上搜索了这个问题,却没有发现任何东西。会发现这样一个简单的脚本,因此很有价值。

这个问题也有很多不赞成解释的不赞成票。在拒绝投票之前,请先评论一下为什么您认为这没有价值或价值不高。

这个问题也引起了我的疑问。如果不清楚,请询问。我真的不知道如何弄清楚。有关示例,请参见答案。

另外(在这里提问之后),我已经有几个答案。我只想(再次)将它们放在此处/链接,因为我认为这可能对其他搜索此对象的人有用。)


4
可能人们知道您想要某种反编译器或类似的东西。您可以将其改写为“读取二进制文件并输出初始化为文件内容的数组的C / C ++声明”或类似的内容。
Matteo Italia'1

Answers:


134

在Debian和其他Linux发行版上(默认情况下vim)安装了该xxd工具,该工具(提供此-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;

6
很好!它甚至在MacOSX中可用。
艾伯特

2
在Windows上将xxd集成到Visual Studio 2013解决方案中,零麻烦。我使用了此来源
Spike0xff

2
唯一的问题可能是该数组不是const(以及长度)。这可能会影响微控制器(RAM与ROM)。您可能需要编辑生成的文件。
Tomasz Gandor

1
@TomaszGandor:是的,尽管从我所见,例如AVR微控制器const还不够,但是如果您希望它们保留在闪存中,则必须添加特定于供应商的属性(PROGMEM在gcc中);我担心这种情况对于通用工具而言可能太具体了,您可能会想要编写一个特定的构建脚本。
Matteo Italia

3
@MatteoItalia-我同意。我把它包装好了,这样| sed 's/unsigned/const unsigned/'就可以通过输出管道输出,它可以说出这一行中您需要的任何内容。(我将结果放入一个单独的文件中-以便轻松覆盖)。
Tomasz Gandor

6

一个简单的工具可以在这里找到:

#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");
}

在char数组的末尾“}”之前,您将有多余的“,”
rkosegi 2013年

1
没问题,它可以用C ++编译。
sashoalm

4

如果您在类似* 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>

<二进制文件>是要转换为C标头的文件的名称,<标头文件>是标头文件的名称,而<数组名称>是希望数组具有的名称。

上面的单行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'};')

1
我用这个答案而不是自己写。它缺少很多格式,并且.h文件可以使用#ifdef保护以防止多重包含,但是它可以工作。+1工作。
cmm

0

该工具在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);
}

0

这是C数组生成器python源代码的二进制文件,与Albert的答案中的程序相同。

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("};")

0

这个问题很老了,但让我建议一个简单的工具,它可以作为替代...

您可以使用基于GUI的工具Fluid。它实际上用于设计FLTK工具包的接口,但也可以从二进制文件生成C ++的无符号字符数组。从muquit下载。

流畅的屏幕截图


0

我检查了所有可用的选项,并决定制作自己的小程序进行转换:

https://github.com/TheLivingOne/bin2array/blob/master/bin2array.c

它的运行速度比bin2c甚至xxd快得多,这对于较大的文件来说非常重要,尤其是如果要将转换嵌入到构建系统中时。例如在我的机器上为50 Mb的文件:

bin2c.py> 20秒

简单的Python脚本-大约10秒

xxd-大约3秒

bin2array-大约0.4秒

此外,如果您想在其中放置32或64位值,它还会产生更紧凑的输出并为数组添加对齐方式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.