Java 等同于 bash 字符串命令的命令或子例程
Java command or sub-routine which equivalent to bash strings command
在bash
我可以做到
strings someBinaryfile.exe
对于 .exe
(或 .dll
,或 .so
),这将仅打印二进制文件的人类可读部分。
java
有没有类似的库。我知道如何打开文件并打印它,但我只需要人类可读的部分。
我不知道有任何 pre-existing Java 库完全复制了 strings
的功能。如果您想考虑自己实现它,那么我们可以阅读 Linux man page for strings 以更好地了解需求:
For each file given, GNU strings prints the printable character
sequences that are at least 4 characters long (or the number given
with the options below) and are followed by an unprintable character.
因此,如果您想用纯 Java 代码实现您自己的解决方案,那么您可以通读文件的每个字节,检查该字节是否可打印,并将这些字节的序列存储在缓冲区。然后,一旦遇到 non-printable 字符,如果缓冲区包含至少 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
功能的基本近似值,但还有更多细节需要考虑:
By default, it only prints the strings from the initialized and loaded
sections of object files; for other types of files, it prints the
strings from the whole file.
实现这部分变得更加复杂,因为您需要解析和理解二进制文件格式的不同部分,例如 ELF or Windows PE.
另一个复杂的问题是字符编码:
-e encoding
--encoding=encoding Select the character encoding of the strings that are to be found. Possible values for encoding are: s =
single-7-bit-byte characters ( ASCII , ISO 8859, etc., default), S =
single-8-bit-byte characters, b = 16-bit bigendian, l = 16-bit
littleendian, B = 32-bit bigendian, L = 32-bit littleendian. Useful
for finding wide character strings. (l and b apply to, for example,
Unicode UTF-16/UCS-2 encodings).
我上面描述的更简单的逻辑假定了 single-byte 个字符。如果您需要识别具有 multi-byte 个字符的编码中的字符串,那么逻辑将需要更加小心地管理缓冲区、检查可打印性和检查字符串长度。
您可以将许多其他参数传递给 strings
,所有这些都在手册页中进行了描述。如果您需要完全重现所有这些功能,那么它会使逻辑进一步复杂化。
如果您不想实现它,那么您可以直接通过 ProcessBuilder
class 分叉并执行 strings
并解析输出。 trade-off 是它引入了一个外部依赖项,您的代码必须 运行 在安装了 strings
的平台上,并且会产生一些开销来分叉和执行外部进程。根据具体情况,trade-off 可能会或可能不会被您的应用程序接受。
在bash
我可以做到
strings someBinaryfile.exe
对于 .exe
(或 .dll
,或 .so
),这将仅打印二进制文件的人类可读部分。
java
有没有类似的库。我知道如何打开文件并打印它,但我只需要人类可读的部分。
我不知道有任何 pre-existing Java 库完全复制了 strings
的功能。如果您想考虑自己实现它,那么我们可以阅读 Linux man page for strings 以更好地了解需求:
For each file given, GNU strings prints the printable character sequences that are at least 4 characters long (or the number given with the options below) and are followed by an unprintable character.
因此,如果您想用纯 Java 代码实现您自己的解决方案,那么您可以通读文件的每个字节,检查该字节是否可打印,并将这些字节的序列存储在缓冲区。然后,一旦遇到 non-printable 字符,如果缓冲区包含至少 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
功能的基本近似值,但还有更多细节需要考虑:
By default, it only prints the strings from the initialized and loaded sections of object files; for other types of files, it prints the strings from the whole file.
实现这部分变得更加复杂,因为您需要解析和理解二进制文件格式的不同部分,例如 ELF or Windows PE.
另一个复杂的问题是字符编码:
-e encoding --encoding=encoding Select the character encoding of the strings that are to be found. Possible values for encoding are: s = single-7-bit-byte characters ( ASCII , ISO 8859, etc., default), S = single-8-bit-byte characters, b = 16-bit bigendian, l = 16-bit littleendian, B = 32-bit bigendian, L = 32-bit littleendian. Useful for finding wide character strings. (l and b apply to, for example, Unicode UTF-16/UCS-2 encodings).
我上面描述的更简单的逻辑假定了 single-byte 个字符。如果您需要识别具有 multi-byte 个字符的编码中的字符串,那么逻辑将需要更加小心地管理缓冲区、检查可打印性和检查字符串长度。
您可以将许多其他参数传递给 strings
,所有这些都在手册页中进行了描述。如果您需要完全重现所有这些功能,那么它会使逻辑进一步复杂化。
如果您不想实现它,那么您可以直接通过 ProcessBuilder
class 分叉并执行 strings
并解析输出。 trade-off 是它引入了一个外部依赖项,您的代码必须 运行 在安装了 strings
的平台上,并且会产生一些开销来分叉和执行外部进程。根据具体情况,trade-off 可能会或可能不会被您的应用程序接受。