【问题标题】:What is the equivalent to .Net Guid.ToByteArray() in JavaJava中的.Net Guid.ToByteArray() 等价于什么
【发布时间】:2020-02-26 23:37:13
【问题描述】:

如何将 Guid.ToByteArray() 的以下 .net 用法转换为 Java?

var g= Guid.Parse("9836f2b9-ba8c-42a6-b884-2e9eed9fb95a");
var ga = g.ToByteArray();

.Net Byte 数组返回

ga= [185,242,54,152,140,186,166,66,184,132,46,158,237,159,185,90]

Java 中的尝试(与 .Net 数组不匹配)

UUID uuid = UUID.fromString("9836f2b9-ba8c-42a6-b884-2e9eed9fb95a");
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
byte[] ga= bb.array();

返回的 Java 字节数组

ga= [-72,-124,46,-98,-19,-97,-71,90,-104,54,-14,-71,-70,-116,66,-90]

更新了Guid to Base64 in Java的解决方案

UUID uuid = UUID.fromString("9836f2b9-ba8c-42a6-b884-2e9eed9fb95a");
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
byte[] uuid_bytes = bb.array();
byte[] guid_bytes = Arrays.copyOf(uuid_bytes,uuid_bytes.length);
guid_bytes[0] = uuid_bytes[3];
guid_bytes[1] = uuid_bytes[2];
guid_bytes[2] = uuid_bytes[1];
guid_bytes[3] = uuid_bytes[0];
guid_bytes[4] = uuid_bytes[5];
guid_bytes[5] = uuid_bytes[4];
guid_bytes[6] = uuid_bytes[7];
guid_bytes[7] = uuid_bytes[6];
byte[] ga= guid_bytes;      

【问题讨论】:

  • 谢谢,但我今天尝试了这些方法,但字节数组字节不匹配。请参阅上面的更新。我应该在之前展示过这个=)我确定这是我需要改变的愚蠢的东西。字节必须匹配才能创建 SecretKeySpec 来解密我传入的一些 .Net AES 加密数据。
  • 我希望有办法解决这个问题,因为我无法控制需要在 Java 端生成密钥的 .net AES 加密端 =)
  • 我刚刚找到了一个解决方案,它可以在这里工作stackoverflow.com/questions/51609674/guid-to-base64-in-java。字节顺序是一团糟。我永远不会想到这一点=)我将更新上面的问题以添加解决方案。感谢您的帮助。

标签: java c# .net


【解决方案1】:

问题的替代解决方案 -

public static byte[] getByteArrayFromUUID(UUID uuid) {
    ByteBuffer mostSignificantBitsByteBuffer = ByteBuffer.allocate(Long.BYTES)
            .putLong(uuid.getMostSignificantBits());
    return ByteBuffer.allocate(Long.BYTES * 2)
            .order(ByteOrder.LITTLE_ENDIAN)
            .putShort(mostSignificantBitsByteBuffer.getShort(2))
            .putShort(mostSignificantBitsByteBuffer.getShort(0))
            .putShort(mostSignificantBitsByteBuffer.getShort(4))
            .putShort(mostSignificantBitsByteBuffer.getShort(6))
            .order(ByteOrder.BIG_ENDIAN)
            .putLong(uuid.getLeastSignificantBits())
            .array();
}

【讨论】:

    【解决方案2】:

    Java 中近似等效的类是java.util.UUID。但是,正如您所注意到的,两者并没有给出相同的字节数组。但是,如果您执行以下操作并查看 Java 给出的数组与 .NET 给出的数组:

    import java.nio.ByteBuffer;
    import java.util.Arrays;
    import java.util.UUID;
    
    public class Main {
    
      // expected from your question
      private static final int[] EXPECTED_BYTES = {
        185, 242, 54, 152, 140, 186, 166, 66, 184, 132, 46, 158, 237, 159, 185, 90
      };
    
      public static void main(String[] args) {
        UUID uuid = UUID.fromString("9836f2b9-ba8c-42a6-b884-2e9eed9fb95a");
    
        byte[] array = toByteArray(uuid);
    
        System.out.println("EXPECTED: " + Arrays.toString(EXPECTED_BYTES));
        System.out.println("ACTUAL  : " + Arrays.toString(toUnsignedInts(array)));
      }
    
      private static byte[] toByteArray(UUID uuid) {
        return ByteBuffer.allocate(16)
            .putLong(uuid.getMostSignificantBits())
            .putLong(uuid.getLeastSignificantBits())
            .array();
      }
    
      // for visual purposes only
      private static int[] toUnsignedInts(byte[] array) {
        int[] result = new int[array.length];
        for (int i = 0; i < array.length; i++) {
          result[i] = Byte.toUnsignedInt(array[i]);
        }
        return result;
      }
    }
    

    还有输出:

    EXPECTED: [185, 242, 54, 152, 140, 186, 166, 66, 184, 132, 46, 158, 237, 159, 185, 90]
    ACTUAL  : [152, 54, 242, 185, 186, 140, 66, 166, 184, 132, 46, 158, 237, 159, 185, 90]
    

    您会看到数组几乎相等,只是某些字节的顺序不匹配。最后八个字节(即最低有效位)都匹配,但前四个字节反转,接下来的两个字节反转,接下来的两个字节也是如此。要直观地看到它:

    EXPECTED: [185, 242, 54, 152, 140, 186, 166, 66, 184, 132, 46, 158, 237, 159, 185, 90]
    ACTUAL  : [152, 54, 242, 185, 186, 140, 66, 166, 184, 132, 46, 158, 237, 159, 185, 90]
               |---------------|  |------|  |-----|
    

    我不足以解释为什么存在这种差异,但this comment 在回答问题you linked to 时说:

    另请参阅[Universally unique identifier - Wikipedia]“许多系统完全以大端格式编码 UUID。” “其他系统,特别是微软在其 COM/OLE 库中编组 UUID,使用混合端格式,其中 UUID 的前三个组件是小端,后两个是大端。” – Denis 2019 年 12 月 20 日 13:06

    评论所针对的答案为您的问题提供了解决方案,您已将其包含在您的问题中。该解决方案只是交换字节以获得所需的效果。这是另一个不涉及创建副本数组的解决方案:

    private static byte[] toByteArray(UUID uuid) {
      long mostSigBits = uuid.getMostSignificantBits();
      return ByteBuffer.allocate(16)
          .order(ByteOrder.LITTLE_ENDIAN)
          .putInt((int) (mostSigBits >> 32))
          .putShort((short) (((int) mostSigBits) >> 16))
          .putShort((short) mostSigBits)
          .order(ByteOrder.BIG_ENDIAN)
          .putLong(uuid.getLeastSignificantBits())
          .array();
    }
    

    注意:我对位移不是很满意,所以可能有一种更简洁的方法来完成上述我想不到的。

    它给出以下输出:

    EXPECTED: [185, 242, 54, 152, 140, 186, 166, 66, 184, 132, 46, 158, 237, 159, 185, 90]
    ACTUAL  : [185, 242, 54, 152, 140, 186, 166, 66, 184, 132, 46, 158, 237, 159, 185, 90]
    

    警告:不幸的是,我不确定您是否可以依靠任一解决方法在 100% 的时间内提供正确的字节。

    【讨论】:

      猜你喜欢
      • 2023-02-02
      • 2011-06-05
      • 2011-03-23
      • 2010-11-06
      • 1970-01-01
      • 2010-10-28
      • 2011-10-13
      • 2011-08-27
      • 1970-01-01
      相关资源
      最近更新 更多