杰瑞科技汇

Java字节数组如何高效转二进制?

  1. 转换为二进制字符串:将每个字节转换为它的8位二进制表示(1 变成 "00000001"),这是最常见的需求。
  2. 转换为二进制数据流:将字节数组直接写入输出流,如 OutputStream,这在处理文件、网络传输等 I/O 操作时非常常用。
  3. 转换为十六进制字符串:虽然不是二进制,但这是表示字节数据的另一种非常流行且紧凑的方式,因为它每个字符代表4位二进制。

下面我将详细介绍这几种方法,并提供完整的代码示例。

Java字节数组如何高效转二进制?-图1
(图片来源网络,侵删)

转换为二进制字符串

这是最直接的理解“转换”的方式,我们将遍历 byte 数组中的每一个字节,并将其格式化为一个8位的二进制字符串。

核心思路

  1. 遍历 byte 数组。
  2. 对于每个 byte,使用 Integer.toBinaryString() 方法将其转换为二进制字符串。
  3. Integer.toBinaryString() 会返回一个无前导零的字符串(1 会变成 "1"),所以我们需要手动补足前导零,确保每个字节都是8位。
  4. 将所有8位的二进制字符串拼接起来。

代码示例

import java.nio.charset.StandardCharsets;
public class ByteArrayToBinary {
    public static void main(String[] args) {
        // 示例字节数组: 'A' -> 65, 'B' -> 66, 'C' -> 67
        // 65 in binary is 01000001
        // 66 in binary is 01000010
        // 67 in binary is 01000011
        byte[] bytes = {'A', 'B', 'C'};
        // 方法1: 使用 String.format 进行格式化
        String binaryString1 = bytesToBinaryStringUsingFormat(bytes);
        System.out.println("方法1 (String.format): " + binaryString1);
        // 方法2: 使用 Integer.toBinaryString 并手动补零
        String binaryString2 = bytesToBinaryStringManualPadding(bytes);
        System.out.println("方法2 (手动补零):      " + binaryString2);
    }
    /**
     * 使用 String.format 将 byte 数组转换为二进制字符串
     * @param bytes 输入的字节数组
     * @return 每个字节都转换为8位二进制并拼接后的字符串
     */
    public static String bytesToBinaryStringUsingFormat(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            // %8s 表示一个至少8个字符宽的字符串,右对齐
            // 0 表示用 '0' 填充空位
            // String.format 会将 byte 自动转为 int,然后格式化为二进制
            sb.append(String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0'));
        }
        return sb.toString();
    }
    /**
     * 使用 Integer.toBinaryString 并手动补零将 byte 数组转换为二进制字符串
     * @param bytes 输入的字节数组
     * @return 每个字节都转换为8位二进制并拼接后的字符串
     */
    public static String bytesToBinaryStringManualPadding(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            // 1. 将 byte 转换为无符号的 int 值,避免负数问题
            //    b & 0xFF 是一个常用的技巧,可以确保 byte 被当作 0-255 的正数处理
            int val = b & 0xFF;
            // 2. 转换为二进制字符串
            String s = Integer.toBinaryString(val);
            // 3. 手动补前导零
            //    因为 toBinaryString 不会生成前导零,所以我们需要检查长度
            if (s.length() < 8) {
                sb.append("00000000".substring(s.length()));
            }
            sb.append(s);
        }
        return sb.toString();
    }
}

输出结果

方法1 (String.format): 010000010100001001000011
方法2 (手动补零):      010000010100001001000011

关键点解释

  • b & 0xFF:这是最重要的一步,Java 中的 byte 是有符号的(范围是 -128 到 127),当你将一个负数 byte-1)直接传递给 Integer.toBinaryString() 时,它会得到一个32位的二进制补码表示(11111111111111111111111111111111),这显然不是我们想要的。b & 0xFF 通过位运算,将 byte 提升为 int,同时只保留低8位,得到一个 0-255 之间的无符号整数,这确保了每个字节都被正确地转换为8位二进制。
  • String.format("%8s", ...).replace(' ', '0'):这是一种非常简洁的补零方式。%8s 会将字符串格式化为8个字符宽度,不足的部分用空格填充,然后我们再用 replace 将这些空格替换为 0

