0

My question is about Java

What is the equivalent of BitConverter.ToUInt16 for Java?

I am trying to translate this method of C#:

public static implicit operator ushort(HashlinkReader p)
        {
            ushort tmp = BitConverter.ToUInt16(p.Data.ToArray(), p.Position);
            p.Position += 2;
            return tmp;
        }

to Java:

public static int convertToInt(HashlinkReader p)
    {
        byte[] byteArray = new byte[p.Data.size()];
        for (int index = 0; index < p.Data.size(); index++) {
            byteArray[index] = p.Data.get(index);
        }
        int tmp = toInt16(byteArray, p.Position);
        p.Position += 2;
        return tmp;
    }
    
    public static short toInt16(byte[] bytes, int index) //throws Exception
    {
        return (short)((bytes[index + 1] & 0xFF) | ((bytes[index] & 0xFF) << 0));
        //return (short)(
        //        (0xff & bytes[index]) << 8 |
        //                (0xff & bytes[index + 1]) << 0
        //);
    }

But I know that's wrong. How would be right?

Prateek Shrivastava
  • 1,877
  • 1
  • 10
  • 17
  • [This is the C# code](https://github.com/microsoft/referencesource/blob/master/mscorlib/system/bitconverter.cs#L188-L200) (not sure if it helps you though) – ProgrammingLlama Jun 30 '20 at 00:50
  • 1
    Your question would be more useful if you actually described what the desired functionality is, instead of assuming readers know what BitConverter.ToUInt16 does. At least include [a link to its documentation](https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint16?view=netcore-3.1). – VGR Jun 30 '20 at 01:16
  • Thank you for your tip. I remade the question here: https://stackoverflow.com/questions/62657220/equivalent-of-bitconverter-touint16-of-c-sharp-for-java-7 – Adalher2478 Jun 30 '20 at 12:16

1 Answers1

3

You want a ByteBuffer:

public static short toInt16(byte[] bytes, int index) {
    return ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder())
        .position(index).getShort();
}

For Java 7, the method calls are the same, but due to their return types, they need to be split into multiple lines:

public static short toInt16(byte[] bytes, int index) {
    ByteBuffer buffer =
        ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder());
    buffer.position(index);
    return buffer.getShort();
}
VGR
  • 40,506
  • 4
  • 48
  • 63
  • Note to OP: there is no unsigned short in Java, so it is expected that this code sometimes won't produce the same numerical result as the C# code, but it will be the same bit pattern. If you want the same numerical results, use an `int`. – Sweeper Jun 30 '20 at 01:33
  • @Adalher2478 Added Java 7 example to answer. Note that Java 7 is pretty old. The current version of Java is 14. – VGR Jun 30 '20 at 12:24
  • It still doesn't work for me :(. Please take a look at this console project: https://1drv.ms/u/s!An2GIBqaxDQCgTHpebTR408lFB5R. Specially at the class HashlinkReader, at the method convertToInt. The console must throw at the end the output: 54321. But instead of that it throws: 12756 – Adalher2478 Jul 01 '20 at 01:00
  • Oops, forgot that `slice()` resets the byte order. Answer updated. – VGR Jul 01 '20 at 01:17
  • @VGR your code works fine for most byte arrays. But what if byte is needed to be unsigned byte? I show you little C# code: https://pastebin.com/VmYkCvU9 and little Java code: https://pastebin.com/c0afYmP3. As you can see, at the first array there are no the same output from the toInt16 method as at the C# code. How can you work with unsigned bytes at your method? – Adalher2478 Jul 01 '20 at 09:37
  • It is important to remember that signed values and unsigned values are *exactly the same bits,* which are merely being interpreted differently. A short value of 0xffff can be interpreted as a signed value of -1, or an unsigned value of 65535. How it gets interpreted depends entirely on how you want to print it. Try using `short res = toInt16(a, 36);`, since defining it as an `int` forces the `short` value to be sign-extended to fit 32 bits. Then print it with `System.out.printf("Result = %#04x%n", res);`. – VGR Jul 01 '20 at 11:48
  • Trying with short I get the output: 0xd431. It's important for me to get the same output as with C# because the output represent a port that will be used to connect to a server. – Adalher2478 Jul 01 '20 at 12:20
  • I just discovered that if I make your method return an int, I get the same output as C#. – Adalher2478 Jul 01 '20 at 12:33