Link to home
Start Free TrialLog in
Avatar of karpra
karpra

asked on

How to Convert a String value of 33333 to unsinged short of 2 bytes

I have a String of values which are of 35444, 38444, which exceed the singed short (2 bytes) range. Is there any way which can convert those values to unsinged short. Thanks in advance.
Avatar of Mick Barry
Mick Barry
Flag of Australia image

java does not have an unsigned short. The only unsigned type is chae.

you could subtract 32767 (or a suitable offset) from the value and then store it as a short. You just need to remember to shift it back when you want to use the value.

Avatar of karpra
karpra

ASKER

if i shift it to 33333 >> 16 and then i need to shift it back when i read it...?
just parse it as an int then subtract the offset and assign to a short.
convert it back (to an int) when you need to use it.

http://helpdesk.objects.com.au/java/how-to-convert-a-string-to-an-int

Avatar of karpra

ASKER

I parsed the int value but one doubt what is the offset value  i am not sure about that...?
shorts range from -32,768 to 32,767
Avatar of karpra

ASKER

ok i got it...what i am doing is using the unsinged value which i receive (33345)  i have to fit this value into 2 bytes and send it to a c++/vb application which uses it as 2 bytes place holder. since java does not support unsinged short values i cannot use an int which is 4 bytes to store. Now i am getting out of range error because of the size issue but the c++ / vb code has that flexibility to hadle unsinged short but the problem is how can i pass the out of range unsinged value to the native application.

Also i need to pass that 2 bytes of unsinged short in bytes to the native app. what ever you suggested looks good but i am not able to put all together to come up wiht a method which can return me an unsinged value of 2 bytes. ....
>>and send it to a c++/vb application

How do you do that exactly?
Avatar of karpra

ASKER

we convert that value to bytes and send it then the other side they will read the bytes and convert to their local datatype we have a structure mapping based on it we were able to do it.....
>>and send it then the other side

But how?
If you're doing it over TCP/IP you just need to use DataOutputStream.writeShort
to send it try this:

out.write((byte) ((n >> 8) & 0xff));
out.write((byte) (n & 0xff));

With io, you don't need to worry about signed/unsigned - that's purely a view issue. The only issue you need to be concerned about is that the native side is reading in 'network byte order'
Avatar of karpra

ASKER

I just tried it local to read that 2 bytes and get the same value somethinglike this

public static void main ( String args [  ]  )   {  
           int n = 33333;
           System.out.println(n);
        byte bt[] = null;
        bt = toBytess(n);
        System.out.println(bt.length);
        System.out.println(toShort(bt));
      
      }
      
public static byte[] toBytess(int n)
    {
        return new byte[]{(byte) ((n >> 8) & 0xff),(byte)((n & 0xff)>>8)};
    }

Reading the value in short this might not be correct as the value exceeds the limits. any suggestions how to read that 2 bytes value back.
public static short toShort(byte[] b)
    {
        return (short)(b[1]<<8 | b[0]);
    }
>>this might not be correct as the value exceeds the limits

You can't treat an unsigned short as a java short, as it will overflow. An unsigned short in java is a char, so if you return char (or int) you'll be OK. char is in fact the *only* unsigned type in java

I note btw that your method to convert to byte[] is wrong. See below for how you could do it, such that:

        int n = 33333;
        byte[] bytes = toBytes(n);
        System.out.println((int)toShort(bytes));

will be symmetrical

    public static byte[] toBytes(int i) {
        return new byte[] { (byte) (i & 0xff), (byte) (i >> 8) };
    }   
 
    public static char toShort(byte[] b) {
        return (char) ((b[1] << 8) | b[0]);
    }

Open in new window

Avatar of karpra

ASKER

ok thanks for correcting so when i run the code with the above methods..i get a char of "?" as output. which is a one byte value?

public static void main ( String args [  ]  )   {  
           int n = 33333;
           System.out.println((short)n);
        byte bt[] = null;
        bt = toBytes(n);
        System.out.println(toShort(bt));
              }
