I am developing a software in Android. In a particular portion of software, I need to convert short to byte and re-convert to it to short. I tried below code but values are not same after conversion.
short n, n1;
byte b1, b2;
n = 1200;
// short to bytes conversion
b1 = (byte)(n & 0x00ff);
b2 = (byte)((n >> 8) & 0x00ff);
// bytes to short conversion
short n1 = (short)((short)(b1) | (short)(b2 << 8));
after executing the code values of n and n1 are not same. Why?
I did not get Grahams solution to work. This, however do work:
n1 = (short)((b1 & 0xFF) | b2<<8);
You can use a ByteBuffer:
final ByteBuffer buf = ByteBuffer.allocate(2);
buf.put(shortValue);
buf.position(0);
// Read back bytes
final byte b1 = buf.get();
final byte b2 = buf.get();
// Put them back...
buf.position(0);
buf.put(b1);
buf.put(b2);
// ... Read back a short
buf.position(0);
final short newShort = buf.getShort();
edit: fixed API usage. Gah.
Related
I get two java bytes as input that together symbolizes a 16-bit signed integer. I need to convert it to one single java integer (signed, of course). I have come up with a "ugly" solution, that includes converting to an int, then to a short and then back to an int. Is there a shorter and more elegant way?
My code is as following:
public int convert(byte b1, byte b2){
int i1 = (int) (((b2 << 8) + (b1 & 0xFF)) & 0x0000FFFF);
short s1 = (short) i1;
int i2 = (int) s1;
return i2;
}
This seems to match your converter - not certain it is simpler but it is certainly less verbose.
public int convert2(byte b1, byte b2) {
return new BigInteger(new byte[]{b2,b1}).intValue();
}
The following is equivalent:
return (short) ((b2 << 8) | (b1 & 0xFF));
byte has a small enough range that it is practical to test this equivalence for all possible values of b1 and b2:
byte b1 = Byte.MIN_VALUE;
do {
byte b2 = Byte.MIN_VALUE;
do {
assertEquals(convert(b1, b2), convertEquivalent(b1, b2));
} while (b2++ != Byte.MAX_VALUE);
} while (b1++ != Byte.MAX_VALUE);
Ideone demo
#AndTurner is probably the solution you sought.
However if a byte array or some file channel (memory mapped file), input stream is involved, one may use a ByteBuffer.
byte[] bytes = ...
ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
...
short n = buf.readShort(); // Sequential
short m = buf.readShort(354L); // Direct access
I have a short counter which increments and is used as an identifier. I need to send the identifier as binary data on a network socket.
So if I have a short value I can do this to 'pack' in two bytes:
short id = 1;
byte val = (byte)(id & 0xFF);
byte val2 = (byte)((id >>> 8) & 0xFF);
System.out.printf("id=%d, val = id & 0xFF = %d, val2 = (id >>> 8) & 0xFF = %d\n",
id, val, val2);
Now when id = 1 this works fine.
But when id = 255 I get:
short id = 255;
byte val = (byte)(id & 0xFF); //val = -1
byte val2 = (byte)((id >>> 8) & 0xFF); //val2 = 0
Now I know that 255 in binary is 11111111 and this means -1 for a java byte value. Am I correct in thinking that how java interprets it is immaterial and if I send as byte binary 11111111 then at the other end it can interpret this however it wants?
Yes, your thinkings are right.
Just for your information: there is a very nice class that does this for you. It is called DataInputStream and DataOutputStream.
Socket socket = ...;
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
/* Write a short */
short out = 255;
dos.writeShort(out);
/* Read a short */
short in = dis.readShort();
In Java, all data types are interpreted as signed. That is, any number with most significant bit equal to 1 is a negative number. When you send the number over the network it doesn't matter how it's interpreted by Java, as you still send the same bits. So yes, your code will work as intended.
I have some problems trying yo convert short value to byte[2]. I'm using this to make some transformations on some audio data buffer(applying gain to buffer). First I load the audio buffer like this:
mRecorder.read(buffer, 0, buffer.length);
where buffer is
private byte[] buffer;
Than, I get the sample (the recording is in 16bit sample size), like this:
short sample = getShort(buffer[i*2], buffer[i*2+1]);
The getShort is define like this:
/*
*
* Converts a byte[2] to a short, in LITTLE_ENDIAN format
*
*/
private short getShort(byte argB1, byte argB2)
{
return (short)(argB1 | (argB2 << 8));
}
Then I apply gain to the sample:
sample *= rGain;
After this, I try to get back the byte array from the multiplied sample:
byte[] a = getByteFromShort(sample);
But this fails, because the sound has a lot of noise even if the gain is 1.
Below is the getByteFromShort method definion:
private byte[] getByteFromShort(short x){
//variant 1 - noise
byte[] a = new byte[2];
a[0] = (byte)(x & 0xff);
a[1] = (byte)((x >> 8) & 0xff);
//variant 2 - noise and almost broke my ears - very loud
// ByteBuffer buffer = ByteBuffer.allocate(2);
// buffer.putShort(x);
// buffer.flip();
return a;
}
So the problem is when converting the short value to byte[2]. When the gain was 1.0, the sound was fill with noise.
Below is the full gain applying method:
for (int i=0; i<buffer.length/2; i++)
{ // 16bit sample size
short curSample = getShort(buffer[i*2], buffer[i*2+1]);
if(rGain != 1){
//apply gain
curSample *= rGain;
//convert back from short sample that was "gained" to byte data
byte[] a = getByteFromShort(curSample);
//modify buffer to contain the gained sample
buffer[i*2] = a[0];
buffer[i*2 + 1] = a[1];
}
}
Could you guys please take a look over getByteFromShort method and tell me where I'm wrong?
Thanks.
getByteFromShort() seems OK.
getShort(byte argB1, byte argB2) is wrong. It produces incorrect result when argB1 is negative.
It should be
return (short)((argB1 & 0xff) | (argB2 << 8));
Use the following code:
ret[0] = (byte)(x & 0xff);
ret[1] = (byte)((x >> 8) & 0xff);
I would use ByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(8*1024);
mRecorder.read(buffer.array(), 0, buffer.capacity());
// using NIO
mRecorder.read(buffer);
while(buffer.remaining() > 1) {
short s = bb.getShort(x);
// do something with s
}
ByteBuffer and its cohorts in java.nio can help with this. Basically, you will create a ByteBuffer backed by an array with your data ByteBuffer.wrap(array). You can then set the endianness of the buffer with ByteBuffer.order() and use functions like get/put Int/Short/byte... to manipulate data in the underlying array.
I'm trying to append two bytes that have hex values and store them into an integer. So obviously everything will be unsigned values.
I'll provide an example since that is much easier to see.
two bytes
0x20 0x07
Integer
Edit: Oops I made a huge mistake here. Sorry for all the confusion.
I want integer to store 2007 not 0x2007. I'm really sorry about that.
Is there way to do this without converting the byte to String and append and switch to int?
or is converting to String is the only way?
You can try
byte b1 = (byte) 0x90;
byte b2 = (byte) 0xF7;
int i = ((b1 & 0xFF) << 8) | (b2 & 0xFF);
However if you are using DataInputStream or ByteBuffers you usually don't need to do this. Just use getShort in both cases.
Yes, just shift b1 by 8 bits and add it to b2:
byte b1 = 0x20;
byte b2 = 0x07;
int i1 = (b1 << 8) + b2; // gives 0x2007
// alternatively
int sameInt = b1 * 256 + b2; // gives 0x2007
I know the file structure, suppose this structure is this:
[3-bytes long int],[1-byte long unsigned integer],[4-bytes long unsigned integer]
So the file contains chains of such records.
What is the most elegent way to parse such a file in Java?
Supposedly, we can define a byte[] array of overall length and read it with InputStream, but how then convert its subelements into correct integer values?
First thing, byte value in java is signed, we need unsigned value in our case.
Next thing, are there useful methods that allow to convert a sub-array of bytes, say, bytes from 1-st to 4-th into a correct integer value?
I know for sure, there are functions pack & unpack in Perl, that allow you to represent a string of bytes as an expression, let's say "VV" means 2 unsigned long int values. You define such a string and provide it as an argument to a pack or unpack functions, along with the bytes to be packed/unpacked. Are there such things in Java / Apache libs etc ?
Like #Bryan Kyle example but shorter. I like shorter, but that doesn't mean clearer, you decide. ;) Note: readByte() is signed and will have unexpected results if not masked with 0xFF.
DataInputStream dis = ...
// assuming BIG_ENDIAN format
int a = dis.read() << 16 | dis.read() << 8 | dis.read();
short b = (short) dis.read();
long c = dis.readInt() & 0xFFFFFFFFL;
or
ByteBuffer bb =
bb.position(a_random_postion);
int a = (bb.get() & 0xFF) << 16 | (bb.get() & 0xFF) << 8 | (bb.get() & 0xFF);
short b = (short) (bb.get() & 0xFF);
long c = bb.readInt() & 0xFFFFFFFFL;
You may take a look at this sample BinaryReader class which is based on the DataInputStream class.
You should be able to do this using a DataInputStream. It's been a while since I've done much development like this, but the trick I seem to remember is that if there's an impedance mis-match between your input format and the language's data types you'll need to construct the data byte by byte. In this case, it looks like you'll need to do that because the data structure has oddly sized structures.
To give you an example to read the first record you might need to do something like this (I'm using a, b, and c for the attributes of the record)
DataInputStream dis = ...
int a = 0;
a = dis.readByte();
a = a << 8;
a = a | dis.readByte();
a = a << 8;
a = a | dis.readByte();
short b = 0;
b = dis.readByte();
long c = 0;
c = dis.readByte();
c = c << 8;
c = c | dis.readByte();
c = c << 8;
c = c | dis.readByte();
c = c << 8;
c = c | dis.readByte();
Obviously, this code could be tightened up by compounding some of the statements, but you get the general idea. What you might notice is that for each of the attributes being read I have to use a primitive that's larger than needed so there aren't any overflow errors. For reference, in Java:
byte = 1 byte
short = 16 bit, 2 bytes
int = 32 bits, 4 bytes
long = 64 bits, 8 bytes