I'm trying to decode a []byte from an Arduino BT, I got the connection perfectly, the problem is when I try to decode the array. all that I get is this character � (the same number of bytes sent) I think that the problem is on the decoding. I try with ASCII charset but still the same problem. I'm using Android Studio and set to UTF-8 format.
Could someone tell me what is happening please?
OutputStream:
public void write(byte[] bytes) {
String text = new String(bytes, StandardCharsets.US_ASCII);
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
Log.d(TAG, "write: Writing to outputstream: " + bytes);
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
}
}
InputStream:
public void run (){
byte [] buffer = new byte[1024];
int bytes;
while(true){
try {
bytes = mmInStream.read(buffer);
String incomingMessage = new String (buffer,0,bytes, StandardCharsets.US_ASCII);
Log.d(TAG,"InputStream: " + incomingMessage);
Intent incomingMessageIntent = new Intent("incomingMessage");
incomingMessageIntent.putExtra("El mensaje", incomingMessage);
Log.d(TAG,"Mensaje enviado a la main actv " + incomingMessage);
LocalBroadcastManager.getInstance(mContext).sendBroadcast (incomingMessageIntent);
} catch (IOException e) {
Log.e(TAG,"Error leyendo Imputstream" +e.getMessage());
break;
}
}
}
Logcat to see the character that I receive:
From the Arduino side you should use char as sending format.
Serial.write Writes binary data to the serial port. This data is sent as a byte or series of bytes
So simply try to decode
Serial.print("1234ABCD\r\n");
Not knowing the commands on Android I guess bytes in Arduino speak is char and not binary data. And always post all code used!
Related
I am required to write a consumer in Java from Kafka streams, publisher app is written by a third party in python. When I use base64 decoding and then zlip uncompress in java, I get an incorrect header check exception.
My Task is: Convert this compressed base64 + zlib data into a text file that is readable.
Publisher's code in python:
# read in the file content
inputf=open(file, 'rb')
input=inputf.read()
inputf.close()
# using zlib.compress(s) method
compressed = zlib.compress(input)
# encoding with base64 encoding
encoding_type='base64'
enc_data=encode(compressed,encoding_type)
enc_data_utf8=enc_data.decode("utf-8")
# enc_data=enc_data_no_no_newline ####[0:86000] # trim
event_etl_event[filename+"_content"]=enc_data_utf8
event_etl_event[filename+"_compressed_format"]="zlib+uuencode"
enter code here
Consumer Code in java
public void processData(){
inputStr = event.getEventEtlEvent().getAllProblemsTxtContent();
System.out.println("Before Base64 decoding: \n" + inputStr);
Path path0 = Paths.get("AllProblems_Before_base64_decoding.txt");
Files.write(path0, inputStr.getBytes());
Base64 base64 = new Base64();
String decodedString = new String(base64.decode(inputStr.getBytes()));
System.out.println("After Base64 decode: \n" + decodedString);
Path path1 = Paths.get("AllProblems_After_base64_decoding.txt");
Files.write(path1, decodedString.getBytes());
System.out.println("now zlib 64 decodingString .........\n\n\n");
byte[] output = ZLibUtils.decompress(decodedString.getBytes());
System.out.println("After Zlib Decompress: "+ output);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} /*catch (InvalidDataException e) {
e.printStackTrace();
} catch (DataFormatException e) {
e.printStackTrace();
}*/catch (Exception e) {
e.printStackTrace();
}
ZLibUtils.java
public static byte[] decompress(byte[] data) throws DataFormatException {
byte[] output = new byte[0];
Inflater decompresser = new Inflater();
decompresser.reset();
decompresser.setInput(data);
ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
// try {
byte[] buf = new byte[data.length];
byte[] a = new byte[data.length];
while (!decompresser.finished()) {
int i = decompresser.inflate(buf);
o.write(buf, 0, i);
}
output = o.toByteArray();
/* } catch (Exception e) {
output = data;
e.printStackTrace();
//FIXME: in later code
System.exit(0);
} finally {
try {
o.close();
} catch (IOException e) {
e.printStackTrace();
}
} */
decompresser.end();
return output;
}
Now when I run my program, i get the following exception:
java.util.zip.DataFormatException: incorrect header check
at java.util.zip.Inflater.inflateBytes(Native Method)
at java.util.zip.Inflater.inflate(Inflater.java:259)
at java.util.zip.Inflater.inflate(Inflater.java:280)
at com.exmple.util.ZLibUtils.decompress(ZLibUtils.java:84
)
Looking forward to hearing from you soon.
The problem is that you convert the base64 decoded data from a byte array into a string and back into a byte array. For most encodings this is not a no-op. That means, for most encodings and most byte arrays,
byte[] decoded = { (byte) 0x9b, 1, 2, 3 };
String decodedString = new String(decoded);
byte[] processed = decodedString.getBytes();
the contents of processed will be different from the contents of decoded.
The solution is to not treat the base64 decoded data as string and instead of that work with the byte data directly:
Base64 base64 = new Base64();
byte[] decoded = base64.decode(inputStr.getBytes());
Path path1 = Paths.get("AllProblems_After_base64_decoding.txt");
Files.write(path1, decoded);
System.out.println("now zlib 64 decodingString .........\n\n\n");
byte[] output = ZLibUtils.decompress(decoded);
I am trying to read bytes received via a bluetooth connection and convert it to String
Monitor input stream
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
MainActivity when I receive, the log statement does not seem to get called if there is multiple lines. If it is just a single line, it's fine
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, "Incoming message: " + readMessage); // does not get called when there's a linebreak.
When I try to check if the string contains certain info as such, it doesn't get called even though the String I received does contain it.
For example, given if I receivedreadMessage = "Obstacle String\nStart of 2nd line"
The following statement doesn't get called
if (readMessage.contains("Obstacle String"))
But when I try to set the readMessage to some TextView, it is able to display the string correctly.
For some reason Android logcat does not seems to handle \r
So, I trimmed the string as such
readMessage = readMessage.replaceAll("\r", "");
i have just started playing around with java nio packages an am at a bit of a loss
i have a client
Socket s=new Socket(ip,port);
OutputStream out=new OutputStream();
PrintStream ps=new PrintStream(s.getOutputStream());
String t=""hiya";
ps.print(t);
ps.flush();
InputSTreamReader in=new InputSTreamReader(s.getInputSTream);
BufferReader b=nwe BufferedReader(in);
System.out.println(b.readLine());//prints echo response from server
and on the server side
this.selkey = selkey;
this.chan = (SocketChannel) chan.configureBlocking(false); // asynchronous/non-blocking
buf = ByteBuffer.allocateDirect(64); // 64 byte capacity
void read() {
try {
int amount_read = -1;
try {
amount_read = chan.read((ByteBuffer) buf.clear());
} catch (Throwable t) {
}
if (amount_read == -1)
disconnect();//deelts client on exit
if (amount_read < 1)
return; // if zero
System.out.println("sending back " + buf.position() + " bytes");
// turn this bus right around and send it back!
buf.flip();
chan.write(buf);//sending data 2 client
} catch (Throwable t) {
disconnect();
t.printStackTrace();
}
}
what this does i send string t to the server into bytebuffer and echos it back which all works fine but hoiw would i print the string on the server side for example in read method
buf.flip()
System.out.write(buff);//which just prints what looks to be chinese
k this is typical have been working on this problem for like an hour but when i post the question the answer acours to me
CAST IT TO A CHAR!
this works
buf.flip();
while (buf.hasRemaining()) {
System.out.print((char) buf.get();
}
System.out.println();
Since you are sending data as bytes, it wont work as Strings.
Even if you did, it would be referencing the byte array.
Try this:
String str = new String (buff);
I have this block of code to read an array sent from the server to the client of recent updates, the issue is that sometimes it works and sometimes it doesn't. It will print out the version properly, but everything else will either not print out, all print out on the same line, or have 2 on the same line.
The purpose of this is to receive a String[] of recent updates from the server, which is looped through and sent as an individual String. Those updates are then displayed on a GUI.
private Response update() {
try {
Socket socket = new Socket(RS2Client.IP, 55555);
byte[] bytes = new byte[1024];
socket.getInputStream().read(bytes);
String version = new String(bytes);
System.err.println("VERSION READ " + version);
for (int i = 0; i < 6; i++) {
byte[] b = new byte[1024];
socket.getInputStream().read(b);
String text = new String(b);
getRecentUpdates().add(text.trim());
System.out.println("New update: " + text);
}
for (String update : getRecentUpdates()) {
System.err.println(update);
}
System.out.println("Client connected! Version: " + version);
socket.close();
if (Double.parseDouble(version) != RS2Client.CLIENT_VERSION) {
return Response.BAD;
}
} catch (Exception e) {
e.printStackTrace();
return Response.ERROR;
}
return Response.GOOD;
}
A socket sends a stream of bytes. It does not keep track of the end of each byte array you send.
If you want to send a byte array, you should send the length first, so you know how many bytes to expect.
I'm trying to send images from my computer to my phone by using a Java program connect to an Android app.
The code I use to send the image:
byte[] data = imageToByteArray(img);
sendMessage(Main.imageCheck + data.length);
out.write(data);
out.flush();
This code is run from the Java program on my computer. The sendMessage() method is:
public void sendMessage(String s) {
if (out != null && server.isConnected()) {
try {
out.writeUTF(s);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The code I use to receive the image and other data:
while ((input = in.readUTF()) != null) {
if (!input.equalsIgnoreCase(pulseCheckMessage)) {
if (input.contains(imageCheck)) {
//byte[] data = Base64.decode(input.replace(imageCheck, ""), Base64.DEFAULT);
byte[] data = new byte[Integer.parseInt(input.replace(imageCheck, ""))];
int length = in.read(data);
updateScreenImage = BitmapFactory.decodeByteArray(data, 0, length);
MainActivity.this.runOnUiThread(updateUiRunnable);
} else {
inLine = "Received: " + input;
MainActivity.this.runOnUiThread(updateUiRunnable);
}
}
pulseTakenTime = System.currentTimeMillis();
pulseCheckReceived = true;
isAlive = true;
}
The commented out code (including the base64 class) was when I was sending the image data as a string by using Base64.encode to convert the byte[] array to a string to send over, which worked without a problem except that it was too slow. So I decided to send the bytes over which I thought would be faster.
imageCheck and Main.imageCheck are strings that are the same. The app receives that string and recognizes it and expects a byte[] array so it tries to do in.read(data) however I get an error:
ERROR: java.nio.charset.ModifiedUtf8.decode(ModifiedUtf8.java:57)
ERROR: java.io.DataInputStream.decodeUTF(DataInputStream.java:444)
ERROR: java.io.DataInputStream.decodeUTF(DataInputStream.java:438)
ERROR: java.io.DataInputStream.readUTF(DataInputStream.java:433)
ERROR: com.mangopearapples.pccontroller.MainActivity.run(MainActivity.java:238)
Thanks.
My guess is that int length = in.read(data); doesn't read all the bytes that have been sent, as documented:
Reads some number of bytes from the contained input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer
(emphasis mine)
So, the next iteration tries to read the unread bytes of the image as UTF, and it fails. Always use a loop to read bytes from a stream, which stops once all the expected number of bytes have been read.
To confirm that this is the real problem, debug and see if the length returned matches with the actual length.