将数据存储在字节数组中 java

Store data in Byte array in java

我正在尝试将像“password”这样的字符串转换为十六进制值,然后将它放在一个长数组中,循环工作正常直到达到值“6F”(o char 的十六进制值)然后我有一个异常 java.lang.NumberFormatException

String password = "password";
char array[] = password.toCharArray();
int index = 0;
for (char c : array) {
    String hex = (Integer.toHexString((int) c));
    data[index] = Long.parseLong(hex);
    index++;
}

如何将 6F 值存储在字节数组中,因为 6F 大于 1 个字节?。请帮我解决这个问题

Long.parseLong 解析十进制数。它将字符串“10”变成数字 10。如果输入是十六进制,即 不正确 - 字符串“10”应该变成数字 16。修复方法是使用 Long.parseLong(String input, int radix) 方法。你想要的基数是 16,尽管写成 0x10 可能更具可读性——这对编译器来说是一样的,纯粹是个人风格的选择。因此,Long.parseLong(hex, 0x10) 就是您想要的。

请注意,实际上 char 具有从 0 到 65535 的数字,这不适合字节。实际上,您必须记下密码不得包含任何非 ASCII 字符的字符(因此不能包含变音符号、雪人、表情符号、有趣的引号等)。

如果你不检查这个,Integer.toHexString((int) c)会变成类似16F或更糟的东西(3到4个字符),它也可能变成一个字符。

更一般地说,从char c转换为十六进制字符串,然后将十六进制字符串解析为数字,是完全没有意义的。它将 15 变成“F”,然后将“F”变成 15。如果你只想将一个字符推入一个字节:data[index++] = (byte) c; 就是你所需要的 - 这是你 [=21] 中唯一需要的行=]循环。

但是,请注意:

这真的不是你应该做的!

您正在做的是将字符数据转换为字节数组。这 实际上并不简单 - 只有 256 个可能的字节,而且还有 way 人们发明的更多字符。字面上有数十万个。

因此,要将字符转换为字节或将字符转换为字节,您必须应用编码。编码具有千差万别的属性。然而,最常用的编码是 'UTF-8'。它代表 每个 unicode 符号,并且有趣的是 属性 基本 ASCII 字符看起来完全一样。然而,它有一个缺点,即任何给定的字符都会被涂抹成 1、2、3 甚至 4 个字节,具体取决于它是什么字符。幸运的是,java 有很多工具可以做到这一点,因此您无需关心。你真正想要的是:

byte[] data = password.getBytes(StandardCharsets.UTF8);

这就是要求字符串使用 UTF8 编码将自身转换为字节数组。这意味着“密码”变成序列“112 97 115 115 119 111 114 100”,这无疑是您想要的,但您也可以使用 außgescheignet ☃ 作为密码,这也行得通 - 它已转换转换成字节,然后你可以回到你的雪人启用密码:

String in = "außgescheignet ☃";
byte[] data = in.getBytes(StandardCharsets.UTF8);
String andBackAgain = new String(data, StandardCharsets.UTF8);
assert in.equals(andBackAgain); // true

如果您将其粘贴到源文件中,请确保将其保存在您使用的任何文本编辑器中作为 UTF8,并且 javac 也以这种方式编译它(java c 有一个 -encoding 参数来强制执行此操作。

如果您认为这会导致您将其发送到的任何对象出现问题,并且您希望将其限制为具有以美国为中心的观点的人所说的 'normal' 个字符,那么您需要与此处展示的代码完全相同,但使用 StandardCharsets.ASCII 代替。然后,如果该行 (password.getBytes(StandardCharsets.ASCII)) 包含非 ASCII 字符,则会出现错误。这是一件好事:您的基础设施无法正确处理它,我们只是在这个假设练习中假设了这一点。在流程的早期在相关行上抛出异常正是您想要的。