1 写在前面
最近博主遇到一个小需求,需要将一个bin文件转换成C语言的数组,然后在代码里面操作这个数组,进行读写操作,最后生成另一个文件。
这个需求的核心是如何将bin转换成C语言的数组形式,本文将介绍以下4种方法:
方法一、使用C语言编写一个小的工具,利用fopen/fread/fwrite等函数来完成;
方法二、利用python脚本来完成;
方法三、利用shell命令hexdump来完成;
方法四、利用shell命令xxd来完成。
2 四种方法
2.1 使用C语言编写小工具
这个比较简单,我们直接看源码:
#include
#include
#include
#include
#include
typedef unsigned char u8;
typedef unsigned int u32;
static int file_read_bin_data(char *file, u8 *buf, int size)
{
FILE *fp;
if((fp=fopen(file, "rb")) == NULL) {
printf("Can not open the file: %s \n", file);
return -1;
}
fread(buf, sizeof(u8), size, fp);
fclose(fp);
return 0;
}
static u32 file_get_bin_size(char *file)
{
u32 size = 0;
FILE *fp = fopen(file, "rb");
if (fp) {
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fclose(fp);
}
return size;
}
int file_out_handle(char *out_file, u8 *buf, u32 size)
{
FILE *fp;
int i,j,k,n;
int fd ;
char pbuf[10]={0};
char mfgimage[4096*2];
if((fp=fopen(out_file, "wa+"))==NULL) {
printf( "\nCan not open the path: %s \n", out_file);
return -1;
}
k=0;
for(i = 0; i < size; i++) {
k++;
sprintf(pbuf,"0x%02x", buf[i]);
fwrite(pbuf,strlen(pbuf),1,fp);
if(k != 16)
fwrite(", ", strlen(", "),1,fp);
else
fwrite(",", strlen(","),1,fp);
if(k == 16) {
k=0;
fwrite("\n", strlen("\n"),1,fp);
}
}
fwrite("\n", strlen("\n"),1,fp);
fclose(fp);
return 0;
}
int main(int argc, const char *argv[])
{
u8 *buf = NULL;
u32 size;
char *src_bin = NULL;
char *dst_file= NULL;
if (argc != 3) {
printf("Error param input !\r\n");
printf("Usage: %s src_bin out_file\e\n", argv[0]);
exit(1);
}
src_bin = (char *)argv[1];
dst_file = (char *)argv[2];
size = file_get_bin_size(src_bin);
buf = (u8 *)malloc(sizeof(u8) * size);
if (buf) {
file_read_bin_data(src_bin, buf, size);
file_out_handle(dst_file, buf, size);
free(buf);
}
return 0;
}
我们来测试下:
#编译生成小工具
gcc -o bin2array.exe bin2array.c
#执行转换
./bin2array test.bin test.exe
#查看原来的bin文件的内容
cat test.bin
#查看转换后的内容
cat test.exe
效果如下:
!
2.2 使用python脚本实现
见源码:
### bin file change to C array ###
import os
import sys
import struct
def read_data_from_binary_file(filename, list_data):
f = open(filename, 'rb')
f.seek(0, 0)
while True:
t_byte = f.read(1)
if len(t_byte) == 0:
break
else:
list_data.append("0x%.2x" % ord(t_byte))
f.close()
def write_data_to_text_file(filename, list_data, data_num_per_line):
f_output = open(filename, 'w+')
if ((data_num_per_line <= 0) or data_num_per_line > len(list_data)):
data_num_per_line = 16
print('data_num_per_line out of range,use default value\n')
f_output.write(' ')
for i in range(0,len(list_data)):
if ( (i != 0) and (i % data_num_per_line == 0)):
f_output.write('\n ')
f_output.write(list_data[i]+', ')
elif (i + 1)== len(list_data):
f_output.write(list_data[i])
else:
f_output.write(list_data[i]+', ')
f_output.write('\n')
f_output.close()
def bin_2_c_array(src,dest):
input_f = src
output_f = dest
data_num_per_line = 16
list_data = []
read_data_from_binary_file(input_f, list_data)
write_data_to_text_file(output_f, list_data, data_num_per_line)
if __name__ == '__main__':
bin_2_c_array(sys.argv[1], sys.argv[2])
我们测试下:
!
2.3 使用shell脚本hexdump实现
见源码:
#!/bin/bash -e
in_file=$1
out_file=$2
### below is using linux shell cmd: hexdump
out_data0=`hexdump -C $in_file | awk '{ print "0x"$2", 0x"$3", 0x"$4", 0x"$5", 0x"$6", 0x"0x$7", 0x"$8", 0x"$9", 0x"$10", 0x"$11", 0x"$12", 0x"$13", 0x"$14", 0x"$15", 0x"$16", 0x"$17","}'`
#echo "$out_data0"
# delete all strings after "0x,"
out_data1=${out_data0%%0x,*}
#echo "$out_data1"
# delete all strings after ", 0x|"
out_data2=${out_data1%%, 0x|*}
#echo "$out_data2"
echo "$out_data2" > $out_file
其核心语句就是hexdump那一行,巧妙利用hexdump的输出然后做转换,我们来看下效果:
2.4 使用shell脚本xxd实现
见源码:
#!/bin/bash -e
in_file=$1
out_file=$2
out_data0=`xxd -i -c 16 $in_file`
#echo "$out_data0"
# delete all strings before '{'
out_data1=${out_data0##*\{}
#echo "$out_data1"
# delete all strings after '}'
out_data2=${out_data1%%\}*}
#echo "$out_data2"
echo "$out_data2" > $out_file
其核心就是xxd命令的调用,我们来看下效果:
下面来一张4种方法生成的对比图:
好了,本次的分享就到这,有兴趣或者有疑问的,欢迎在评论席提出来,希望能够帮助到你。
3 更多分享
欢迎关注我的github仓库01workstation,日常分享一些开发笔记和项目实战,欢迎指正问题。
同时也非常欢迎关注我的专栏:有问题的话,可以跟我讨论,知无不答,谢谢大家。