3

buffer is a bytebuffer .I'm getting a lost of percision error with this.

    byte myPort = buffer.get(0); // Might need to change this depending on byte order
    switch(myPort){
        case 0xF1: // Chat service
            break;
        case 0xF2: // Voice service
            break;
        case 0xF3: // Video service
            break;
        case 0xF4: // File transfer service
            break;
        case 0xF5: // Remote login
            break;
    }

Apparently, 0xFF is not a byte in java and its really confusing me. I don't know if I'm losing it but isn't 0xF a nibble and 0xFF a byte? Apparently my ide netbeans allows byte values all the way up to 127. This seems to be a problem with signed values, but I'm not sure why.

Thanks for any help.

Dr.Knowitall
  • 10,080
  • 23
  • 82
  • 133
  • 1
    And where are you getting that error? Also, I don't see any use of `0xFF` in the code. Is that code complete? – Rohit Jain Dec 13 '12 at 06:34
  • I get the error at case 0xF1 and so forth. The cases are giving me the error. This is not the whole code, but its the only relevant part of the code. – Dr.Knowitall Dec 13 '12 at 06:35
  • That's because your value `0xF1` is not in the byte range - `[-128, 127]`. byte in Java is signed. `0xF1` is equal to `241`. – Rohit Jain Dec 13 '12 at 06:37
  • Lol, who knew. Unsigned bytes make more sense to me in networking so I don't understand why they wouldn't offer it in Java. The idea of casting to an integer makes me cringe since I'm a C/C++ programmer. – Dr.Knowitall Dec 13 '12 at 06:51

2 Answers2

4

As already stated in the comments, byte is [-128 .. 127].

You should convert your byte from the byte buffer to int, to preserve the "unsigned byte" range you assume (and which does not exist in Java):

  int myPort = buffer.get(0) & 0xff; // Might need to change this depending on byte order
  switch(myPort){
      case 0xF1: // Chat service
          break;
      case 0xF2: // Voice service
          break;
      case 0xF3: // Video service
          break;
      case 0xF4: // File transfer service
          break;
      case 0xF5: // Remote login
          break;
  }

Note that simply assigning the byte to an int would not work due to sign extension:

  byte val = (byte) 0xb6;  
  int myPort = val;

results in myPort = -74 (0xffffffb6), while

  byte val = (byte) 0xb6;
  int myPort = val & 0xff;

results in myPort = 182 (0xb6).


See Why doesn't Java support unsigned ints? for some good background information on the absence of unsigned data types in Java

Community
  • 1
  • 1
Andreas Fester
  • 36,091
  • 7
  • 95
  • 123
  • 1
    I guess I learned something new. Sorry I'm a C/C++ programmer so I'm used to usigned bytes and things like that. I didn't know that it didn't exist in java. – Dr.Knowitall Dec 13 '12 at 06:50
  • Its one of the design decisions of Java which cause headache even for long time Java programmers :) – Andreas Fester Dec 13 '12 at 06:51
1

You are correct: a Java "byte" is a signed number between -127 and 127.

The solution is simply to cast to "short" or "int".

EXAMPLE:

int myPort = buffer.get(0); // Might need to change this depending on byte order
    switch(myPort){
        case 0xF1: // Chat service
            break;
        case 0xF2: // Voice service
            break;
        case 0xF3: // Video service
            break;
        case 0xF4: // File transfer service
            break;
        case 0xF5: // Remote login
            break;
    }

If you prefer to leave "myPort" a "byte", then simply cast to int in your switch statement:

EXAMPLE:

byte myPort = buffer.get(0); // Might need to change this depending on byte order
    switch(0xff & (int)myPort){
        case 0xF1: // Chat service
            break;
        ...

Either way, the BITS are the same: it's their MEANING that's causing the compile error.

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • 1
    Don't you have to mask myPort with `(myPort & 0x00FF)` to avoid sign extension? – josefx Dec 13 '12 at 06:42
  • No I don't need to mask myPort since I'm only sending the least significant byte through the network. I assume that the higher byte is 0xFF in my program. Its a server that makes a connection upon least byte request and then changes the client channel socket to bind to (0xFF00 | myPort). I want to send as little as possible through the network. – Dr.Knowitall Dec 13 '12 at 06:57
  • @Mr.Student the problem is that javas byte is signed, so the most significant bit is interpreted as a signed bit. Casting a signed byte to a int in java will "extend" the sign. A byte with all bits set will be converted to 0xffffffff instead of 0x000000ff. – josefx Dec 13 '12 at 07:25