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[]:
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
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
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
ᄂ ᄀ
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:
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.
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.
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.
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.
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.
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