hello i am new with byte manipulation in java. i already have byte array with flowing format
1-> datapacketlength (length of name) (first byte)
2-> name (second byte + datapacket length)
3-> datapacketlength (length of datetime)
4-> current date and time
how can i extract the name and current date and time.should i use Arrays.copyOfRange() method.
Regards from
mcd
You can use ByteBuffer and use your current byte array, then use the methods that come with it to get the next float, int etc (such as buffer.getInt and buffer.getFloat).
You can get a portion of your byte array when you create a new bytebuffer by using the wrap method I believe. The possibilities are endless :). To get strings as you asked, you simply need to do something like:
byte[] name = new byte[nameLength];
buffer.get(name);
nameString = byteRangeToString(name);
where byteRangeToString is a method to return a new string representation of the byte[] data you pass it.
public String byteRangeToString(byte[] data)
{
try
{
return new String(data, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
/* handle accordingly */
}
}
See: http://developer.android.com/reference/java/nio/ByteBuffer.html
Using copyOfRange() may run you into memory issues if used excessively.
What about something like :
int nameLength = 0;
int dateLength = 0;
byte[] nameByteArray;
byte[] dateByteArray
for(int i=0; i<bytesArray.length; i++){
if(i == 0){
nameLength = bytesArray[i] & 0xFF;
nameByteArray = new byte[nameLength];
}
else if(i == nameLength+1){
dateLength = byteArray[i] & 0xFF;
dateByteArray = new byte[dateLength];
}
else if(i < nameLength+1){
nameByteArray[i-1] = bytesArray[i];
}
else{
dateByteArray[i-(nameLength+1)] = bytesArray[i];
}
}
You want to use a DataInputStream.
Related
I aim to use code via https://github.com/davidgyoung/ble-advert-counter/blob/master/app/src/main/java/com/radiusnetworks/blepacketcounter/MainActivity.java
to scan and read BLE device's adverting data.
The code works well. I could get the formatted adverting data via LogCat as pic shown.
But in the code I can't find the related log statement.
I didnt see BluetoothLeScanner class or onScanResult() method invoked.
And I want to obtain the String "ScanResult{mDevice=F3:E5:7F:73:4F:81, mScanRecord=ScanRecord..." to get the formatted data value.
How can I achieve this?
Thanks
I'm not sure about the logs but here's how you can get the data.
onLeScan() callback has all the information that is being printed in the logs. To get the device information you can use the device object from the call back(ex. device.getAddress()). Scan record will be in the callback's scanRecord byte array. You need to parse the array to get the information. I've used below code to parse the scan information.
public WeakHashMap<Integer, String> ParseRecord(byte[] scanRecord) {
WeakHashMap<Integer, String> ret = new WeakHashMap<>();
int index = 0;
while (index < scanRecord.length) {
int length = scanRecord[index++];
//Zero value indicates that we are done with the record now
if (length == 0) break;
int type = scanRecord[index];
//if the type is zero, then we are pass the significant section of the data,
// and we are thud done
if (type == 0) break;
byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length);
if (data != null && data.length > 0) {
StringBuilder hex = new StringBuilder(data.length * 2);
// the data appears to be there backwards
for (int bb = data.length - 1; bb >= 0; bb--) {
hex.append(String.format("%02X", data[bb]));
}
ret.put(type, hex.toString());
}
index += length;
}
return ret;
}
Refer the below link to understand about the ble date advertisement.
BLE obtain uuid encoded in advertising packet
Hope this helps.
I developed my own rest api using c# servicestack on mono. It works as expected except when it comes to file download. I noticed it appends some bits at the start of file. for example see the image below:
I filed bug to mono bugzilla, Meanwhile, I want to override image response on my client to remove first appended stuff to make image work. I tried it on c# client by editing received stream before saving it to file and it works fine.
I need to know how and where I can override volley library to get clean images not malformed ones with the best performance.
Update 04:37 PM:
I believe I need to modify com.android.volley.toolbox.ImageRequest >> I will try it and post solution if it works with me.
Regards,
Shaheen
I modified the method doParse in com.android.volley.toolbox.ImageRequest
private Response<Bitmap> doParse(NetworkResponse response){
byte[] data = response.data;
byte [] pattern = fromHexString("FFD8FFE000");
int position = matchPosition(data,pattern);
if(position>0)
data = Arrays.copyOfRange(data, position, data.length-position);
....
....
....
....
..}
here is the helper methods I used:
public static int matchPosition(byte [] a, byte [] b){
int matchLength=0;
int maxSearch = 30>a.length?a.length:30;
for (int i =0;i<maxSearch;i++) {
if (a[i]==b[0] && i+b.length<a.length){
for(int j = 0;j< b.length;j++ )
{
if((i+j)==a.length-1)
return -1;
if(a[i+j]==b[j])
matchLength++;
}
if(matchLength == b.length)
return i;
else
matchLength = 0;
}
}
return -1;
}
private static byte[] fromHexString(final String encoded) {
if ((encoded.length() % 2) != 0)
throw new IllegalArgumentException("Input string must contain an even number of characters");
final byte result[] = new byte[encoded.length()/2];
final char enc[] = encoded.toCharArray();
for (int i = 0; i < enc.length; i += 2) {
StringBuilder curr = new StringBuilder(2);
curr.append(enc[i]).append(enc[i + 1]);
result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
and this work around resolved the issue explained above!
Hi I am trying to send messages to a Java server that I cannot change from an iOS device. I am using AsyncSocket and was wondering how to send and receive the length appended to the string. I am doing a UTF conversion of the string to NSData however I was wondering if there is a difference in the size of the primitive between the two languages. Also is there a big endian and little endian variation? Basically I need to be able to convert the following java methods:
inStream.readUTF();
inStream.readInt();
inStream.readChar();
inStream.readShort();
inStream.readFully(recvBuff, 0, recvLen);
outStream.writeInt();
outStream.writeUTF();
outStream.writeChars();
outStream.writeShort();
outStream.write(sendBytes, 0, sendBytes.length);
I know I am very close but something is not quite right, this is what I have got so far:
I am using an NSMutableArray to append the data and the using AsyncSockets read and write methods.
[theSocket readDataToData:[AsyncSocket ZeroData] withTimeout:timeout buffer:buffer bufferOffset:offset tag:tag]; // inStream.readUTF();
[theSocket readDataToLength:sizeof(int32_t) withTimeout:timeout buffer:buffer bufferOffset:offset tag:tag]; // inStream.readInt();
[theSocket readDataToLength:sizeof(unichar) withTimeout:timeout buffer:buffer bufferOffset:offset tag:tag]; // inStream.readChar();
[theSocket readDataToLength:sizeof(int16_t) withTimeout:timeout tag:tag]; // inStream.readShort();
[theSocket readDataWithTimeout:timeout buffer:buffer bufferOffset:offset maxLength:maxLength tag:tag]; // inStream.readFully(recvBuff, 0, recvLen);
[outputBufferStream appendBytes:&[sendString length] length:sizeof([sendString length])]; // outStream.writeInt();
[outputBufferStream appendData:[sendString dataUsingEncoding:NSUTF8StringEncoding]] // outStream.writeUTF();
char array[5];
[outputBufferStream appendBytes:array length:sizeof(array)]; // outStream.writeChars();
int16_t _short;
[outputBufferStream appendBytes:&_short length:sizeof(_short)]; // outStream.writeShort();
unsigned char *sendBytes;
[outputBufferStream appendBytes:sendBytes length:sendBytesLength]; // outStream.write(sendBytes, 0, sendBytes.length);
I usually append the length at the beginning like so:
int32_t sendStringLength = [sendString length];
[outputBufferStream appendBytes:&sendStringLength length:sizeof(sendStringLength)];
At the end of the write i am appending the following as a terminator:
[outputBufferStream appendData:[#"\n" dataUsingEncoding:NSUTF8StringEncoding]];
I would really appreciate any help with this. Thanks.
EDIT::
I have got most of it working thanks to Robadob. Here is a little java snippet (working) of the bit i am currently stuck trying to get working on Objective-C:
private int sendData(String stringToSend) {
if (theSocket==null) {
lastError="sendData() called before socket was set up.";
return 1; // Error
}
try {
System.out.println("Sending "+stringToSend.length()+" chars ["+ stringToSend.length()*2+" bytes]");
System.out.println("'" + stringToSend + "'");
outStream.writeInt(stringToSend.length()*2);
outStream.writeChars(stringToSend);
outStream.flush();
} catch (IOException e) {
lastError="sendData() exception: "+e;
System.out.println(lastError);
return 2; // Error
}
return 0; // Ok
}
Here is a snippet of what I have got so far in Objective-C:
- (int32_t)sendData:(NSString *)stringToSend {
if (theSocket == nil) {
lastError = #"sendData called before socket was set up";
return 1; // Error
}
#try {
NSLog(#"Sending %d chars [%d bytes]", [stringToSend length], ([stringToSend length] * 2));
NSLog(#"'%#'", stringToSend);
uint32_t stringToSendInt = ([stringToSend length] * 2);
uint32_t stringToSendIntBigE = CFSwapInt32HostToBig(stringToSendInt);
[outputBufferStream appendBytes:&stringToSendIntBigE length:sizeof(stringToSendIntBigE)];
stringToSend = [stringToSend stringByAppendingString:#"\n"];
for (int i = 0; i < ([stringToSend length]); i++) {
unichar characterTmp = [stringToSend characterAtIndex:i];
unichar character = characterTmp << 8;
[outputBufferStream appendBytes:&character length:sizeof(character)];
}
[self syncWriteData:outputBufferStream withTimeout:socketTimeout tag:kSendDataSocketTag];
outputBufferStream = [NSMutableData data];
}
#catch (NSException *e) {
lastError = [NSString stringWithFormat:#"sendData exception: %#", [e reason]];
NSLog(#"%#", lastError);
return 2; // Error
}
return 0; // Ok
}
If you read the docs for writeUTF it says it writes the first 2 bytes using writeShort. This says
Writes a short to the underlying output stream as two bytes, high byte
first. If no exception is thrown, the counter written is incremented
by 2.
A byte is 8 bits, so that makes the value they are writing is 16 bits, you are using int32_t, which is 32 bits. you should be writing an int16 or int16_t (I don't objective-c).
In my current project I have to read a JavaScript file from the web and extract an object from it. The variable can vary from time to time, so I have to read it instead of hard coding it into my android app.
Say I want to extract the following variable (and parse the string using JSONObject after that, which is trivial):
var abc.xyz = {
"a": {"one", "two", "three"},
"b": {"four", "five"}
}
I have a problem with this. Do I have to implement some compiler-like scanner just to look for the name and get its value, or there is some existing tool I can use?
The JavaScript file is not as simple as this example. It contains a lot of other code. So a simple new JSONObject() or something will not do.
There are many libraries in Java to parse the JSON. There is a list on JSON.org
Read the file with Java
import org.json.JSONObject;
URL url = new URL("http://example.com/foo.js");
InputStream urlInputStream = url.openStream();
JSONObject json = new JSONObject(urlInputStream.toString());
Finally code it myself.
//remove comments
private String removeComment(String html){
String commentA = "/*";
String commentB = "*/";
int indexA, indexB;
indexA = html.indexOf(commentA);
indexB = html.indexOf(commentB);
while(indexA != -1 && indexB != -1 ){
html = html.substring(0, indexA) + html.substring(indexB + commentB.length());
indexA = html.indexOf(commentA);
indexB = html.indexOf(commentB);
}
return html;
}
//find variable with name varName
private String findVar(String varName, String html, char lBrace, char rBrace){
String tmp = html.substring(html.indexOf(varName));
tmp = tmp.substring(tmp.indexOf(lBrace));
int braceCount = 0;
int index = 0;
while(true){
if(tmp.charAt(index) == lBrace){
braceCount ++;
}else if(tmp.charAt(index) == rBrace){
braceCount --;
}
index ++;
if(braceCount == 0){
break;
}
}
return tmp.substring(0, index);
}
I'm translating one app from java to php and i'm finding some trouble.
I have a string like this 98191107990D0000EF050000789C65970BCCD75318C7CFEFFC ... in java there's this function where I pass this string as parameter:
private static byte[] decodeNibbleHex(String input)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length - 1; i += 2) {
char[] bChars = new char[2];
bChars[0] = chars[i];
bChars[1] = chars[(i + 1)];
int val = Integer.decode("0x" + new String(bChars)).intValue();
baos.write((byte)val);
}
return baos.toByteArray();
}
but... i don't know to to translate this function in PHP... i tried too many times and i'm becoming crazy! i tried with a for cycle, with this eval("\$hex = 0x" . $dati[$i].$dati[$i+1] . ";"); and this $binary_string = pack("h*" , $dati[$i].$dati[$i+1]); and many many other functions...
If someone understand Java and can help me I will appreciate it!!
Thank guys!
Take a look here:
http://www.php.net/manual/de/function.hexdec.php#100578
Is this not exactly what you whrere looking for?
If my understanding is correct of your java function, it takes the string's chars in pairs, and threats them as bytes and put them in a ByteArray. In php there's no such thing as a byte array but you can represent random binary data in everyday strings. This is my take on your function (didn't tried to compare with the java code's output).
$str= '98191107990D0000EF050000789C65970BCCD75318C7CFEFFC';
$output[] = array();
for ($i=0, $c = strlen($str) - 1; $i < $c; $i+=2) {
$output[] = chr(intval($str[$i].$str[$i+1], 16));
}
print join($output); // binary string, not really useful in ascii terminal (-:
In summary this seem to be a base16_decode() function, with base16_encode() written like it follows, you get back the input string:
function base16_encode($str) {
$byteArray = str_split($str);
foreach ($byteArray as &$byte) {
$byte = sprintf('%02x', ord($byte));
}
return join($byteArray);
}
print base16_encode(join($output)); // should print back the original input.