你如何 "print" 处理不可打印值的字节数组
How do you "print" an array of bytes that handles non-printable values
我在这个论坛上看到了很多有些相关的问题和答案,但没有找到任何解决我的问题的东西。
这个想法很简单:
(这是使用 Java 编程语言 - 我目前仅限于使用 Java 7)
接收到字节数组(代表任何内容:某种有线格式、某种形式的编码数据、嵌入 "text" 的二进制数据等)。我希望能够以下列形式打印数组:
- 十六进制字符串
- 作为"printable"文本
第一种情况部分是出于调试原因,但也可能在非调试模式下使用。第二种情况纯粹是出于调试原因,可以与其他信息源进行人工比较。
我想我有第一种情况的解决方案,但第二种情况我很难解决。
显然,字节数组可能包含不可打印的字符或以不同方式呈现的字符。我如何 "print" 一个数组来表示所有字节?我可以提供的一个很好的模拟是 UNIX od
命令,其中 od -ah
以十六进制形式显示二进制数据以及 ASCII 字符。在这种情况下,点 (.
) 通常用于代替不可打印或控制字符。
我不需要它看起来像 od
输出的那样,但希望能够显示数据,以便至少可以看到可打印的字符,其余部分用一些表示某种占位符。另外,我不想删除不可打印的字符,因为那样会误导数据。
如果有人知道如何实现这一点,我将不胜感激。
试试 #2:
String original = new String(bytes);
String printable = original.replaceAll("\P{Print}", ".")); //Or any other character instead of "." you want
它使用 POSIX printable character class.
如果您需要 Unicode 支持,请使用 utf-8 字符集参数创建字符串,并使用 UNICODE_CHARACTER_CLASS 标志构造模式并使用与上述相同的正则表达式。
嗯,Arrays.toString()
适合你吗?
public class PrintBytes {
public static void main( String[] args ) {
byte[] test = { 1, 2, 3, 0, (byte)0xFF, (byte)0xFE };
String s = Arrays.toString( test );
System.out.println( s );
}
}
输出:
run:
[1, 2, 3, 0, -1, -2]
BUILD SUCCESSFUL (total time: 0 seconds)
它不是十六进制,但它是一种可用的有线格式。
为什么不使用 DatatypeConverter
这里是一个有两个数组的例子。第一个来自单词'hello',第二个是发明的
import java.nio.charset.StandardCharsets;
import javax.xml.bind.DatatypeConverter;
public class MainTest {
public static void main(String[] args) {
// Something printable
String hello = "hello";
byte[] printable = hello.getBytes(StandardCharsets.UTF_8);
System.out.println("Printable: " + new String(printable, StandardCharsets.UTF_8));
// Something not printable
byte[] notPrintable = { (byte)-156, (byte)190, (byte)56, (byte)-29, (byte)1};
System.out.println("NotPrintable: " + new String(notPrintable, StandardCharsets.UTF_8));
// With DatatypeConverter.printBase64Binary you can get a String printable from any byte[]
final String printableString = DatatypeConverter.printBase64Binary(printable);
final String notPrintableString = DatatypeConverter.printBase64Binary(notPrintable);
System.out.println("Printable string with DatatypeConverter: " + printableString);
System.out.println("Not printable string with DatatypeConverter: " + notPrintableString);
byte[] otherPrintable = DatatypeConverter.parseBase64Binary(printableString);
byte[] otherNotPrintable = DatatypeConverter.parseBase64Binary(notPrintableString);
// And the best point is that you can revert it
final String otherHello = new String(otherPrintable, StandardCharsets.UTF_8);
final String strangeString = new String(otherNotPrintable, StandardCharsets.UTF_8);
System.out.println("Other Hello: " + otherHello);
System.out.println("Strange String: " + strangeString);
}
}
这是输出
Printable: hello
NotPrintable: d�8�
Printable string with DatatypeConverter: aGVsbG8=
Not printable string with DatatypeConverter: ZL444wE=
Other Hello: hello
Strange String: d�8�
编辑:DatatypeConverter 对 java7 和 java8 有效,查看
我在这个论坛上看到了很多有些相关的问题和答案,但没有找到任何解决我的问题的东西。
这个想法很简单:
(这是使用 Java 编程语言 - 我目前仅限于使用 Java 7)
接收到字节数组(代表任何内容:某种有线格式、某种形式的编码数据、嵌入 "text" 的二进制数据等)。我希望能够以下列形式打印数组:
- 十六进制字符串
- 作为"printable"文本
第一种情况部分是出于调试原因,但也可能在非调试模式下使用。第二种情况纯粹是出于调试原因,可以与其他信息源进行人工比较。
我想我有第一种情况的解决方案,但第二种情况我很难解决。
显然,字节数组可能包含不可打印的字符或以不同方式呈现的字符。我如何 "print" 一个数组来表示所有字节?我可以提供的一个很好的模拟是 UNIX od
命令,其中 od -ah
以十六进制形式显示二进制数据以及 ASCII 字符。在这种情况下,点 (.
) 通常用于代替不可打印或控制字符。
我不需要它看起来像 od
输出的那样,但希望能够显示数据,以便至少可以看到可打印的字符,其余部分用一些表示某种占位符。另外,我不想删除不可打印的字符,因为那样会误导数据。
如果有人知道如何实现这一点,我将不胜感激。
试试 #2:
String original = new String(bytes);
String printable = original.replaceAll("\P{Print}", ".")); //Or any other character instead of "." you want
它使用 POSIX printable character class.
如果您需要 Unicode 支持,请使用 utf-8 字符集参数创建字符串,并使用 UNICODE_CHARACTER_CLASS 标志构造模式并使用与上述相同的正则表达式。
嗯,Arrays.toString()
适合你吗?
public class PrintBytes {
public static void main( String[] args ) {
byte[] test = { 1, 2, 3, 0, (byte)0xFF, (byte)0xFE };
String s = Arrays.toString( test );
System.out.println( s );
}
}
输出:
run:
[1, 2, 3, 0, -1, -2]
BUILD SUCCESSFUL (total time: 0 seconds)
它不是十六进制,但它是一种可用的有线格式。
为什么不使用 DatatypeConverter
这里是一个有两个数组的例子。第一个来自单词'hello',第二个是发明的
import java.nio.charset.StandardCharsets;
import javax.xml.bind.DatatypeConverter;
public class MainTest {
public static void main(String[] args) {
// Something printable
String hello = "hello";
byte[] printable = hello.getBytes(StandardCharsets.UTF_8);
System.out.println("Printable: " + new String(printable, StandardCharsets.UTF_8));
// Something not printable
byte[] notPrintable = { (byte)-156, (byte)190, (byte)56, (byte)-29, (byte)1};
System.out.println("NotPrintable: " + new String(notPrintable, StandardCharsets.UTF_8));
// With DatatypeConverter.printBase64Binary you can get a String printable from any byte[]
final String printableString = DatatypeConverter.printBase64Binary(printable);
final String notPrintableString = DatatypeConverter.printBase64Binary(notPrintable);
System.out.println("Printable string with DatatypeConverter: " + printableString);
System.out.println("Not printable string with DatatypeConverter: " + notPrintableString);
byte[] otherPrintable = DatatypeConverter.parseBase64Binary(printableString);
byte[] otherNotPrintable = DatatypeConverter.parseBase64Binary(notPrintableString);
// And the best point is that you can revert it
final String otherHello = new String(otherPrintable, StandardCharsets.UTF_8);
final String strangeString = new String(otherNotPrintable, StandardCharsets.UTF_8);
System.out.println("Other Hello: " + otherHello);
System.out.println("Strange String: " + strangeString);
}
}
这是输出
Printable: hello
NotPrintable: d�8�
Printable string with DatatypeConverter: aGVsbG8=
Not printable string with DatatypeConverter: ZL444wE=
Other Hello: hello
Strange String: d�8�
编辑:DatatypeConverter 对 java7 和 java8 有效,查看