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

Posted

技术标签:

【中文标题】将文件转换为 C/C++ 源代码数组的脚本/工具【英文标题】:script/tool to convert file to C/C++ source code array 【发布时间】:2012-02-01 04:37:21 【问题描述】:

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


(这个问题之前被删除了。我把这个问题放回去了,因为它很有价值。我在谷歌上搜索这个并没有找到任何东西。当然自己编写代码很简单,但我会保存一些如果我能找到这么简单的脚本,几分钟就可以了。因此它很有价值。

这个问题也有很多反对票,没有太多解释。请在投反对票之前发表评论,为什么您认为这没有价值或价值不高。

这个问题也让我对我所问的问题产生了很多困惑。如果有不清楚的地方,请询问。我真的不知道如何说得更清楚。有关示例,请参阅答案。

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

【问题讨论】:

可能人们明白你想要某种反编译器或类似的东西。您可以将其改写为“读取二进制文件并输出初始化为文件内容的数组的 C/C++ 声明”或类似的内容。 【参考方案1】:

在 Debian 和其他 Linux 发行版上默认安装(连同 vimxxd 工具,如果使用 -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;

【讨论】:

啊,太好了!它甚至可以在 MacOSX 中使用。 在 Windows 上将 xxd 集成到 Visual Studio 2013 解决方案中的问题为零。我用this source 唯一的问题可能是,这个数组不是 const (以及长度)。这可能会对微控制器(RAM 与 ROM)产生影响。您可能需要编辑生成的文件。 @TomaszGandor:是的,虽然从我看到的例如AVR 微控制器const 还不够,如果您希望它们留在闪存中,您必须添加供应商特定属性(gcc 中的PROGMEM);我担心这种情况对于通用工具来说可能过于具体,您可能需要编写一个特定的构建脚本。 @MatteoItalia - 我同意。我已经把它包装好了,所以这是通过| sed 's/unsigned/const unsigned/' 输出的管道,它可以在这一行中说出你需要的任何其他内容。 (我把结果放到一个单独的文件中 - 很容易被覆盖)。【参考方案2】:

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

【讨论】:

我使用了这个答案,而不是自己写。它缺少很多格式,.h 文件可以使用一些#ifdef 保护来防止多重包含,但它有效。 +1 工作。【参考方案3】:

一个简单的工具可以找到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");

【讨论】:

您将在字符数组末尾的“”之前有额外的“,” 这不是问题,它可以用 C++ 编译。【参考方案4】:

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

【讨论】:

【参考方案7】:

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

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 位值。

【讨论】:

以上是关于将文件转换为 C/C++ 源代码数组的脚本/工具的主要内容,如果未能解决你的问题,请参考以下文章

在 C/C++ 中将 1 位 bmp 文件转换为数组 [关闭]

前端例程:文件转十六进制数组工具

将 C/C++ 向量快速转换为 Numpy 数组

如何将表列转换为数组?

将 char 数组转换为 uint16_t 数组 C/C++

如何将文本文档批量拆分为变量