So lesen Sie eine .NET-Guid in eine Java-UUID ein

Lesezeit: 6 Minuten

So lesen Sie eine NET Guid in eine Java UUID ein
Der Slicer

Ich muss eine Guid, die in .NET generiert wurde, einer Java-Anwendung mitteilen. ich benutze Guid.ToByteArray() um es auf der Festplatte als zu speichern byte[], lesen Sie es dann in Java ein und konvertieren Sie es in eine UUID. Zu diesem Zweck habe ich die Implementierung des (privaten) Konstruktors von UUID kopiert, der a akzeptiert 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;
}

Wenn ich jedoch die UUID mit inspiziere toString()unterscheidet sich die Java-UUID von der .NET-Guid.

Beispielsweise die .NET-Guid

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

wird zur Java-UUID

c2948788-ce65-e14d-aa15-75a11342bc63

Es scheint, dass die Byte-Reihenfolge der ersten drei Gruppen umgekehrt ist, während die Reihenfolge in den letzten beiden Gruppen dieselbe ist.

Da würde ich das erwarten toString() von Guid und UUID, um das gleiche Ergebnis zu erzielen, weiß jemand, wie ich die .NET-Guid korrekt in eine Java-UUID einlesen soll?

Bearbeiten: Zur Klarstellung: Die Implementierung stammt nicht von mir. Es ist der private Erbauer der java.util.UUID Klasse, die dauert byte[]die ich kopiert habe, um ein Byte zu lesen[] von der Festplatte in eine UUID.

Ich möchte keine Zeichenfolgen verwenden, um die Guids zu speichern, da ich viele davon speichere und es wie eine Platzverschwendung erscheint.

Der Link von Russell Troywest verdeutlicht zumindest, warum die ersten paar Gruppen der Guid umgekehrt herauskommen, während die zweite Hälfte in derselben Reihenfolge bleibt. Die Frage ist, kann ich mich auf .NET verlassen immer Generieren dieser Bytes in der gleichen Reihenfolge?

  • Es sieht so aus, als ob Sie die Bits in die falsche Richtung verschieben. Warum versuchen, damit süß zu sein? Lesen Sie die Bytes und nehmen Sie zuerst die entsprechenden Zuweisungen vor (unter Verwendung eines Index zuerst) und verwenden Sie dann einen Shift-Operator zur Optimierung (falls erforderlich). Der Punkt ist, einen leicht verständlichen Code zu haben.

    – casperOne

    21. April 2011 um 14:43 Uhr

  • Java speichert Daten streng Big Endian, während C # keine “Endianness” angibt, sondern Daten normalerweise als Little Endian speichert. Wie @casperOne sagte, Sie schalten in die falsche Richtung.

    – Doug Stephen

    21. April 2011 um 14:48 Uhr

  • Ich habe versucht, ein Framework zurückzuentwickeln, das diese Konstruktion verwendet. Hatte über zwei Stunden auf die seltsame Bitverschiebung gestarrt, bis ich diesen Thread gefunden habe.

    – Jouke Waleson

    24. November 2012 um 16:21 Uhr

So lesen Sie eine NET Guid in eine Java UUID ein
Russell Troywest

Könnten Sie die .Net-Guid nicht einfach als Zeichenfolge speichern und in Java einlesen? Auf diese Weise müssen Sie sich keine Gedanken über die Byte-Reihenfolge oder ähnliches machen.

Wenn nicht, dann Dies erklärt, wie die Bytes in C# angeordnet sind

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

Bearbeiten 2017-08-30: Vertauschte Array-Elemente 6 und 7 pro Kommentar.