>>so when i run the code with the above methods..i get a char of "?" as output. which is a one byte value?

That's because you're making System.out think it's a char as in alphabet. You need to cast it to an int  as i did
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of karpra

ASKER

we have to pass as little endian. so the method returns an int type casted to short? the output value is 13698 which is not 33333 which i pass

public static int toShort(byte[] b) {
              return (char) ((b[0] & 0xff) << 8) | (b[1] & 0xff);
    }

or heres LE stream class with methods to read unsigned short

http://www.javafaq.nu/java-example-code-1079.html

>>the output value is 13698 which is not 33333 which i pass

That will be a result of passing it a byte[] containing a *big* -endian representation. You need to pass it a little-endian
If you find this a little confusing (it can be), the following approach could make it clearer (import java.nio.ByteBuffer, java.nio.ByteOrder):
    public static byte[] unsignedShort2ByteArrayLittleEndian(char c) {
        ByteBuffer bb = ByteBuffer.allocate(2);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        bb.putChar(c);
        return bb.array();
    }   
 
    public static int toUnsignedShortLittleEndian(byte[] b) {
        ByteBuffer bb = ByteBuffer.wrap(b);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        return bb.getChar();
    }   

Open in new window

Avatar of karpra

ASKER

Hi guys..sorry for delay...the actual test started now
i have got some string value = " 65455 " Now my goal is to store this value in 2 bytes datatype short (max 32,767) in java which is equivalent to 2 byte datatype unsinged int (max 65535) in C++.

when i tried to store i get the index out of range in java for value above 32,767. how can i store bigger value in 2 bytes (any datatype that support since there is no unsinged int in java)

I tried the above suggestion of little endian but i am little confused.
you'll need to use an int to store it.
to store it as a short you'll need to offset it and I showed earlier, (after parsing it as an int)

int i = Integer.parseInt(value);
short x = (short) (i - offset);

that assumes the range of possible values is less than the range available to short

Avatar of karpra

ASKER

thanks...that was quick..
so if i pass this short of 2 bytes value then the c++ guy willl have to know the offset to get his unsinged int value on the other side? or is there any way i can convert into two bytes short and pass it and they just use that value with their datatype unsingedInt to read that big value.
no thats for holding it in a short on the java side
if you're sending it over the wire then use the little endian stream class I posted earlier, it has a method to write an unsigned short

int i = Integer.parseInt(value);
led.writeShort(i);

http://www.javafaq.nu/java-example-code-1078.html
Avatar of karpra

ASKER

Hi guys..i amback again....i think i am close to the solution but this does not let me...here is what i tried
pls help me where i am going wrong.is this the right approch....i followed the link and tried to do some thing like this...

public static void main ( String args [  ]  )   {  
        int n = 33333;
         writeShort(n);
   }
public static void writeShort(int s) {
      
      byte[] b = new byte[2];
      b[0] = (byte)(s & 0xFF);
      b[1] = (byte)((s >>> 8) & 0xFF);
        
         System.out.println(toShort(b));  I am expecting this will print my original value 33333 which prints 13698 , pls help me where i amn going wrong.

         System.out.println(s & 0xFF);
         System.out.println((s >>> 8) & 0xFF);
            System.out.println((byte)(s & 0xFF));
       System.out.println((byte)((s >>> 8) & 0xFF));
   }

public static int toShort(byte[] b) {
    return  ((b[0] & 0xff) << 8) | (b[1] & 0xff);
}
Avatar of karpra

ASKER

i Need to give the value 33333 somhow fit in two bytes array size and pass when c++ code reads that 2 bytes i will get the value 33333 back. Now if there is any way i can convert any value between 32767 and 65000 into 2 bytes in java and send so that c++ can read it and get the same value then my job is done..how can i test this scenario...
the class I posted above has a method to do it, did it not work?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial