【问题标题】:How do I convert an enumeration into a fized size byte[]如何将枚举转换为固定大小的字节 []
【发布时间】:2018-01-31 15:21:12
【问题描述】:

假设我有一个枚举:

public enum MyEnum {
    SUCCESS;
}

我还有一个字符串表示为 byte[]:

byte[] bytes = aString.getBytes(Charset.forName("UTF8"));

我需要一种机制,将 2 byte[] 组合成一个数组,枚举后跟字符串,然后从另一端检索数据。我能想到的唯一方法是将枚举转换为已知的固定大小字节 []。 然后,当我从给定的 byte[] 中提取数据时,我知道第一个 x 代表枚举,其余的代表字符串。然后我需要做的就是将 byte[] 的第一部分转换回枚举,其余部分转换为字符串:

new String(byte[],Charset)

任何有用的实用程序可以帮助我吗?

澄清:该机制需要非常快速,并且字符串的 byte[] 已经通过另一种机制提供。我需要为枚举创建一个 byte[],然后简单地将两者结合起来。在另一端,我需要将枚举的字节 [] 和字符串提取到单独的字节 [] 中。我需要将第一个 byte[] 转换为枚举,但表示字符串的第二个 byte[] 被传递到其他地方。因此我不想创建一个包含枚举和字符串的单个封装数据类,开销太大。

【问题讨论】:

  • 目前还不清楚你在问什么,但听起来很像 hack/kludge。这可能是XY problem。如果您可以退后一步并展示您要完成的工作,我敢打赌会有一个更清洁的解决方案。
  • 我正在处理一个以字节[] 的形式传递消息的遗留系统。在这种情况下,消息由 2 个元素组成,一个枚举和一个字符串。我需要将其中的一对转换成一个字节[],然后再转换成单独的枚举和字符串。
  • This answer 显示了使用 SerializationUtils 的示例。然后还有Java的标准序列化机制(通过ObjectOutputStream)。
  • 对不起,我应该在问题中提到,机制必须非常快,尽可能优化。我通常发现这些实用程序虽然非常有用,但不能用于需要每秒处理许多事务的系统。

标签: java arrays enums


【解决方案1】:

一些进一步的调查表明这是一个可能的答案:

byte[] data = ... from somewhere else
byte[] message = new byte[data.length + 1]
message[0] = Integer.valueOf(MyEnum.SUCCESS.ordinal()).byteValue();
System.arrayCopy(data, 0, message, 1, data.length);

【讨论】:

  • 这正是我想建议的,但要小心枚举的序数
  • 您应该添加一个单元测试,以确保每个单独命名的枚举常量的序号永远保持不变。
  • 好点,虽然我相信这些机制依赖于相同的工件,所以应该总是兼容的。
  • 为什么不只是message[0] = (byte)MyEnum.SUCCESS.ordinal();
  • @DodgyCodeException 每个枚举值,可以包含自身的字节表示。这将防止有人弄乱枚举顺序的情况
【解决方案2】:

这是我的另一个尝试。它应该会提高性能,因为枚举 bytes[] 已兑现...

enum Enum {
    SUCCESS;

    private static final int CONSTANT_LENGTH = 64;
    private static final byte[][] CACHE = new byte[Enum.values().length][CONSTANT_LENGTH];

    static {
        for (int i = 0; i < CACHE.length; i++) {
            CACHE[i] = Enum.values()[i].toString().getBytes();
            CACHE[i] = Arrays.copyOf(CACHE[i], CONSTANT_LENGTH);
        }
    }

    static byte[] getEnumBytes(Enum e) {
        return CACHE[e.ordinal()];
    }

    static Enum getEnum(byte[] bytes) {
        for (int i = 0; ii < CACHE.length; i++) {
            if (Arrays.equals(CACHE[i], bytes)) {
                return Enum.values()[i];
            }
        }
    }

}

调用可能是这样的:

System.out.println(Arrays.toString(Enum.getEnumBytes(Enum.SUCCESS)));

请注意Enum也可以通过类似的方式兑现。

【讨论】:

    【解决方案3】:

    你可以在你的枚举类中写这样的东西(因为枚举实际上是类):

    enum Enum {
        SUCCESS;
    
        static byte[] getEnumBytes(Enum e){
            byte[] result = e.toString().getBytes();
            //logic to make byte[] length constant for each Enum
            return result;
        };
    
    
        static Enum getEnum(byte[] bytes){
            //logic to retrieve Enum from bytes[] converted to String
            return Enum.valueOf("...");
        };
    
    }
    

    【讨论】:

    • 这不会给我一个固定长度的字节[],大小会根据枚举名称中的字符数而有所不同。
    • 如果您注意到我在注释行中写道,您必须编写逻辑以确保 getBytes 返回固定的 byte[] 长度(也许在结束)...
    • 这也是非常低效的,因为它将枚举元素的名称转换为字节[],我原以为序数整数值会更好,更快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 2016-07-30
    相关资源
    最近更新 更多