Ich muss Guids von/nach MySQL (als Binary (16) gespeichert) in einer C#-App lesen und schreiben, aber die Datenbank wird auch von Java-Apps verwendet. Hier sind die Erweiterungsmethoden, die ich zum Konvertieren zwischen .NET-Little-Endian- und Java-Big-Endian-Bytereihenfolge verwende:

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);
    }
}

  • Ich bin mir nicht sicher, ob dies eine Java-spezifische Sache ist, aber ich musste Endianess für Active Directory Guid / NativeGuid umdrehen und die Verwendung dieses Codes erzeugt einen Fehler. Die Lösung liegt in den letzten zwei Byte-Swaps, die nicht im Code enthalten sind: java[6]= netto[7]; Java[7]= netto[6]; Beachten Sie auch, dass die beiden Methoden identisch sind und Sie sie auf eine Flip-Funktion reduzieren können.

    – Maverich

    18. Juni 2013 um 11:57 Uhr

  • Also sagst du das statt net[6] = java[6] und net[7] = java[7] es sollte diese zwei Bytes tauschen? Ich weiß, dass dieser Code für mich beim Umgang mit Guids in MySQL funktioniert hat (habe diese DB gerade nicht zur Hand), aber die Antwort von @Russell Troywest unten könnte doch die sicherere Option sein.

    – Paul Smith

    18. Juni 2013 um 13:29 Uhr

  • so scheint Active Directory zu funktionieren. Seltsames Zeug! Ich wechsle im Grunde zwischen DirectoryEntry.Guid und DirectoryEntry.NativeGuid, indem ich Ihren Code mit dieser Änderung verwende. Laut Dokumentation von Guids sollte dieses letzte Byte gemäß meinem grundlegenden Verständnis dieses Textes ausgetauscht werden

    – Maverich

    18. Juni 2013 um 15:14 Uhr

  • Es scheint einen Tippfehler (oder einen Fehler) in Ihrem Code von zu geben net[6] = java[6];sollte es sein net[6] = java[7];?

    – Felix

    7. Dezember 2016 um 6:00 Uhr

  • Ich musste net schalten[7] bis 6 und netto[6] bis 7 in ToBigEndian

    – Alexander

    30. August 2017 um 20:49 Uhr

1647157029 959 So lesen Sie eine NET Guid in eine Java UUID ein
ᄂ ᄀ

Wie bereits erwähnt, hat die binäre Kodierung von GUID in .NET Bytes in den ersten drei Gruppen in der Little-Endian-Reihenfolge (umgekehrt) – siehe Guid.ToByteArray-Methode. Erschaffen java.util.UUID daraus können Sie den folgenden Code verwenden:

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());
}

Als Antwort auf Ihre Bearbeitung, nein, Sie können sich nicht konsequent darauf verlassen, dass die Bytes in derselben Reihenfolge generiert werden. Die Laufzeit bestimmt die Endianness. C# bietet jedoch BitConverter.isLittleEndian genau aus diesem grund.

Ich weiß, dass Sie die Endianness der Java-Implementierung und die Bitverschiebung nicht ändern können. Aber Sie können die Bits auf der C#-Seite nach dem Speichern und vor dem Senden an Java verschieben.

Aktualisieren:

MSDN-Artikel zu IsLittleEndian

Bearbeiten: Um praktisch zu sein, können Sie sich wahrscheinlich darauf verlassen, dass es im Layout des ersten Byte-Blocks immer Little Endian ist, aber technisch gesehen können Sie das nicht.

1647157029 842 So lesen Sie eine NET Guid in eine Java UUID ein
Joey

Das GUID.toByteArray ist in C# ziemlich seltsam. Die erste Hälfte ist in Little-Endian und die zweite Hälfte in Big-Endia.

Ein Kommentar auf dieser Seite stellt diese Tatsache fest:
http://msdn.microsoft.com/en-us/library/system.guid.tobytearray.aspx

Die Reihenfolge der Bytes im zurückgegebenen Bytearray unterscheidet sich von der Zeichenfolgendarstellung eines Guid-Werts. Die Reihenfolge der beginnenden Vier-Byte-Gruppe und der nächsten zwei Zwei-Byte-Gruppen ist umgekehrt, während die Reihenfolge der letzten Zwei-Byte-Gruppe und der abschließenden Sechs-Byte-Gruppe dieselbe ist.

1647157029 27 So lesen Sie eine NET Guid in eine Java UUID ein
Gemeinschaft

Ich denke, Ihr Problem hier ist, dass .NET Little-Endian ist, aber JAVA Big-Endian ist. Wenn Sie also eine 128-Bit-Ganzzahl (eine GUID) lesen, die von einer C#-App aus einer JAVA-App geschrieben wurde, müssen Sie die Konvertierung von Little- durchführen. Endian zu Big-Endian.

Die Codecs DotNetGuid1Codec und DotNetGuid4Codec kann UUIDs in .Net Guids kodieren.

// Convert time-based (version 1) to .Net Guid
UuidCodec<UUID> codec = new DotNetGuid1Codec();
UUID guid = codec.encode(timeUuid);
// Convert random-based (version 4) to .Net Guid
UuidCodec<UUID> codec = new DotNetGuid4Codec();
UUID guid = codec.encode(randomUuid);

Sehen: uuid-Ersteller

996430cookie-checkSo lesen Sie eine .NET-Guid in eine Java-UUID ein

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy