【问题标题】:Cast a hexadecimal string to a class object将十六进制字符串强制转换为类对象
【发布时间】:2019-01-31 10:09:57
【问题描述】:

我有这样的课:

public class Fields implements java.io.Serializable{
    public short ID;
    public int SSN;
    public long Number;
}

我有一个十六进制字符串,其值如下,每 2 个字符代表一个字节:

String str="1000180018000540AC80D6487653E5000100D40B7900D4C3FFF2FAFF8985";

现在我想在这样的模式中将此字符串转换为上述类对象:

//ID has short type so we need 2 bytes
ID=4096; //(decimal value of 1000)

//SSN has integer type so we need 4 bytes
SSN=402659328; //(decimal value of 18001800)

//Number has long type so we need 8 bytes
Number=378492038049986131; //(decimal value of 0540AC80D6487653)

这种转换可以很容易地用<reinterpret_cast> 在c++ 中实现,但正如Is there cast in Java similar to in C++ 问题所说,我可以用java 中的序列化来实现它。我认为当我们首先将类对象序列化为字节数组时可以使用序列化,其次我们可以将获得的字节反序列化为原始类对象,这与我的建议有点不同,因为我有一个字符串(比如字节),我想反序列化它。那我该怎么做呢?

【问题讨论】:

  • 序列化对你没有帮助。它具有非常特定的格式,与您的格式不匹配。您必须手动解析字符串。
  • @talex 但 C++ 很容易用<reinterpret_cast> 做到这一点。那么java中没有像<reinterpret_cast>这样的方法吗?因为速度对我来说很重要,使用高速率字符串数据手动解析将是一个瓶颈!
  • <reinterpret_cast> 不会轻易做到。它甚至不会工作。 "1000" 是 4 个 ASCII 字节,0x31, 0x30, 0x30, 0x30,C++ 不会神奇地将其转换为 2 个字节 0x10, 0x00。
  • @ahmadimortezaali 如果你想使用<reinterpret_cast>,你必须使用c++ :) Java 没有类似的东西。

标签: java arrays serialization deserialization hexdump


【解决方案1】:

Java 序列化具有非常特定的数据格式,它不能帮助您解析使用不同的预定义格式获得的数据。但是a ByteBuffer 在解析这类数据时会很有用。

首先,您需要将字符串转换为实际的byte[] 数组。我将使用来自this answer 的简单解决方案,请随意选择另一个更适合您的示例的解决方案:

byte[] data = DatatypeConverter.parseHexBinary(str);
ByteBuffer buffer = ByteBuffer.wrap(data);

buffer.order(ByteOrder.LITTLE_ENDIAN); // maybe!

short id = buffer.getShort();
int ssn = buffer.getInt();
long number = buffer.getLong();

您是否需要 order() 调用取决于您的数据的字节顺序。ByteBuffer 默认为 BIG_ENDIAN,因此如果需要,您可以不使用该调用。

【讨论】:

  • 这是对 NIO ByteBuffer 的很好使用。
  • 非常感谢!通过将buffer.order(ByteOrder.LITTLE_ENDIAN); 更改为buffer.order(ByteOrder.BIG_ENDIAN);,我想要的结果完美地达到了!
  • @ahmadimortezaali:请注意 BIG_ENDIAN 是默认设置,因此在这种情况下您也可以完全忽略它。
【解决方案2】:

我认为<reinterpret_cast> 不会起作用。 "1000" 的内部字节表示是 4 个 ASCII 字节。一个字符 1 (0x31) 后跟 3 个字符 0 (0x30) ,而不是 0x10, 0x00 十六进制。在id<reinterpret_cast> 中得到的结果将是十六进制0x31303030 而不是0x1000

您需要做的是解析字符串的不同组成部分。

应该这样做:

int id = Integer.parseInt(str.substring(0,4), 16);

【讨论】:

  • 你的意思可能是int id = ...
  • 是的,本来打算分两行做的,但我改变了主意,忘记改变类型了。
【解决方案3】:

您只需要splitparse

public Fields(String str) {
    ID = Short.parseShort(str.substring(0, 4), 16);
    SSN = Integer.parseInt(str.substring(4, 12), 16);
    Number = Long.parseLong(str.substring(12, 28), 16);
}

【讨论】:

    猜你喜欢
    • 2018-01-31
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2020-11-07
    相关资源
    最近更新 更多