0

My question is about Java.

I need a method that returns an unsigned 16-bit integer converted from two bytes at the specified position in a byte array.

In other words I need the equivalent of the method BitConverter.ToUInt16 of C# for Java that works with Java 7.

In C#

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;

namespace CSharp_Shell
{

    public static class Program 
    {
        public static void Main() 
        {
           byte[] arr = { 10, 20, 30, 40, 50};
           ushort res = BitConverter.ToUInt16(arr, 1);
           Console.WriteLine("Value = "+arr[1]);
           Console.WriteLine("Result = "+res);
        }
    }
}

I get the output:

Value = 20
Result = 7700

But when I translate it to Java

import java.util.*;

    public class Main
    {
        public static void main(String[] args)
        {
            byte[] arr = { 10, 20, 30, 40, 50};
            int tmp = toInt16(arr, 1);
            System.out.println(("Value = "+arr[1]));
            System.out.println(("Result = "+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
            //);
        }
    }

I am expecting the same output as at C#, but instead of that I get the output:

Value = 20
Result = 30

How can I get the same output with Java?

  • 1
    Why did you comment out the (almost) correct implementation? – Sweeper Jun 30 '20 at 12:20
  • 1
    Don't you have to shift the high 8 bits to left by 8? ```return (short)(((bytes[index + 1] & 0xFF) << 8) | (bytes[index] & 0xFF));``` – Felix Jun 30 '20 at 12:23
  • Side note: Java 7 is quite old. Consider to move at least to Java 8 (better Java 11+). There are also new utility methods, e.g.: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Short.html#toUnsignedInt(short) – Puce Jun 30 '20 at 12:29
  • `ByteBuffer.wrap(bytes, index, 2).order(ByteOrder.LITTLE_ENDIAN).getShort()` –  Jun 30 '20 at 12:41

1 Answers1

0

Java does not provide support for primitive unsigned integers values, but you could utilize the Integer class to handle unsigned values. That said, you can adapt a wrapper class that simulates the behavior in C#.

As codeflush.dev mentioned, you need to shift the higher-order bits.

public class BitConverter {
    /**
     * Returns a 16-bit "unsigned" integer converted from two bytes at a specified position in a byte array.
     *
     * @param value      The array of bytes.
     * @param startIndex The starting position within value.
     * @return A 16-bit "unsigned" integer formed by two bytes beginning at startIndex.
     * @throws IndexOutOfBoundsException
     * @see <a href="https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.touint16?view=netcore-3.1">
     * BitConverter.ToUInt16(Byte[], Int32)</a>
     */
    public static final short toInt16(byte[] value, int startIndex) throws IndexOutOfBoundsException {
        if (startIndex == value.length - 1) {
            throw new IndexOutOfBoundsException(String.format("index must be less than %d", value.length - 2));
        }
        return (short) (((value[startIndex + 1] & 0xFF) << 8) | (value[startIndex] & 0xFF));
    }
}
public class Main {
    public static void main(String[] args) {
        byte[] arr = {10, 20, 30, 40, 50};
        int tmp = BitConverter.toInt16(arr, 1);
        System.out.println(("Value = " + arr[1])); // 20
        System.out.println(("Result = " + tmp));   // 7700
    }
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132