Looking for a solution to why my readShort function won't properly read this number (602).
byte array contains:
0x02 0x05 0x02 0x5A
byte tab = pkt.read(); //successfully reads 2
byte color = pkt.read(); //successfully reads 5
short len = pkt.readShort(); //problem
My readShort function, which has been working fine until this relatively large value came up.
public short readShort() {
short read = (short)((getBytes()[0] << 8) + getBytes()[1] & 0xff);
return read;
}
25A is 602, but it's printing that len = 90 (5A). So why is it not reading the 0x02?
Sorry I ended up needing an extra set of parenthesis in my function.
Solution was: short read = (short)(((getBytes()[0] & 0xff) << 8) + (getBytes()[1] & 0xff))
You could use a DataInputStream and something like
byte[] bytes = new byte[] { 0x02, 0x05, 0x02, 0x5A };
DataInputStream pkt = new DataInputStream(new ByteArrayInputStream(bytes));
try {
byte tab = pkt.readByte();
byte color = pkt.readByte();
short len = pkt.readShort();
System.out.printf("tab=%d, color=%d, len=%d%n", tab, color, len);
} catch (IOException e) {
e.printStackTrace();
}
Output is (your expected)
tab=2, color=5, len=602
Related
I am new to LZO compression and decompression. I'm trying to use this lzo-java library.
Input Information :
I have one byte array which is in compressed format. This byte array I want to decompress and finally I want decompressed byte array.
NOTE : I don't know the how much size should give to decompress byte array because I don't know exact size of decompressed byte.
I created below code but it is not giving any exception and not even decompressing single byte.
Program :
InputStream stream = new ByteArrayInputStream(src);
int b1 = stream.read();
int b2 = stream.read();
int b3 = stream.read();
int b4 = stream.read();
int dstLength = ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);// decompressed byte array length not known
LzoAlgorithm algorithm = LzoAlgorithm.LZO1X;
LzoDecompressor decompressor = LzoLibrary.getInstance().newDecompressor(algorithm, LzoConstraint.SAFETY);
byte dst[] = new byte[dstLength];
lzo_uintp lzo = new lzo_uintp(dstLength);
int decompress = decompressor.decompress(src, 0, src.length, dst, 0, lzo);
System.out.println("decompessed : " + decompress);//it is giving me 0
What I'm missed in above code? Any suggestions will be helpful for me!
I tried to implement native messaging protocol in java but it didn't work.
I tried it following way.
private String readMessage() {
int length = getInt(getLength());
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
byte[] b = new byte[4];
try {
int total;
for(int totalRead = 0 ; totalRead < length ; totalRead = totalRead + 4){
System.in.read(b); // make sure
bOut.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
String bRes = null;
try {
bRes = new String(bOut.toByteArray(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return bRes;
}
To read size i have used following methods:
This construct the int from first four bytes
private int getInt(byte[] bytes)
{
return (bytes[3] << 24) & 0xff000000 |
(bytes[2] << 16) & 0x00ff0000 |
(bytes[1] << 8) & 0x0000ff00 |
(bytes[0] << 0) & 0x000000ff;
}
This reads first four bytes and returns byte array
private byte[] getLength()
{
int length = 0 ;
byte[] bytes = new byte[4];
try
{
System.in.read(bytes);
} catch (IOException e)
{
e.printStackTrace();
}
return bytes;
}
This gives "Error when communicating with the native messaging host" error. How can i implement this protocol correctly in java.
Can someone provide simple working example for java
My approach below gives a Java implementation that receives a message from a Chrome App and sends a message back. On my little-endian machine it works.
I haven't properly studied your effort but hopefully this will help with your 'simple working example' request.
The main points:
Communication is with the standard stream. As you know, read in the first 4 bytes separately to learn the length (here, in to lengthByte):
byte[] lengthByte = new byte[4];
int bytesRead = System.in.read(lengthByte,0,4);
//Read the message into byte[] c:
byte[] c = new byte[text_length];
int lengthAppMessage = System.in.read(c,0,text_length);
When writing back to the app, we write the message length in the 1st 4 bytes. For the message {"m":"hi"}, which is the message I send below, the message length is 10. (For {"m":"hello"} it's 13, etc.)
int returnedMessageLength = 10;
System.out.write((byte) (returnedMessageLength));
System.out.write((byte)0);
System.out.write((byte)0);
System.out.write((byte)0);
Where the last three lines are padding to sum to 4 bytes. You may need to put these three lines in to the stream before the message length.
When appending the message, the {"...":"..."} format is needed. We can send the message through in sections e.g.
System.out.append('{');
System.out.append('"');
System.out.append('m');
System.out.append('"');
System.out.append(':');
System.out.append('"');
System.out.append('h');
System.out.append('i');
System.out.append('"');
System.out.append('}');
The point is that breaking the message in to sections and sending each section separately circumnavigates the Java formatting problem (caused by the single outer quotes.)
Put all of the above code inside a never-ending 'while' loop to avoid exiting too soon. (To see this code running, I integrated it with the example from Google's native messaging page.)
This is not good code that I've used, but either by accident or design, it worked this way for me.
The below codes works well on my side.
//Convert length from Bytes to int
public static int getInt(byte[] bytes) {
return (bytes[3] << 24) & 0xff000000|
(bytes[2] << 16)& 0x00ff0000|
(bytes[1] << 8) & 0x0000ff00|
(bytes[0] << 0) & 0x000000ff;
}
// Read an input from Chrome Extension
static public String receiveMessage(){
byte[] b = new byte[4];
try{
System.in.read(b);
int size = getInt(b);
byte[] msg = new byte[size];
System.in.read(msg);
// make sure to get message as UTF-8 format
String msgStr = new String(msg, "UTF-8");
return msgStr;
}catch (IOException e){
e.printStackTrace();
return null;
}
}
You could use https://github.com/Cosium/web-native-messaging-host .
It is a java library allowing to turn any JVM application into a Web Native Messaging Host .
I'm working on a project that involves receiving a byte array over wireless, the Android app reads this as a String over a TCP connection:
input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
...
...
//Loop
String read = input.readLine();
//Do something meaningful with String read...
The String will always be of a fixed format i.e. the first 3 characters will be an ID and the next following 20 characters will be the message data. The amount of characters will not change (3+20 characters = 23, with a starting and ending character '[' and ']' so that's 25 characters in total.
An example of a String received by the application would be [01A01020304050A0B0C0D]
ID - 0x01A
Byte0 0x01
Byte1 0x02
Byte2 0x03
Byte3 0x04
Byte4 0x05
Byte5 0x0A
Byte6 0x0B
Byte7 0x0C
Byte 8 0x0D
I would guess that I would have to use the substring operation, but I'm having trouble converting the substring to a byte value (note: the app is expecting byte[] and not Byte[]) and I feel I'm not doing it efficiently. I came across this piece of code that I've been using:
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
This is returning a byte array of size 1 and will have to be run 9 times (9 bytes) per message. I'm a bit concerned that this may be a bit too strenuous on processing, especially when the application is receiving messages very frequently (roughly about 10-15 messages per second)
I appreciate any thoughts and many thanks in advance!
just use this :
byte[] decodedString = Base64.decode(your_string, Base64.DEFAULT);
byte[] b = string.getBytes();
byte[] b = string.getBytes(Charset.forName("UTF-8"));
byte[] b = string.getBytes("UTF-8");
There is no way to be more effecient than using this methods.
Best and simple way:
String myString = "This is my string";
byte[] myByteArray = myString.getBytes("UTF-8");
Now, you able to access id, message whatever; easily from myByteArray.
Just write your data like
byte[] data = yourData.getBytes();
os.write(data, 0, data.length) // data is of 23 bytes
os.flush();
what about reading through InputStream, as you mentioned in your question that String is of 23 characters just do like
public byte[] readData(InputStream is) {
byte[] data = new byte[23];
int read = is.read(data);
System.out.println("Read: " + read);
return data;
}
When you have data then you can split data like this
byte[] tempId = new byte[3];
System.arrayCopy(data, 0, id, 0, id.length);
byte[] tempMessage = new byte[20];
System.arrayCopy(data, 3, message, 0, message.length);
String id = new String(tempId);
String message = new String(tempMessage);
Now you id and message separated and converted into String.
byte[] array = String.getBytes("UTF-8");
Hi I am getting the Data from the GPS device, I want to send the response back to the Gps device by creating the packet MY packet is like this.
No. Field TYPE Length description
1 sMark Char 6 Flag of message (\r\n*KW\0)
2 packetLe short 2 Message Length
3 CMD Short 2 0x8200
4 cErrorCodeChar 1 0x00OK, 0x01invalid deviceID
5 sEnd Char 2 message end "\r\n"
I want Crete Packet like this by using this code.
InetAddress IPAddress = receivePacket.getAddress();
String sendString = "polo";
sendData = sendString.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
I am trying like this.
ByteArrayOutputStream bytearrypacket = new ByteArrayOutputStream();
DataOutputStream dateoutputpacket = new DataOutputStream(bytearrypacket);
dateoutputpacket.writeChars("\r\n*KW\0");
dateoutputpacket.writeShort(15);
dateoutputpacket.writeShort(82);
dateoutputpacket.writeChar('1');
dateoutputpacket.writeChars("\r\n");
dateoutputpacket.flush();
byte[] result = bytearrypacket.toByteArray();
Updated:
ByteArrayOutputStream bytearrypacket = new ByteArrayOutputStream();
DataOutputStream dateoutputpacket = new DataOutputStream(bytearrypacket);
dateoutputpacket.writeBytes("\r\n*KW\0");
dateoutputpacket.writeShort(15);
dateoutputpacket.writeShort(82);
dateoutputpacket.writeByte(1);
dateoutputpacket.writeBytes("\r\n");
dateoutputpacket.flush();
byte[] result = bytearrypacket.toByteArray();
Updated 2:
try {
ByteArrayOutputStream bytearrypacket = new ByteArrayOutputStream();
DataOutputStream dateoutputpacket = new DataOutputStream(bytearrypacket);
dateoutputpacket.writeBytes("\r\n*KW\0");
dateoutputpacket.writeShort(15);
dateoutputpacket.writeShort(82);
dateoutputpacket.writeByte(1);
dateoutputpacket.writeBytes("\r\n");
dateoutputpacket.flush();
byte[] result = bytearrypacket.toByteArray();
DatagramPacket responsepacket = new DatagramPacket(result, result.length, packet.getAddress(), packet.getPort());
dsocket.send(responsepacket);
} catch (IOException ex) {
ex.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
} catch (IllegalBlockingModeException il) {
il.printStackTrace();
} catch (IllegalArgumentException ilg) {
ilg.printStackTrace();
}
Create a DataOutputStream around a ByteArrayOutputStream; use its various methods to write the data; then get the bytes from the ByteArrayOutputStream and wrap a DatagramPacket around that.
Ive quickly put this together. Using this function you can create a byte array which has all packet information in the correct place. I used some of the sample info from the question. That should be enough to send the info across the connection. you can pass the byte array directly into your datagram
public class Sample {
public static void main(String[] args){
byte[] packet = createMsg("\r\n*KW\0", (short)15, (short)82, '1', "\r\n");
for(byte b : packet){
System.out.println(b);
}
}
public static byte[] createMsg(String sMark, short packetle, short cmd, char cErrorCode, String sEnd){
byte[] buffer = new byte[13];
char[] sMarkArr = sMark.toCharArray();
char[] sEndArr = sEnd.toCharArray();
// sMark
buffer[0] = (byte) sMarkArr[0];
buffer[1] = (byte) sMarkArr[1];
buffer[2] = (byte) sMarkArr[2];
buffer[3] = (byte) sMarkArr[3];
buffer[4] = (byte) sMarkArr[4];
buffer[5] = (byte) sMarkArr[5];
// packetle
buffer[6] = (byte)(packetle & 0xFF);
buffer[7] = (byte)((packetle >> 8) & 0xFF);
// cmd
buffer[8] = (byte)(cmd & 0xFF);
buffer[9] = (byte)((cmd >> 8) & 0xFF);
// cErrorCode
buffer[10] = (byte)(cErrorCode);
// sEnd
buffer[11] = (byte)sEndArr[0];
buffer[12] = (byte)sEndArr[1];
return buffer;
}
}
Remember when doing comms in java, the datatypes sizes and format aren't always the same as some other languages.
Check out http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html to get each of the sizes
Hope this helps
EDIT:
Packet is 13 * 8 = 104 bits = 000000000000000000000000000000000000...
calling buffer[0] = (byte)sMark adds the char (e.g. A)
Packet is 13 * 8 = 104 bits = 001000001000000000000000000000000000...
calling buffer[6] = (byte)packetle adds the char (e.g. 2)
Packet is 13 * 8 = 104 bits =
[ Char 6 bytes ][Short 1 byte]
[010000010000000000000000000000000000000000000000][00000010]...
NOTE: as you are using bytes for chars you will need to add an extra byte, as java chars are 16-bit, otherwise you may get loss of data
I am designing an archive format(Just for fun) in Java using this template-
First 4 bytes: Number of files in the archive
Next 4 bytes: Number of bytes in the filename
Next N bytes: Filename
Next 10 bytes: Number of bytes in the file
Next N bytes: File contents
from PHP Safe way to download mutliple files and save them.
I am having on trouble with finding the values of the number of files etc. but I don't know how to expand an integer into 4 bytes.
Is it similar to this- How do I truncate a java string to fit in a given number of bytes, once UTF-8 encoded?
Use a DataOutput/DataInput implementation to write/read that format, it does most of the work for you. The classical implementations are DataOutputStream and DataInputStream:
DataOutputStream dos = new DataOutputStream(outputStream);
dos.writeInt(numFiles);
// for each file name
byte[] fn = fileName.getBytes("UTF-8"); // or whichever encoding you chose
dos.writeInt(fn.length);
dos.write(fn);
// ...
Reading works pretty much the same.
Note that these use big endian. You'll have to check (or specify) if your format uses big- or little-endian.
You can convert an int into 4 bytes like this:
public byte[] getBytesForInt(int value) {
byte[] bytes = new byte[4];
bytes[0] = (byte) ((value >> 24) & 0xFF);
bytes[1] = (byte) ((value >> 16) & 0xFF);
bytes[2] = (byte) ((value >> 8) & 0xFF);
bytes[3] = (byte) (value & 0xFF);
return bytes;
}
This would put them in big-endian order as often used for transport (see Endianness). Alternatively if you're already dealing with an OutputStream you could wrap it with a DataOutputStream and just use writeInt(). For example as per your template:
FileOutputStream fileOut = new FileOutputStream("foo.dat");
DataOutputStream dataOut = new DataOutputStream(fileOut);
dataOut.writeInt(numFiles);
dataOut.writeInt(numBytesInName);
dataOut.writeUTF(filename);
dataOut.writeLong(numBytesInFile);
dataOut.write(fileBytes);
Note that the writeLong() is actually 8 bytes. I'm not sure why you'd want to use 10 and I imagine 8 from a long is plenty.