c# java .net guid uuid

c# - Cómo leer un.NET Guid en un UUID de Java



(7)

¿No podría simplemente almacenar .Net Guid como una cadena y leerlo en Java? De esa manera no tienes que preocuparte por el orden de bytes ni nada.

Si no es así, esto explica cómo se distribuyen los bytes en C #

http://msdn.microsoft.com/en-us/library/fx22893a.aspx

Necesito comunicar un Guid generado en .NET a una aplicación Java. Utilizo Guid.ToByteArray() para almacenarlo en el disco como un byte[] , luego lo leo en Java y lo convierto en un UUID. Para este propósito copié la implementación del constructor (privado) de UUID que toma un byte[] :

private UUID(byte[] data) { long msb = 0; long lsb = 0; assert data.length == 16; for (int i=0; i<8; i++) msb = (msb << 8) | (data[i] & 0xff); for (int i=8; i<16; i++) lsb = (lsb << 8) | (data[i] & 0xff); this.mostSigBits = msb; this.leastSigBits = lsb; }

Sin embargo, cuando inspecciono el UUID utilizando toString() , el UUID de Java es diferente del .NET Guid.

Por ejemplo, el .NET Guid

888794c2-65ce-4de1-aa15-75a11342bc63

se convierte en el UUID de Java

c2948788-ce65-e14d-aa15-75a11342bc63

Parece que la ordenación de bytes de los primeros tres grupos se invierte, mientras que la ordenación de los dos últimos grupos es la misma.

Como esperaría que el toString() tanto del Guid como del UUID produjera el mismo resultado, ¿alguien sabe cómo debería leer correctamente el .NET Guid en un UUID de Java?

Edit: Para aclarar, la implementación no es mía. Es el constructor privado de la clase java.util.UUID que toma un byte[] , que copié para usarlo con el fin de leer un byte [] del disco en un UUID.

No quiero usar cadenas para almacenar los Guids ya que estoy almacenando muchos de ellos y parece un desperdicio de espacio.

El enlace de Russell Troywest al menos aclara por qué los dos primeros grupos de Guid salen invertidos, mientras que la segunda mitad permanece en el mismo orden. La pregunta es, ¿puedo depender de .NET siempre generando estos bytes en el mismo orden?


Como ya se indicó, la codificación binaria de GUID en .NET tiene bytes en los primeros tres grupos ubicados en el orden little-endian (invertido); consulte el http://msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx . Para crear java.util.UUID desde él puede usar el siguiente código:

import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.UUID; public UUID toUUID(byte[] binaryEncoding) { ByteBuffer source = ByteBuffer.wrap(binaryEncoding); ByteBuffer target = ByteBuffer.allocate(16). order(ByteOrder.LITTLE_ENDIAN). putInt(source.getInt()). putShort(source.getShort()). putShort(source.getShort()). order(ByteOrder.BIG_ENDIAN). putLong(source.getLong()); target.rewind(); return new UUID(target.getLong(), target.getLong()); }


Creo que su problema aquí es que .NET es little-endian pero JAVA es big-endian , así que cuando lee un entero de 128 bits (un GUID) escrito por una aplicación C # desde una aplicación JAVA, tiene que hacer la conversión desde little endian a big-endian


El GUID.toByteArray es bastante extraño en C #. La primera mitad está en little-endian y la segunda mitad está en big-endia.

Un comentario en esta página señala este hecho: http://msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx

el orden de los bytes en la matriz de bytes devuelta es diferente de la representación de cadena de un valor Guid. El orden del grupo inicial de cuatro bytes y los siguientes dos grupos de dos bytes se invierte, mientras que el orden del último grupo de dos bytes y el grupo final de seis bytes es el mismo.


En respuesta a su edición, no, no puede depender constantemente de los bytes que se generan en el mismo orden. El tiempo de ejecución determina la endianidad. Sin embargo, C # ofrece BitConverter.isLittleEndian por esta misma razón.

Sé que no puedes cambiar el endianness de la implementación de Java y el cambio de bits. Pero puede cambiar los bits en el extremo C # después de almacenarlos y antes de enviarlos a Java.

Actualizar:

Artículo de MSDN sobre IsLittleEndian

Edición: para ser práctico, PROBABLEMENTE puede contar con que siempre sea un poco endian en su diseño del primer fragmento de bytes, pero técnicamente no puede.


Este código funciona para mí.

var msb: Long = 0 var lsb: Long = 0 for(i <- Seq(3, 2, 1, 0, 5, 4, 7, 6)) { msb = (msb << 8) | (data(i) & 0xFF) } for(i <- 8 until 16) { lsb = (lsb << 8) | (data(i) & 0xFF) } new UUID(msb, lsb)


Edición 2017-08-30 : Elementos de matriz intercambiados 6 y 7 por comentarios.

Tengo que leer y escribir Guids desde / a MySQL (almacenado como binario (16)) en una aplicación C #, pero las aplicaciones Java también utilizan la base de datos. Estos son los métodos de extensión que utilizo para convertir .NET little-endian y el orden de bytes de big-endian de Java:

public static class GuidExtensions { /// <summary> /// A CLSCompliant method to convert a Java big-endian Guid to a .NET /// little-endian Guid. /// The Guid Constructor (UInt32, UInt16, UInt16, Byte, Byte, Byte, Byte, /// Byte, Byte, Byte, Byte) is not CLSCompliant. /// </summary> [CLSCompliant(true)] public static Guid ToLittleEndian(this Guid javaGuid) { byte[] net = new byte[16]; byte[] java = javaGuid.ToByteArray(); for (int i = 8; i < 16; i++) { net[i] = java[i]; } net[3] = java[0]; net[2] = java[1]; net[1] = java[2]; net[0] = java[3]; net[5] = java[4]; net[4] = java[5]; net[6] = java[7]; net[7] = java[6]; return new Guid(net); } /// <summary> /// Converts little-endian .NET guids to big-endian Java guids: /// </summary> [CLSCompliant(true)] public static Guid ToBigEndian(this Guid netGuid) { byte[] java = new byte[16]; byte[] net = netGuid.ToByteArray(); for (int i = 8; i < 16; i++) { java[i] = net[i]; } java[0] = net[3]; java[1] = net[2]; java[2] = net[1]; java[3] = net[0]; java[4] = net[5]; java[5] = net[4]; java[6] = net[7]; java[7] = net[6]; return new Guid(java); } }