你如何 "print" 处理不可打印值的字节数组

How do you "print" an array of bytes that handles non-printable values

我在这个论坛上看到了很多有些相关的问题和答案,但没有找到任何解决我的问题的东西。

这个想法很简单:

(这是使用 Java 编程语言 - 我目前仅限于使用 Java 7)

接收到字节数组(代表任何内容:某种有线格式、某种形式的编码数据、嵌入 "text" 的二进制数据等)。我希望能够以下列形式打印数组:

  1. 十六进制字符串
  2. 作为"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 有效,查看