I am implementing a Bluetooth Android application, where Image is sent from one device to another. The bitmap's byte array is sent and successfully reconstructed at the receiver end. However, I need to send a single integer value together with the bitmap as an index(so the receiver knows what to do with the received bitmap). So basically I want to send this in a byte stream:
int|bitmap
Since I need to transfer an int up to 27, that means it fits into a single byte, right? My current code looks like this:
ba[0] = Integer.valueOf(drawableNumber).byteValue(); //drawableNumber value is between 1 and 27
ByteArrayOutputStream bs = new ByteArrayOutputStream(); //create new output stream
try {
bs.write(ba); //bytes of the integer
bs.write(bitmapdata); //bytes of the bitmap
bs.toByteArray() // put everything into byte array
}
mChatService.write(bs.toByteArray()); // that is where bytes are sent to another device
And at the receiver end:
case MESSAGE_READ:
readBuf = (byte[]) msg.obj; // readBuf contains ALL the received bytes using .read method
So my question is, how can I reconstruct the integer and the image I have sent(basically a single byte to a single integer)? I manage to reconstruct the bitmap alone, but I need this additional integer value to know what to do with the received image. The integer value will always be between 0 and 27. I have checked all other answers, but could not find a proper solution..
EDIT: Main question is how to separate the integer bytes from the bitmap bytes in the byte array. Because at the receiving end I want to reconstruct the sent integer AND the bitmap separately
Since converting a byte to an int is a downcast, you can just assign the byte to an int variable.
int myInt = ba[0];
When I try this in java, it simply tells me what my mind was thinking when I commented. An integer is represented as a byte (so in your case, it is simply ba[0]). Or it should be based on your code. Any more than that and it would be a long. That means it is also the first byte that will get read out of your buffer (or should be).
import java.io.ByteArrayOutputStream;
public class TestClass {
public static void main(String args[]){
byte[] ba = new byte[10];
int myInt = 13;
ByteArrayOutputStream bs = new ByteArrayOutputStream(); //create new output stream
try {
bs.write(myInt); //bytes of the integer
ba = bs.toByteArray(); // put everything into byte array
} finally{};
for(int i = 0; i < ba.length; i++){
System.out.println(i);
System.out.println(ba[i]);
}
}
}
Again I realize this isn't exactly an answer, just too much for a comment.
Related
So I asked this question a few days ago, but maybe I can elaborate a bit more, or in a different way now. I am a big java and android newbie, so it takes a lot of time to figure stuff out for me. I have a Bluetooth connecting between 2 devices. I tried using sensors and everything works fine. The devices connect and they send sensor values to one another.
This sensor value, however, is auto-generated. What I want is to get DB values from one of the devices, convert them to bytes, add them to a byte array and send this byte array as a single message to the other device, where it is going to reverse the process. I have everything set up, everything is as it should be with only 1 exception - I need to somehow catch the incomingMessage as a byte array, so I can finish the process.
How can I get the value of the incomingMessage(which is supposed to be transferring a byte array) and add it to another byte array that I am then "decoding"?
The commented out one is the example that I tried and was working.
if (mBluetoothConnection.incomingMessage != null) {
//messageTemp = mBluetoothConnection.incomingMessage;
msg = mBluetoothConnection.incomingMessage;
}
The one that is not commented out is the one, whose value I want to assign to a byte array:
byte[] array = msg;
This is the only thing that I have not been able to figure out so far.
My current issue is that "array" returns null object reference.
Please, help me! I feel like I have almost connected 2 bridges and the paint on each differest by just a centimeter from being okay.
Alright, I managed to figure it out, but forgot to update, here is my other post with a little bit more code:
How can I assing the value of an incoming Bluetooth message to a byte array which I want to decode into integers?
Here's what I changed:
I only touched the run() method in my BluetoothConnectionService
Instead of using the byte[] buffer, as I mention in the commented code, I declared a public static byte[] incomingBytes and gave it a size of 44, since this is what my 11 integer array going to need. Then I just replaced the "buffer" with "incomingBytes" in the example code, and looks like this:
public static byte[] incomingBytes = new byte[44];
public void run(){
//byte [] buffer replaced with incomingBytes
byte[] buffer = new byte[44]; // this was in the example, but it is not used. It was replaced by incomingBytes, declared at the start of the class
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mmInStream.read(incomingBytes);
incomingMessage = new String(incomingBytes, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
Then I only need to call incomingBytes for my convertion in the other class and it works fine.
byte [] r = new byte[4096];
DatagramPacket dpr = new DatagramPacket(r, r.length);
sock.receive(dpr);
After the receive, will dpr.getData() & r always be the same?
ex: Can I directly use the byte array r or do I need to call getData() to retrieve the buffer again?
Testing it, showed it to be the same, but is this always guaranteed?
byte [] r = new byte[4096];
DatagramPacket dpr = new DatagramPacket(r, r.length);
sock.receive(r);
That should be sock.receive(dpr);
After the receive, will dpr.getData() & r always be the same?
Yes. r was supplied to the constructor as 'the buffer for holding the incoming datagram', and getData() 'returns the buffer used to receive or send data'.
i.e. can I directly use the byte array r or do I need to call getData() to retrieve the buffer again?
You can use the byte array, but why? Use getData() like everybody else, not forgetting to also use getOffset() and getLength(), rather than assuming the datagram filled the byte array: for example, System.out.println(new String(datagram.getData(), datagram.getOffset(), datagram.getLength()));
I have some data in a byte array, retrieved earlier from a network session using non-blocking IO (to facilitate multiple channels).
The format of the data is essentially
varint: length of text
UTF-8: the text
I am trying to figure out a way of efficiently extracting the text, given that its starting position is undetermined (as a varint is variable in length). I have something that's really close but for one small niggle, here goes:
import com.clearspring.analytics.util.Varint;
// Some fields for your info
private final byte replyBuffer[] = new byte[32768];
private static final Charset UTF8 = Charset.forName ("UTF-8");
// ...
// Code which extracts the text
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(replyBuffer);
DataInputStream inputStream = new DataInputStream(byteInputStream);
int textLengthBytes;
try {
textLengthBytes = Varint.readSignedVarInt (inputStream);
}
catch (IOException e) {
// I don't think we should ever get an IOException when using the
// ByteArrayInputStream class
throw new RuntimeException ("Unexpected IOException", e);
}
int offset = byteInputStream.pos(); // ** Here lies the problem **
String textReceived = new String (replyBuffer, offset, textLengthBytes, UTF8);
The idea being that the text offset in the buffer is indicated by byteInputStream.pos(). However that method is protected.
It seems to me that the only way to get the "rest" of the text after decoding the varint is to use something that copies it all into another buffer but that seems rather wasteful for me.
Constructing the string directly from the underlying buffer should be fine, because after this I don't care anymore for the state of byteInputStream or inputStream. So I am trying to figure out a way to calculate offset, or, put another way, how many bytes Varint.readSignedVarInt consumed. Perhaps there is an efficient method of converting from the integer value returned by Varint.readSignedVarInt to the number of bytes that would have taken up in the encoding?
There are a few ways you can find the offset of the string in the byte array:
You can create a subclass of ByteArrayInputStream that gives you access to the pos field. It has protected access so that subclasses can use it.
If you want something more generally applicable, create a subclass of FilterInputStream that counts the number of bytes that have been read. This is more work and probably not worth the effort though.
Count the number of bytes that encode the varint. There are at most 5.
int offset = 0; while (replyBuffer[offset++] < 0);
Calculate the number of bytes needed to encode a varint. Each byte encodes 7 bits so you can take the position of the highest 1 bit and divide by 7.
// "zigzag" encoding required since you store the length as signed
int textLengthUnsigned = (textLengthBytes<<2) ^ (textLengthBytes >> 31);
int offset = (31 - Integer.numberOfLeadingZeros(textLengthUnsigned))/7 + 1
Hello boys and girls.
I'm developing a terminal based client application which communicates over TCP/IP to server and sends and receives an arbitary number of raw bytes. Each byte represents a command which I need to parse to Java classes representing these commands, for further use.
My question how I should parse these bytes efficiently. I don't want to end up with bunch of nested ifs and switch-cases.
I have the data classes for these commands ready to go. I just need to figure out the proper way of doing the parsing.
Here's some sample specifications:
Byte stream can be for example in
integers:[1,24,2,65,26,18,3,0,239,19,0,14,0,42,65,110,110,97,32,109,121,121,106,228,42,15,20,5,149,45,87]
First byte is 0x01 which is start of header containing only one byte.
Second one is the length which is the number of bytes in certain
commands, only one byte here also.
The next can be any command where the first byte is the command, 0x02
in this case, and it follows n number of bytes which are included in
the command.
So on. In the end there are checksum related bytes.
Sample class representing the set_cursor command:
/**
* Sets the cursor position.
* Syntax: 0x0E | position
*/
public class SET_CURSOR {
private final int hexCommand = 0x0e;
private int position;
public SET_CURSOR(int position) {
}
public int getPosition() {
return position;
}
public int getHexCommnad() {
return hexCommand;
}
}
When parsing byte streams like this the best Design Pattern to use is the Command Pattern. Each of the different Commands will act as handlers to process the next several bytes in the stream.
interface Command{
//depending on your situation,
//either use InputStream if you don't know
//how many bytes each Command will use
// or the the commands will use an unknown number of bytes
//or a large number of bytes that performance
//would be affected by copying everything.
void execute(InputStream in);
//or you can use an array if the
//if the number of bytes is known and small.
void execute( byte[] data);
}
Then you can have a map containing each Command object for each of the byte "opcodes".
Map<Byte, Command> commands = ...
commands.put(Byte.parseByte("0x0e", 16), new SetCursorCommand() );
...
Then you can parse the message and act on the Commands:
InputStream in = ... //our byte array as inputstream
byte header = (byte)in.read();
int length = in.read();
byte commandKey = (byte)in.read();
byte[] data = new byte[length]
in.read(data);
Command command = commands.get(commandKey);
command.execute(data);
Can you have multiple Commands in the same byte message? If so you could then easily wrap the Command fetching and parsing in a loop until the EOF.
you can try JBBP library for that https://github.com/raydac/java-binary-block-parser
#Bin class Parsed { byte header; byte command; byte [] data; int checksum;}
Parsed parsed = JBBPParser.prepare("byte header; ubyte len; byte command; byte [len] data; int checksum;").parse(theArray).mapTo(Parsed.class);
This is a huge and complex subject.
It depends on the type of the data that you will read.
Is it a looooong stream ?
Is it a lot of small independent structures/objects ?
Do you have some references between structures/objects of your flow ?
I recently wrote a byte serialization/deserialization library for a proprietary software.
I took a visitor-like approach with type conversion, the same way JAXB works.
I define my object as a Java class. Initialize the parser on the class, and then pass it the bytes to unserialize or the Java object to serialize.
The type detection (based on the first byte of your flow) is done forward with a simple case matching mechanism (1 => ClassA, 15 => ClassF, ...).
EDIT: It may be complex or overloaded with code (embedding objects) but keep in mind that nowadays, java optimize this well, it keeps code clear and understandable.
ByteBuffer can be used for parsing byte stream - What is the use of ByteBuffer in Java?:
byte[] bytesArray = {4, 2, 6, 5, 3, 2, 1};
ByteBuffer bb = ByteBuffer.wrap(bytesArray);
int intFromBB = bb.order(ByteOrder.LITTLE_ENDIAN).getInt();
byte byteFromBB = bb.get();
short shortFromBB = bb.getShort();
I'm sending a byte array through a socket and I'm receiving it through a DataInputStream. I don't know the size of the byte array, and there's no way to check. I've tried doing this:
byte[] content = new byte[ARRAY_SIZE];
int something;
while((something = inFromStream.read()) > 0)
output.write(something);
This however, still means that I need to know the size of the byte array. I don't want to just fill in a gigantic number (since the byte array received from the stream could be 100 or maybe even 5000000000). How do I deal with this (preferably with the standard Java API/libraries)?
You can send the byte[] piece wise to the OutputStream
byte[] buffer = new byte[1024 /* or some other number */];
int numRead;
while((numRead = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, numRead);
}
The way around - just logic without code sample
getSizeOfInput int countTokens (){
readInput tokenizeInput countTokens
return countTokens }
create an array with the size of countTokens
But all in all - look at the link
create an ArrayList of bytes