在java中将数据存储在字节数组中 这真的不是你应该做的!

问题描述

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

java.lang.NumberFormatException

如何将 6F 值存储在 Byte 数组中,因为 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; 就是你所需要的——这是你 {{1} 中唯一需要的行}} 循环。

但是,请注意这一点:

这真的不是你应该做的!

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

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

for

这要求字符串使用 UTF8 编码将自身转换为字节数组。这意味着“密码”变成了序列“112 97 115 115 119 111 114 100”,这无疑是你想要的,但你也可以有密码,比如byte[] data = password.getBytes(StandardCharsets.UTF8); ,这也有效——它变成了成字节,你可以回到你的雪人启用密码:

außgescheignet ☃

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

如果您认为这会导致发送到任何内容的问题,并且您想将其限制为具有以美国为中心的观点的人所称的“正常”字符,那么您需要与以下代码完全相同的代码此处展示,但请改用 String in = "außgescheignet ☃"; byte[] data = in.getBytes(StandardCharsets.UTF8); String andBackAgain = new String(data,StandardCharsets.UTF8); assert in.equals(andBackAgain); // true 。然后,如果该行 (StandardCharsets.ASCII) 包含非 ASCII 字符,则会显示错误。这是一件好事:您的基础设施无法正确处理它,我们只是在这个假设的练习中假设了这一点。在相关行的流程早期抛出异常正是您想要的。