在bash
我能做到
strings someBinaryfile.exe
表示.exe
(或.dll
或.so
),它只打印二进制文件的人类可读部分。
java
中是否有类似的库。我知道如何打开文件并进行打印,但我只需要人类可读的部分。
答案 0 :(得分:2)
我不知道任何预先存在的Java库完全复制strings
的功能。如果您想考虑自己实施,那么我们可以阅读Linux man page for strings以更好地了解要求:
对于给定的每个文件,GNU字符串打印可打印字符 长度至少为4个字符的序列(或给定的数字 使用下面的选项),然后是一个不可打印的字符。
因此,如果您想在纯Java代码中实现自己的解决方案,那么您可以读取文件的每个字节,检查该字节是否可打印,并将这些字节的序列存储在缓冲区中。然后,一旦遇到不可打印的字符,如果缓冲区包含至少4个字节,则打印缓冲区的内容。例如:
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;
class Strings {
private static final int MIN_STRING_LENGTH = 4;
public static void main(String[] args) throws IOException {
for (String arg : args) {
File f = new File(arg);
if (!f.exists()) {
System.err.printf("error: no such file or directory: %s%n", arg);
continue;
}
if (!f.canRead()) {
System.err.printf("error: permission denied: %s%n", arg);
continue;
}
if (f.isDirectory()) {
System.err.printf("error: path is directory: %s%n", arg);
continue;
}
try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(f));
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
for (int b = is.read(); b != -1; b = is.read()) {
if (b >= 0x20 && b < 0x7F) {
os.write(b);
} else {
if (os.size() >= MIN_STRING_LENGTH) {
System.out.println(new String(os.toByteArray(), "US-ASCII"));
}
os.reset();
}
}
if (os.size() >= MIN_STRING_LENGTH) {
System.out.println(new String(os.toByteArray(), "US-ASCII"));
}
}
}
}
}
这将涵盖strings
功能的基本近似值,但还需要考虑进一步的细节:
默认情况下,它只打印初始化和加载的字符串 目标文件的部分;对于其他类型的文件,它打印 整个文件中的字符串。
实现此部分变得更加复杂,因为您需要解析和理解二进制文件格式的不同部分,例如ELF或Windows PE。
另一个复杂因素是字符编码:
-e编码 --encoding = encoding选择要查找的字符串的字符编码。编码的可能值是:s = 单个7位字节字符(ASCII,ISO 8859等,默认),S = 单个8位字节字符,b = 16位bigendian,l = 16位 littleendian,B = 32位bigendian,L = 32位littleendian。有用 用于查找宽字符串。 (例如,l和b适用于 Unicode UTF-16 / UCS-2编码)。
我上面描述的更简单的逻辑假定单字节字符。如果您需要使用多字节字符识别编码中的字符串,那么逻辑将需要更加小心地管理缓冲区,检查可打印性和检查字符串长度。
您可以将许多其他参数传递给strings
,所有这些都在手册页中进行了描述。如果您需要完全重现所有这些功能,那么它将使逻辑更加复杂。
如果您不想实现它,那么您可以直接通过ProcessBuilder
类分叉并执行strings
并解析输出。权衡的是,它引入了一个外部依赖项,您的代码必须在安装了strings
的平台上运行,并且会产生一些开销来分叉和执行外部进程。根据具体情况,您的申请可能会或可能不会接受这种权衡。