我需要将一个二进制文件的内容包含在我的C/C++源代码中,作为一个数组声明的文本,该数组被初始化为文件的内容。 我不想在运行时动态地读取文件。 我希望执行一次操作,然后使用生成的数组声明文本。
如何将二进制文件转换为用于C/C++数组声明的文本,该数组被初始化为文件的内容?
在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;
如果您在*nix-like系统上,使用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'};')
One simple tool can be found 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数组生成器的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("};")
这个问题虽然旧了,但是让我推荐一个简单的工具作为替代方案...
你可以使用基于GUI的工具叫做Fluid。它实际上是用于设计FLTK工具包的界面,但也可以从二进制文件生成C++的unsigned char数组。从muquit下载它。
ld
。请参考https://github.com/termux/termux-packages/issues/16429#issuecomment-1541466535。我在一篇文章中对其进行了重新组织。这个工具在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);
}
const
将不足够,您必须添加供应商特定的属性(在gcc中为PROGMEM
); 我担心这种情况对于通用工具来说可能太特定了,您可能需要编写一个特定的构建脚本。 - Matteo Italia| sed 's/unsigned/const unsigned/'
管道传递,这行代码可以包含您需要的任何其他内容。(我将结果放入一个单独的文件中 - 可以轻松地进行覆盖)。 - Tomasz Gandor