转换为二进制数据流

如果你不是想得到一个字符串,而是想把二进制数据写入文件或通过网络发送,那么你应该直接使用 java.io 包中的流。

核心思路

使用 FileOutputStreambyte 数组直接写入文件,文件本身就是二进制数据的存储形式。

代码示例

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ByteArrayToBinaryStream {
    public static void main(String[] args) {
        // 准备要写入的字节数据
        String data = "Hello, Java!";
        byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
        // 定义输出文件路径
        String filePath = "output.bin";
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            // 直接将字节数组写入文件输出流
            fos.write(bytes);
            System.out.println("字节数组已成功写入文件: " + filePath);
        } catch (IOException e) {
            System.err.println("写入文件时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

运行此代码后,会在项目根目录下创建一个名为 output.bin 的文件,你可以使用任何十六进制编辑器(如 HxD, WinHex, VS Code 的 Hex Editor 插件)打开它,就能看到原始的二进制数据。

Java字节数组如何高效转二进制?-图2
(图片来源网络,侵删)

转换为十六进制字符串(常用替代方案)

要求是二进制,但在实际开发中,将字节数组转换为十六进制字符串更为常见,因为:

  • 更紧凑:每两个十六进制字符代表一个字节,比8位二进制字符串短得多。
  • 可读性更好"A1B2""1010000110110010" 更容易阅读和调试。
  • 不易出错:避免了一长串 01 的视觉混淆。

核心思路

遍历每个字节,将其转换为两个十六进制字符(0-9, A-F)。

代码示例

import java.nio.charset.StandardCharsets;
public class ByteArrayToHex {
    public static void main(String[] args) {
        String data = "ABC";
        byte[] bytes = data.getBytes(StandardCharsets.UTF_8); // 结果是 {65, 66, 67}
        // 方法1: 使用 String.format (类似二进制的方法)
        String hexString1 = bytesToHexStringUsingFormat(bytes);
        System.out.println("方法1 (String.format): " + hexString1);
        // 方法2: 使用 Integer.toHexString 并手动补零
        String hexString2 = bytesToHexStringManualPadding(bytes);
        System.out.println("方法2 (手动补零):      " + hexString2);
        // 方法3: 使用第三方库 (如 Apache Commons Codec) - 推荐在生产环境使用
        // String hexString3 = Hex.encodeHexString(bytes);
        // System.out.println("方法3 (Apache Commons): " + hexString3);
    }
    public static String bytesToHexStringUsingFormat(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            // %02x 表示将整数格式化为2位的小写十六进制数,不足用0填充
            sb.append(String.format("%02x", b & 0xFF));
        }
        return sb.toString();
    }
    public static String bytesToHexStringManualPadding(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            int val = b & 0xFF;
            // Integer.toHexString 不会生成前导零,需要手动处理
            if (val < 16) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(val));
        }
        return sb.toString();
    }
}

输出结果

方法1 (String.format): 414243
方法2 (手动补零):      414243
需求场景 推荐方法 优点 缺点
查看/调试每个字节的二进制位 转为二进制字符串 直观,完全符合字面意思 字符串冗长,不适合大量数据
将数据持久化到文件或网络传输 写入二进制流 高效,直接操作原始数据 不能直接用于日志或控制台显示
紧凑地表示或传输字节数据 转为十六进制字符串 紧凑、可读、通用 不是原始的二进制位表示

对于大多数开发需求,方法一方法三 是最常用的,如果你只是想看看数据长什么样,用方法一;如果你需要传输或存储一个紧凑的文本表示,用方法三。

Java字节数组如何高效转二进制?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