前言
-
在使用 RT-Thread 时,需要对两个文件的内容进行比较,顺手写了一个测试的 MSH shell 命令,经过优化,发现功能可以使用
-
RT-Thread 下支持多种文件系统,如FAT等,可以通过 USB、串口 的 Ymodem 等协议把文件导出到电脑上进行内容的分析,如果文件一时间无法导出,需要确认两个文件内容是否相同,怎么办?就写个简单的文件内容对比测试命令即可
相关代码
- RT-Thread 的 MSH shell cmd 代码,存放的位置可以随意,如可以放在专门的测试代码目录的文件中,或者main.c 中,只有构建编译到即可
#ifdef DFS_USING_POSIX
#include <unistd.h>
#include <fcntl.h>
#endif /* DFS_USING_POSIX */
static void _buffer_dump(char *buffer, int size)
{
int i;
for(i = 0; i < size / 8; i++)
{
rt_kprintf("%02x %02x %02x %02x ",
*(buffer + i * 8),
*(buffer + i * 8 + 1),
*(buffer + i * 8 + 2),
*(buffer + i * 8 + 3));
rt_kprintf("%02x %02x %02x %02x\r\n",
*(buffer + i * 8 + 4),
*(buffer + i * 8 + 5),
*(buffer + i * 8 + 6),
*(buffer + i * 8 + 7));
}
}
int file_compare(int argc, char **argv)
{
int fd1 = -1;
int fd2 = -1;
int diff_count = 0;
int dump_line = 1;
int total_count = 0;
char *rbuf1 = RT_NULL;
char *rbuf2 = RT_NULL;
rt_kprintf("%s : argc = %d\n", __func__, argc);
if (argc < 3)
{
rt_kprintf("[Usage] : %s : file_path1 file_path2 \n", __func__);
return -1;
}
if (argc > 3)
{
dump_line = atoi(argv[3]);
}
rt_kprintf("%s : argv[0] = %s \n", __func__, argv[0]);
rt_kprintf("%s : file_path1= %s \n", __func__, argv[1]);
rt_kprintf("%s : file_path2= %s \n", __func__, argv[2]);
fd1 = open(argv[1], O_RDONLY, 0);
if (fd1 < 0)
{
rt_kprintf("%s : file_path1 open fail\n", __func__);
return -1;
}
fd2 = open(argv[2], O_RDONLY, 0);
if (fd2 < 0)
{
rt_kprintf("%s : file_path2 open fail\n", __func__);
close(fd1);
return -1;
}
rbuf1 = rt_malloc(4096);
if (!rbuf1)
{
rt_kprintf("%s : rbuf1 memory failed\n", __func__);
close(fd1);
close(fd2);
return -1;
}
rt_memset(rbuf1, 0, 4096);
rbuf2 = rt_malloc(4096);
if (!rbuf2)
{
rt_kprintf("%s : rbuf2 memory failed\n", __func__);
rt_free(rbuf1);
close(fd1);
close(fd2);
return -1;
}
rt_memset(rbuf2, 0, 4096);
rt_kprintf("%s : compare enter\n", __func__);
while (read(fd1, rbuf1, 4096) > 0)
{
total_count++;
if ((read(fd2, rbuf2, 4096) > 0))
if (rt_memcmp(rbuf1, rbuf2, 4096) != 0)
{
diff_count++;
rt_kprintf("%s : compare fail, count = %d\n", __func__, total_count);
if (dump_line > 0x00)
{
rt_kprintf("%s : dump file1 = %s \n", __func__, argv[1]);
_buffer_dump(rbuf1, 4096);
rt_kprintf("%s : dump file2 = %s \n", __func__, argv[2]);
_buffer_dump(rbuf2, 4096);
dump_line--;
}
//return -1; /* continue compare */
}
}
close(fd1);
close(fd2);
rt_kprintf("%s : compare end!\n", __func__);
rt_kprintf("%s : total_count = %d, diff_count = %d!\n", __func__, total_count, diff_count);
rt_free(rbuf1);
rt_free(rbuf2);
return 0;
}
MSH_CMD_EXPORT(file_compare, file_compare);
命令解释
-
命令的格式: file_compare file1 file2 diff_page_number
-
file1 与 file2 是 两个文件,可以有路径,没有路径就是当前 shell 运行的目录下
-
diff_page_number 默认打印一个page,这里是 4K 字节,也就是每次4K 字节进行对比,如果发现内容不相同,就打印出这4K字节的数据
运行效果
msh />file_compare output/batch_0_ts_0.bin ref_output/rf_009_CONV_005_ts_DWH_bid0.bin
file_compare : argc = 3
file_compare : argv[0] = file_compare
file_compare : file_path1= output/batch_0_ts_0.bin
file_compare : file_path2= ref_output/rf_009_CONV_005_ts_DWH_bid0.bin
file_compare : compare enter
file_compare : compare fail, count = 83
file_compare : dump file1 = output/batch_0_ts_0.bin
14 00 0f 00 17 00 02 00
00 1e 00 00 0b 04 0d 00
00 1c 00 00 14 00 18 00
07 03 10 06 0d 02 3d 00
12 12 2f 03 00 00 17 00
17 00 0c 00 14 00 01 00
00 1d 03 00 07 06 0f 00
00 13 00 00 10 00 17 00
07 0e 16 0a 0f 04 37 00
0d 15 26 08 00 00 10 00
16 00 0f 00 16 00 00 00
00 1b 00 00 0b 01 0d 00
00 1c 00 00 11 00 16 00
.....
file_compare : dump file2 = ref_output/rf_009_CONV_005_ts_DWH_bid0.bin
14 00 0f 00 17 00 02 00
00 1e 00 00 0b 04 0d 00
00 1c 00 00 14 00 18 00
07 03 10 06 0d 02 3d 00
12 12 2f 03 00 00 17 00
17 00 0c 00 14 00 01 00
00 1d 03 00 07 06 0f 00
00 13 00 00 10 00 17 00
07 0e 16 0a 0f 04 37 00
0d 15 26 08 00 00 10 00
16 00 0f 00 16 00 00 00
00 1b 00 00 0b 01 0d 00
00 1c 00 00 11 00 16 00
07 05 10 08 0c 03 3c 00
11 0e 30 02 00 00 16 00
18 00 0d 00 18 00 01 00
00 1e 02 00 07 07 10 00
.......
0d 00 00 1f 00 00 00 00
file_compare : compare fail, count = 84
file_compare : compare fail, count = 85
file_compare : compare fail, count = 86
file_compare : compare fail, count = 87
file_compare : compare fail, count = 88
file_compare : compare fail, count = 89
file_compare : compare fail, count = 90
file_compare : compare fail, count = 91
file_compare : compare fail, count = 92
file_compare : compare fail, count = 93
file_compare : compare fail, count = 94
file_compare : compare fail, count = 95
file_compare : compare fail, count = 96
file_compare : compare fail, count = 97
file_compare : compare fail, count = 98
file_compare : compare fail, count = 99
file_compare : compare fail, count = 100
file_compare : compare fail, count = 101
file_compare : compare fail, count = 102
file_compare : compare fail, count = 103
file_compare : compare fail, count = 104
file_compare : compare fail, count = 105
file_compare : compare fail, count = 106
file_compare : compare fail, count = 107
file_compare : compare fail, count = 108
file_compare : compare fail, count = 109
file_compare : compare fail, count = 110
file_compare : compare fail, count = 111
file_compare : compare fail, count = 112
file_compare : compare fail, count = 113
file_compare : compare fail, count = 114
file_compare : compare fail, count = 115
file_compare : compare fail, count = 116
file_compare : compare fail, count = 117
file_compare : compare fail, count = 118
file_compare : compare fail, count = 119
file_compare : compare fail, count = 120
file_compare : compare fail, count = 121
file_compare : compare fail, count = 122
file_compare : compare fail, count = 123
file_compare : compare fail, count = 124
file_compare : compare fail, count = 125
file_compare : compare fail, count = 126
file_compare : compare fail, count = 127
file_compare : compare fail, count = 128
file_compare : compare fail, count = 129
file_compare : compare fail, count = 130
file_compare : compare fail, count = 131
file_compare : compare fail, count = 132
file_compare : compare fail, count = 133
file_compare : compare fail, count = 134
file_compare : compare fail, count = 135
file_compare : compare fail, count = 136
file_compare : compare fail, count = 137
file_compare : compare fail, count = 138
file_compare : compare fail, count = 139
file_compare : compare fail, count = 140
file_compare : compare fail, count = 141
file_compare : compare fail, count = 142
file_compare : compare fail, count = 143
file_compare : compare fail, count = 144
file_compare : compare fail, count = 145
file_compare : compare fail, count = 146
file_compare : compare fail, count = 147
file_compare : compare fail, count = 148
file_compare : compare fail, count = 149
file_compare : compare fail, count = 150
file_compare : compare fail, count = 151
file_compare : compare fail, count = 152
file_compare : compare fail, count = 153
file_compare : compare fail, count = 154
file_compare : compare fail, count = 155
file_compare : compare fail, count = 156
file_compare : compare fail, count = 157
file_compare : compare fail, count = 158
file_compare : compare fail, count = 159
file_compare : compare fail, count = 160
file_compare : compare end!
file_compare : total_count = 160, diff_count = 78!
-
如以上,比对结果是失败的,默认把比对失败的第一个4K 大小的 buffer 二进制打印出来,可以复制出来使用文件对比工具,如 Beyond Compare 进行数据差异对比
-
两个文件内容相同时的对比结果
msh />file_compare output/batch_0_ts_0.bin ref_output/rf_009_CONV_005_ts_DWH_bid0.bin
file_compare : argc = 3
file_compare : argv[0] = file_compare
file_compare : file_path1= output/batch_0_ts_0.bin
file_compare : file_path2= ref_output/rf_009_CONV_005_ts_DWH_bid0.bin
file_compare : compare enter
file_compare : compare end!
file_compare : total_count = 160, diff_count = 0!
小结
-
熟悉 RT-Thread MSH shell cmd 命令的编写方法,如命令行后面的参数的个数、参数的处理方法
-
shell cmd 参数的个数:argc ,命令本身算一个,也就是
file_compare f1 f2
,argc = 3,其中 argv[0] = file_compare , argv[1] = f1, argv[2] = f2 -
默认 RT-Thread 的 shell cmd 长度有限制,如果命令行很长,需要在RT-Thread 中进行配置