简体   繁体   中英

Representing signed byte in an unsigned byte variable

I apologies if the title of this question is not clear, but i cannot figure out the best way to describe my predicament in so few words.

I am writing a communication framework between java and C# using sockets and byte by byte transfer of information.

I have ran into an issue which has been confusing me for a good few hours now. As you hopefully know. java's byte base type is signed, meaning it can store -128 to +127 if you were to represent it in integer form. C# however, uses unsigned bytes, meaning that it store 0-255 in integer form.

This is where i am encountering the issue. If need to send some bytes of information from my c# client to my java server, i use the following code:

C#:

MemoryStream stream;

public void write(byte[] b, int off, int len) {
    stream.Write(b, off, len);
}

Java:

DataInputStream in;

public int read(byte[] b, int off, int len) throws IOException{
    in.read(b, off, len));
}

As you can see these are very very similar pieces of code that when used within their own languages will produce predictable results. However, due to the differences in the signing these will produce unusable data.

Ie if i send 255 from my c# client to java server, I will receive a value of -1 on the java server. This is because both of those values are represented of these 8 bits: 11111111

Preferably in order to solve this problem I would need to use the following code, using sbyte , c#'s signed byte.

C#:

MemoryStream stream;

public void write(sbyte[] b, int off, int len) {

    //Code to change sbyte into a byte but keeping it in the form in which java will understand

    stream.Write(b, off, len);
}

I basically need to store java's representation of a signed byte inside an unsigned C# byte in order to send that byte across to the server. I will also need to do this in reverse to get an sbyte out of a byte received from my java server.

I have tried numerous ways in which to do this with no success. If anyone has any idea as to how i can go about this i would be GREATLY appreciative.

You basically don't need to do anything except stop thinking about bytes as numbers. Think of them as 8 bits, and Java and C# are identical. It's rare that you really want to consider a byte as a magnitude - it's usually just binary data like an image, or perhaps encoded text.

If you want to send the byte 10100011 across from Java to C# or vice versa, just do it in the most natural way. The bits will be correct, even if the byte values will be different when you treat them as numbers.

It's not entirely clear what data you're actually trying to propagate, but in 99.9% of cases you can just treat the byte[] as opaque binary data, and transmit it without worrying.

If you do need to treat the bytes as magnitudes, you need to work out which range you want. It's easier to handle the Java range, as C# can support it with sbyte[] ... but if you want the range 0-255, you just need to convert the byte to an int on the Java side and mask it with the bottom 8 bits:

byte b = ...;
int unsigned = b & 0xff;

If you really need to treat byte[] as sbyte[] or vice versa on C#, you can use a little secret: even though C# doesn't allow you to convert between the two, the CLR does. All you need to do is go via a conversion of the reference to object to fool the C# compiler into thinking it might be valid - otherwise it thinks it knows best. So this executes with no exceptions:

byte[] x = new byte[] { 255 };
sbyte[] y = (sbyte[]) (object) x;
Console.WriteLine(y[0]); // -1

You can convert in the other direction in exactly the same way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM