在java中将字符串转换为字节[重复]

Posted

技术标签:

【中文标题】在java中将字符串转换为字节[重复]【英文标题】:Converting String to bytes in java [duplicate] 【发布时间】:2012-11-22 23:25:48 【问题描述】:

可能重复:Convert a string representation of a hex dump to a byte array using Java?

我想将 String "1B4322C2" 转换为字节,但问题是如果我使用 getBytes() 它会将其转换为字符串长度的两倍,我想将它们转换为字符串长度的一半。

例如以上字符串的输出应该是0x1B , 0x43, 0x22, 0xC2

谢谢

【问题讨论】:

字符串总是8个字符吗? 【参考方案1】:

要将“1B4322C2”编码为字节,您可以使用

byte[] bytes = new BigInteger("FB4322C2", 16).toByteArray();
if (bytes.length > 1 && bytes[0] == 0)
    bytes = Arrays.copyOfRange(bytes, 1, bytes.length);
System.out.println(Arrays.toString(bytes));

打印

[-5, 67, 34, -62]

【讨论】:

【参考方案2】:

您不需要 String.getBytes() 方法。这会将字符串的字符转换为它们的字节表示形式。

要执行您想要执行的操作,您需要手动将字符串拆分为单独的字符串,每对一个字符串。然后,您将要解析它们。

不幸的是,Java 没有无符号字节,0xC2 会溢出。如果内存不是问题,您可能希望将这些值视为短裤或整数。

因此,您可以使用 Integer 类将字符串解析为数字。由于您的字符串是十六进制的,因此您必须使用可让您提供基数的 parse 方法。

String test = "1B4322C2";

for (int bnum = 0; bnum < test.length() / 2; bnum++) 
    String bstring = test.substring(bnum * 2, bnum * 2 + 2);
    int bval = Integer.parseInt(bstring, 16);
    System.out.println(bstring + " -> " + bval);

这将输出:

1B -> 27
43 -> 67
22 -> 34
C2 -> 194

如果您需要将它们放在数组中,您可以实例化一个宽度为字符串一半的数组,然后它们将每个值放在其bnum 索引下。

【讨论】:

Java doesn't have unsigned bytes, and 0xC2 is going to overflow. 绝对的废话。没有溢出。试试byte b = 0xC2; 它可以工作。【参考方案3】:

(我现在已经投票决定以重复的形式关闭,我应该先这样做......但是在问题被删除之前将这个答案留在这里是有意义的......)

对,所以你实际上想要做的是解析一个十六进制字符串。

您应该查看Apache Commons Codec,它有一个Hex 类正是为了这个目的。就我个人而言,我对 API 并不感兴趣,但这应该可行:

Hex hex = new Hex();
byte[] data = (byte[]) hex.decode(text);

或者:

byte[] data = Hex.decodeHex(text.toCharArray());

(我个人希望你可以使用byte[] data = Hex.decodeHexString(text);,但我们开始了......如果你愿意,你可以随时编写自己的包装方法。)

如果您不想使用 3rd 方库,则 Stack Overflow 上的其他地方有很多实现,例如this one.

【讨论】:

你可以使用Byte.parseByte(str,16); @Quoi:嗯,这需要为每个字节创建一个新的String 对象。我认为我们不需要那么低效。 我们为什么要向 Apache Commons 发送 Java 开头?这可以使用基本数字原始包装类来处理。编辑:哦等等,这家伙不是java初学者。本来可以骗我的。继续。 @JonSkeet - 类似if ((str.length() % 2) == 1) str = "0" + str; for(int i=0;i&lt;str.length()-1;) String str1 = str.substring(i, i+2); System.out.print(Byte.parseByte(str1,16)); i+=2; @Chris:即使对于初学者来说,很多事情当然可以在没有第三方库的情况下实现,但不应该——为什么要重新发明一个已经在其他地方有效发明的***?我认为寻找解决问题的现有库是我们应该积极教给初学者的东西。 (Guava 和 Joda Time 是我首先引导人们访问的图书馆 :)【参考方案4】:

如果您不想使用外部库,这应该通过一些调整来解决问题(添加 0x 和 )

public static String byteArrayToHexadecimal(byte[] raw) 
    final BigInteger bi = new BigInteger(1, raw);
    final String result = bi.toString(16);
    if (result.length() % 2 != 0) 
        return "0" + result;
    
    return result;

抱歉,换个方式(没有优化,因为对我来说根本不是瓶颈):

public static byte[] hexadecimalToByteArray(String hex) 
    if (hex.length() % 2 != 0) 
        hex = "0" + hex;
    
    final byte[] result = new byte[hex.length() / 2];
    for (int i = 0; i < hex.length(); i += 2) 
        String sub = "0x" + hex.substring(i, i + 2);
        result[i / 2] = (byte) ((int) Integer.decode(sub));
    
    return result;

不过,我建议按照 J. Skeet 的建议选择 Apache Commons Codec

【讨论】:

OP 想要反过来,但我承认BigInteger 的使用很巧妙。 请注意,这与 OP 想要的方向相反,我个人不会使用 BigInteger 进行十六进制转换 - 这不是它的设计目的,它通常会削减前导0。 (例如,使用上面的代码, 0, 0, 0 应该给出“000000”,但我相信它只会给出“00”。)【参考方案5】:

您可以使用 String Tokenizer 或 String Builder 并分离字符串,然后将其从十六进制转换为字符串...

此链接可能对您有所帮助..Convert Hex to ASCII

希望这会有所帮助..

【讨论】:

【参考方案6】:

getBytes将每个字符转换为字节形式的字符代码;它不会从字符串本身解析出字节值。为此,您可能需要编写自己的解析函数。

【讨论】:

以上是关于在java中将字符串转换为字节[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在java中将字符串数组元素转换为字节数组[重复]

如何在C#中将字节转换为字符串[重复]

在android中将字节[]转换为十六进制字符串[重复]

如何在Go中将字节数组转换为字符串[重复]

在此算法中将字节数组转换为字符串时出错[重复]

如何在 C# 中将字符串转换为字节 []