【问题标题】:Store data in Byte array in java在java中将数据存储在字节数组中
【发布时间】:2021-03-01 00:25:04
【问题描述】:

我正在尝试将“密码”之类的字符串转换为十六进制值,然后将其放在一个长数组中,循环正常工作直到达到值“6F”(o char 的十六进制值)然后我有一个例外@ 987654324@

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 值存储在 Byte 数组中,因为 6F 大于 1 个字节?请帮我解决这个问题

【问题讨论】:

  • 尝试使用正确的方法docs.oracle.com/javase/7/docs/api/java/lang/… 如果您阅读javadocs,您会阅读字符串中的字符必须都是十进制数字
  • 那么我可以在字节值中存储像 6F 这样的值吗?@ScaryWombat
  • 上面的代码甚至没有处理字节。请参阅 public static final byte MAX_VALUE 一个保持字节可以具有的最大值的常量,27-1。 如果您查看 asci 表,您会看到 o -> 6F -> @ 987654328@
  • 注意:char 也是一个integral type - 可以用于算术并且只转换为其他类型long l = (long) c

标签: java arrays types byte byte-shifting


【解决方案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; 就是您所需要的 - 这是您在for 循环中唯一需要的行。

但是,请注意:

这真的不是你应该这样做的!

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

因此,要将字符转换为字节或反之,您必须应用编码。编码具有千差万别的属性。然而,最常用的编码是“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 也以这种方式编译它(javac 有一个 -encoding 参数来强制执行此操作)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-24
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    相关资源
    最近更新 更多