2017-02-21 9 views
0

J'essaye de porter un code C# existant qui utilise BitConverter to Java. J'ai trouvé plusieurs autres fils de discussion, mais je suis tombé sur un cours de github qui semble faire l'affaire. Cependant, le ToUInt16 ne correspond pas à la sortie de mon code C#. Le ToInt16 et ToInt32 semblent retourner les mêmes valeurs. Pouvez-vous m'aider à comprendre ce qui ne va pas avec cette implémentation (ou éventuellement ce que je fais de mal)?C# BitConverter to Java

Code Réf: Java BitConverter

ToUInt16:

public static int ToUInt16(byte[] bytes, int offset) { 
     int result = (int)bytes[offset+1]&0xff; 
     result |= ((int)bytes[offset]&0xff) << 8; 
     if(Lysis.bDebug) 
      System.out.println(result & 0xffff); 
     return result & 0xffff; 
    } 

ToUInt32:

public static long ToUInt32(byte[] bytes, int offset) { 
    long result = (int)bytes[offset]&0xff; 
    result |= ((int)bytes[offset+1]&0xff) << 8; 
    result |= ((int)bytes[offset+2]&0xff) << 16; 
    result |= ((int)bytes[offset+3]&0xff) << 24; 
    if(Lysis.bDebug) 
     System.out.println(result & 0xFFFFFFFFL); 
    return result & 0xFFFFFFFFL; 
} 

MyCode Snippet:

byte[] byteArray = from some byte array 
int offset = currentOffset 
int msTime = BitConverter.ToUInt16(byteArray, offset) 

msTime ne correspond pas à ce qui vient de C#

C# Exemple (chaîne du fournisseur est converti à partir d'une chaîne à l'aide Convert.FromBase64String)

byte[] rawData = Convert.FromBase64String(vendorRawData); 
    byte[] sampleDataRaw = rawData; 

    Assert.AreEqual(15616, sampleDataRaw.Length); 

    //Show byte data for msTime 
    Console.WriteLine(sampleDataRaw[7]); 
    Console.WriteLine(sampleDataRaw[6]); 

    //Show byte data for msTime 
    Console.WriteLine(sampleDataRaw[14]); 
    Console.WriteLine(sampleDataRaw[13]); 

    var msTime = BitConverter.ToUInt16(sampleDataRaw, 6); 
    var dmWindow = BitConverter.ToUInt16(sampleDataRaw, 13); 
    Assert.AreEqual(399, msTime); 
    Assert.AreEqual(10, dmWindow); 

C# Console de sortie pour octet valeurs:

1 
143 
0 
10 

Groovy Exemple (chaîne du fournisseur est converti à partir d'une chaîne à l'aide decodeBase64 groovy())

def rawData = vendorRawData.decodeBase64() 
    def sampleDataRaw = rawData 
    Assert.assertEquals(15616, rawData.length) 

    //Show byte data for msTime 
    println sampleDataRaw[7] 
    println sampleDataRaw[6] 

    //Show byte data for dmWindow 
    println sampleDataRaw[14] 
    println sampleDataRaw[13] 

    def msTime = ToUInt16(sampleDataRaw, 6) 
    def dmWindow = ToUInt16(sampleDataRaw, 13) 
    Assert.assertEquals(399, msTime) 
    Assert.assertEquals(10, dmWindow) 

**Asserts fail with** 

    399 fro msTime is actually 36609 
    10 from dmWindow is actually 2560 

de sortie Groovy des valeurs d'octets dans println

1 
-113 
0 
10 
+1

Pouvez-vous fournir des tests de test qui échouent, afin que nous puissions voir quelle sortie vous attendez et obtenez réellement pour une entrée donnée? – slim

+2

Dans le cas où cela vous aide, vous pouvez consulter l'implémentation .Net qui peut être trouvée dans la source de référence https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,567d835b31ee9268,references – pinkfloydx33

+2

Un exemple serait bien. En outre, je recommande d'utiliser 'ByteBuffer' pour ce genre de conversions. Il peut faire tout cela sans bibliothèque. – john16384

Répondre

2

Il y a une différence entre les deux méthodes . Le premier ToUInt16 prend l'ordre des octets big-endian. c'est-à-dire que le premier octet est l'octet le plus significatif.

Mais ToUInt32 suppose que l'ordre des octets little-endian (un choix étrange). Donc le premier octet est le moins significatif.

Une mise en œuvre corrigée ressemblerait à ceci:

public static long toUInt32(byte[] bytes, int offset) { 
    long result = Byte.toUnsignedLong(bytes[offset+3]); 
    result |= Byte.toUnsignedLong(bytes[offset+2]) << 8; 
    result |= Byte.toUnsignedLong(bytes[offset+1]) << 16; 
    result |= Byte.toUnsignedLong(bytes[offset]) << 24; 
    return result; 
} 

Lorsque l'indexation du tableau est 'inversée'.

(J'ai aussi changé la hacky recherche bitmasking aux appels plus clairs à Byte.toUnsignedLong, qui fait la même chose.)

+0

Merci @Jorn Vernee! Que devrais-je changer avec l'implémentation de ToUInt16, s'il y a quelque chose, c'est aussi renvoyer un résultat qui ne correspond pas – scarpacci

+0

@scarpacci Je devrais voir un [ mcve] dans mon propre code de test 'ToUInt16' fonctionne comme prévu –

+0

Je vais travailler pour obtenir un exemple Merci encore pour votre aide – scarpacci

0

Ce que j'ai trouvé, était que le ToInt16 me donne en fait les résultats que je voulais, pas ToUInt16 dans la solution. J'ai vérifié quelques résultats et ils correspondent tous à la sortie .Net.

Le link de @ pinkfloydx33 où j'ai pu voir le code source, est en fait ce qui m'a conduit à essayer d'utiliser ToInt16 au lieu de ToUInt16.