【发布时间】:2018-12-25 15:54:10
【问题描述】:
我想以编程方式读取二进制文件中的文本/字符串。
我的目标的确切替代方案是 Linux 中的 strings shell 命令。
当我运行strings -n 4 /bin/dd shell 命令时,它会打印 818 行文本。
我怎样才能像strings 命令那样找到二进制中的所有字符串?
我的代码使用 read 而不是 fgetc 并在找到 EOF 后为其余文本添加了打印块。
/bin/dd 可以找到 813 个词,但strings 仍然可以找到 818 个词。有什么区别?
另一个问题;您能否建议此代码的性能改进?我猜read(1) 不是最快的方法。
最新更新的代码
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
bool isPrintable(unsigned char c)
{
if(c >= 0x20 && c <= 0x7e || c == 0x09)
{
return true;
}
return false;
}
int main(int argc, char * argv [])
{
char buffer[300];
char *p = buffer;
char ch;
int fd;
if(argc < 2)
{
printf("Usage: %s file", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if(0 <= fd)
{
while(1 == read(fd, &ch, 1))
{
if(isPrintable(ch) && (p - buffer < sizeof(buffer) - 3))
{
*p++ = ch;
}
else
{
if(p - buffer >= 4) // print collected text
{
*p++ = '\n';
*p++ = '\0';
printf("%s", buffer);
}
p = buffer;
}
}
if(p - buffer >= 4) // print the rest, if any
{
*p++ = '\n';
*p++ = '\0';
printf("%s", buffer);
}
close(fd);
}
else
{
printf("Could not open %s\n", argv[1]);
return 1;
}
return 0;
}
这是mystrings 和strings 的性能测量。 strings 可以在更短的时间内找到更多的文字。
$ time ./mystrings /lib/i386-linux-gnu/libc-2.27.so | wc -l
11852
real 0m0,917s
user 0m0,271s
sys 0m0,629s
$ time strings /lib/i386-linux-gnu/libc-2.27.so | wc -l
12026
real 0m0,028s
user 0m0,027s
sys 0m0,000s
即使我使用fopen、fread、fclose 也没有那么快:
$ time ./mystrings2 /lib/i386-linux-gnu/libc-2.27.so | wc -l
11852
real 0m0,084s
user 0m0,070s
sys 0m0,004s
我也愿意接受任何有关性能改进的建议。
【问题讨论】:
-
你试过调试了吗?
-
很大程度上取决于具体的文件。
strings是binutils的一部分,因此它知道如何解析常见的可执行格式以直接获取字符串表;它仅适用于不是 ELF/dwarf/etc 的东西。需要猜测的文件,然后只查找彼此相邻的可打印字符序列。 -
OP,如果您的动机是修复代码,请花一些精力调试它。您可以使用
printf 'hello\377world' > file作为测试用例,其中strings显示两个字符串,而您的代码没有显示。 -
fgetc返回int而不是char和 @thatotherguy 有你的号码。他仔细选择了那个测试用例。想清楚。如果找不到调试器,请使用一张纸。
标签: c linux string shell binary