1

I've been trying to translate the following Java code to C#.

    // two bytes to make a short (16 bit integer)
private short bytesToShort(byte hi, byte low) {
    return ByteBuffer.wrap(new byte[]{hi, low}).getShort();
}

So far this is what I've managed to put together from searching around:

    private short bytesToShort(byte hi, byte low)
{
    MemoryStream stream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(stream);

    writer.Write(hi);
    writer.Flush();
    writer.Write(low);
    writer.Flush();

    BinaryReader reader = new BinaryReader(stream);
    
    return reader.ReadInt16();
    
}

But I'm getting the "Unable to read beyond the end of stream" error. Adding stream.Position = 0; after the last writer.Flush(); fixes that issue but the values I'm getting are not correct. I assume I have more issue with the above code and the stream.Position = 0; is not the correct answer even if it seems to fix the issue.

Any suggestions?

UPDATE

I have two working solutions to this now. The first one is what Andreas posted as an answer below:

return (short) (((hi & 0xFF) << 8) | (low & 0xFF));

It works like a charm and I think out of the two solutions I have, this is the better one. The other is:

return BitConverter.ToInt16(new byte[2] { (byte)low, (byte)hi }, 0);

For this one I had to swap the positions of "low" and "hi" in order to get the correct results.

Important! For those translating from Java to C#, there is a very important difference between the Java byte and the C# byte.

Java byte is signed which means it takes values between -128 to 127 but the C# byte is unsigned which takes values between 0 and 255.

If you want to use the Java signed byte in C#, you have to use sbyte, this was a detail I was not aware off and it created issues for me.

Nick
  • 368
  • 1
  • 7
  • 16
  • 3
    Possible duplicate of https://stackoverflow.com/questions/5749801/converting-2-bytes-to-short-in-c-sharp – Sweeper Jun 26 '20 at 04:14

2 Answers2

4

return ByteBuffer.wrap(new byte[]{hi, low}).getShort() is the same as:

return (short) (((hi & 0xFF) << 8) | (low & 0xFF));

That version is the same in both Java and C#.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • This worked like a charm! While waiting I also found another answer which I will post as an update to my original post. – Nick Jun 26 '20 at 05:16
  • @Nick You "found"? I believe [Sweeper found it](https://stackoverflow.com/questions/62587779/translating-from-java-to-c-sharp-a-snippet-of-bytebuffer-code/62588238?noredirect=1#comment110682969_62587779) for you. – Andreas Jun 26 '20 at 10:01
  • You are correct, the solution was based on the link that Sweeper posted. – Nick Jun 26 '20 at 19:30
0

Its very simple in C#. You can use two methods in C#

First is

short sh = (short)((hi << 4) | low);

Second is you can use Convert.To function like below

sh =Convert.ToInt16((hi << 4) | low);

This convert is very powerful with many options. You can also explore BitConverter.ToInt16(byte[] array,int index)

Below is working code for console application in C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace testBitConvertor
{
    class Program
    {
        static void Main(string[] args)
        {
            byte hi = 1;
            byte low = 1;

            // short sh = BitConverter.ToInt16(new byte(hi << 8) | low),1);
            short sh = (short)((hi << 4) | low);
            Console.WriteLine(sh);
            sh =Convert.ToInt16((hi << 4) | low);
            Console.WriteLine(sh);
            Console.ReadKey();
        }
    }
}
Imran
  • 775
  • 7
  • 19