I have a string of hex values that I am trying to write to a socket as bytes.
String confDeliv = "\\x7E\\x01\\x00\\x20\\x37\\x02\\x03\\xF2\\xD5";
I have tried doing this to try and solve my problem
byte [] Delivery_Conf = {(byte)0x7E, (byte)0x01, (byte)0x00, (byte)0x20,
(byte)0x37, (byte)0x02, (byte)0x03, (byte)0xF2, (byte)0xD5};
But I have yet to succeed to write it to the socket. I don't get any errors but when I send it to the device it doesn't do what I need it to do I have tried two different ways of doing this.
Try 1:
DataOutputStream dOut = new DataOutputStream(sock.getOutputStream()); //69.171.154.64
for (int i = 0; i < Delivery_Conf.length-1; i++) {
dOut.writeByte(Delivery_Conf[i]);
}
dOut.flush();
This method I used when I but the values into a byte array.
Try 2:
DataOutputStream dOut = new DataOutputStream(sock.getOutputStream());
dOut.writeBytes(confDeliv);
dOut.flush();
This is the method I used when I tried sending it as the string but still no luck. I am able to make the device work when I use python using its byte string.
eg.
confDel = b"\x7E\x01\x00\x20\x37\x02\x03\xF2\xD5"
I think java changes something when I send it and I think that is why I can get it to work with java. I have looked around for while but I do not seem to find anything that will help me with my problem.
You should use the following:
byte [] Delivery_Conf = {(byte)0x7E, (byte)0x01, (byte)0x00, (byte)0x20,
(byte)0x37, (byte)0x02, (byte)0x03, (byte)0xF2, (byte)0xD5};
// ...
dos.write(Delivery_conf);
The version you had writing a byte at a time should work but it's inefficient, and it's possible that the device has timing constraints.
The version using the String isn't correct. Adding another backslash to make \x compile is not a correct solution: you should change \x to \u00 throughout. Throughout the string, that is, of course.
Related
I am trying to read data from UDP port on localhost using Java. I'm pretty good with Java, but I can't solve this for quite a while now...
The thing is, after I connect using DatagramSocket and receive a packet with DatagramPacket, I get some bytes that have no sence, I can't see connection with the data I expect. Printout looks like this:
$őZAŇ"¤E€^ĽxΕ’M#ŢúCîS5;Ń8†8Ŕ$5»ôxŕ¸Ţf+?’Ť;Ů%>ż?>żA€ĹĽ‘_
so, I'm obviously handlig something in the wrong way. I've also read some signed/unsigned data problems with Java.
About a year ago I've created a similar app using C#, everything went pretty smooth.
Really hope someone can help.
Here is the code (one of the versions, I've tried a lot of different solutions)
DatagramSocket mySocket = new DatagramSocket(null);
InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 20777);
mySocket.bind(addr);
byte[] receiveData = new byte[152];
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, 0, receiveData.length);
mySocket.receive(receivePacket);
byte[] barray = receivePacket.getData();
ByteArrayInputStream inputStream = new ByteArrayInputStream(barray);
DataInputStream dInputStream = new DataInputStream(inputStream);
float a = dInputStream.readFloat();
System.out.println(a);
}
Using this method you can convert a byte array to hexadecimal string representation.
private String bytesToHex(byte[] bytes) {
char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
Hope it helps.
I won't flag your question as a duplicate because it is your first one, but I think you should refer to this other exchange. A very elegant and clear solution to your problem is available.
By the way, a citation of the code reading the section you printed would have been welcome. Good luck...
You need:
A specification of the packet format you are receiving.
A DataInputStreamwrapped around a ByteArrayInputStream wrapped around the byte array you used to build the DatagramPacket, not forgetting to use the constructor that takes an offset and length, which you get from the DatagramPacket.
Code that calls the appropriate DataInputStream methods corresponding to (1).
At the moment you don't even appear to have (1). Without that, you haven't got a hope. Just trying to 'make sense' of binary data, especially by just printing it, is a complete waste of your time.
EDIT If, as per your comment, all the fields are floats, just loop over the datagram calling DataInputStream.readFloat() until it throws EOFException:
try
{
while (true)
{
float f = dataInputStream.readFloat();
System.out.println(f);
}
}
catch (EOFException exc)
{
// expected
}
If that doesn't work (i.e produce recognizable value), you will have to switch to DatagramSocketChannel and ByteBuffer and experiment with the different byte-order possibilites.
Why you were trying to print floating-point data as though it was text remains a mystery.
I'm trying to get a very simple Client-Server system to work, where the Client will send a String over to the Server, and the server will then store that String into a file.
The client sends the string through:
//Other Code
sockStrm = new DataOutputStream (clientSocket.getOutputStream ());
//Other code
sockStrm.writeChars (line);
//Other code
And the Server receives the String with:
//Other code
strm = new BufferedReader (new InputStreamReader (clientSocket.getInputStream ()));
//Other code
stringLine = strm.readLine ();
//Other code
When I send the string STOP, the length of the String is 4 on the client side, and on the server side the length of the String is 9 and displays as STOP
I've tried to substring the received String on the Server side, without luck.
Any pointers on how to deal with this?
Use symmetric methods:
DataOutputStream sockStrm =...
sockStrm.writeUTF(str);
and
DataInputStream sockStrm = ...
String str = sockStrm.readUTF();
writeChars writes individual characters as two byte values. Readers follow the encoding to reconstruct the string from a sequence of bytes, which will definitely not be according to high-byte-low-byte for each character code. Hence you get some mish-mash of zero bytes with the original low-byte values so you still have a glimpse of the original string value.
Using \x00 to denote a NULL byte:
S-T-O-P => on the line: \x00-S-\x00-T-\x00-O-\x00-P => prints as STOP
Use a loop over the characters of the incoming string and display their integer values (str.charAt(i)) to see the above for yourself.
i want to write a string to a serial port, but serial port write method allows only byte array to write in it...so how can i send whole string to a port..here is my code...
serialPort.setSerialPortParams(300,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
OutputStream mOutputToPort = serialPort.getOutputStream();
String mValue = "ABCDEFG";
System.out.println("beginning to Write . \r\n");
mOutputToPort.write(mValue.getBytes());
System.out.println("AT Command Written to Port. \r\n");
mOutputToPort.flush();
i dont want to send it one by one char..i want whole at a time... thnxx in advance
Your code works (it does write the whole string at once), but it is not nice. If this is what you intend to do, the "clean" way to do it is:
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(mOutputToPort));
bw.write(mValue);
// probably "write" some more here to the buffer
bw.flush(); // now ensure accumulated data is actually written
If you are only writing one string and not more you might as well use an OutputStreamWriter directly and not use a buffer:
OutputStreamWriter osw = new OutputStreamWriter(mOutputToPort);
osw.write(mValue, 0, mValue.length());
osw.flush();
(In Java, Writers deal with writing characters to streams instead of bytes.)
If you want to ensure that no buffering occurs (and I doubt there is any reason for it, it will only increase system call overhead since the serial port will buffer the data anyway and send it out slower than your code delivers it), 123456789 provided a suitable answer. You should be careful with calling getBytes() though, as this will use the system's default character encoding (usually UTF-8 or ISO-8859-1, both suitable for writing pure ASCII) to convert from characters to bytes. If you want a particular encoding then specify it in the call to getBytes(), e.g.
try {
byte[] bytes = someString.getBytes("US-ASCII");
for (int i=0; i<bytes.length; i++)
mOutputToPort.write(bytes[i]); }
catch (UnsupportedEncodingException e) {} // well, this one is always supported
Try to use getBytes() method which returns byte array.
OutputStream mOutputToPort = serialPort.getOutputStream();
String mValue = "ABCDEFG";
System.out.println("beginning to Write . \r\n");
Byte[] data = mValue.getBytes();
for(int i=0;i<data.length;i++){
mOutputToPort.write(data[i]);}
System.out.println("AT Command Written to Port. \r\n");
mOutputToPort.flush();
I've got some trouble with sending a UTF8 string from a c socket to a java socket.
The following method works fine:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
main.title = in.readLine();
but then I need a int java.io.InputStream.read(byte[] b, int offset, int length) method which does not exist for a BufferedReader. So then I tried to take a DataInputStream
DataInputStream in2 = new DataInputStream(socket.getInputStream());
but everything it reads is just rubbish.
Then I tried to use the readLine() method from DataInputStream but this doesn't give me the correct UTF8 string.
You see my dilemma. Can't I use two readers for one InputStream? Or can I convert the DataInputStream.readLine() result and convert it to UTF8?
Thanks,
Martin
We know from the design of the UTF-8 encoding that the only usage of the value 0x0A is the LINE FEED ('\n'). Therefore, you can read until you hit it:
/** Reads UTF-8 character data; lines are terminated with '\n' */
public static String readLine(InputStream in) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while (true) {
int b = in.read();
if (b < 0) {
throw new IOException("Data truncated");
}
if (b == 0x0A) {
break;
}
buffer.write(b);
}
return new String(buffer.toByteArray(), "UTF-8");
}
I am making the assumption that your protocol uses \n as a line terminator. If it doesn't - well, it is generally useful to point out the constraints you're writing to.
Do NOT use BufferedReader and DataInputStream on the same InputStream!! I did that and spent days trying to figure out why my code broke. BufferedReader can read more than what you extract from it into its buffer, resulting in situation when the data I was supposed to read with the DataInputStream being "in the BufferedReader". This resulted in lost data which caused my program to "hang" waiting for it to arrive.
I believe that you should not mismatch the BufferedReader and DataInputStream here. DataInputStream has readLine() too, so use it.
And yet another comment. I am not sure it is a problem but avoid multiple calls of socket.getInputStream(). Do it once and then wrap it as you want using other streams and readers.
Am I understanding it correctly that you are sending both text and binary data on the same socket, in the same "conversation"? There should be no problem creating two readers for the same inputstream. The problem is knowing when (and how much) to read which reader. They will both consume (and advance) the underlying stream when you read from them, since you have mixed types of data. You could just read the stream as bytes and then convert the bytes explicitly in your code (new String(bytes, "UTF-8") etc). Or you could split your communication onto two different sockets.
NOW here is the coding for j2me mobile for sending the string:
String s="hai";
try{
String url = "btspp://001F81000250:1;authenticate=false;encrypt=false;master=false";
StreamConnection stream = null;
InputStream in;
OutputStream out;
stream = (StreamConnection) Connector.open(url);
out=stream.openOutputStream();
String s=tf.getString();
byte size=(byte) s.length();
out.write(size);
out.write(s.getBytes());
out.flush();
out.close();
stream.close();
}
catch(Exception e){
}
NOW the coding for j2se for receiving the String :
StreamConnectionNotifier notifier=null;
try{
String url = "btspp://localhost:"+new UUID("1101", true).toString()+";name=PCServerCOMM;authenticate=false";
System.out.println(LocalDevice.getLocalDevice().getBluetoothAddress()+"\nCreate server by uri: " + url);
notifier= (StreamConnectionNotifier) Connector.open(url);
while(true){
System.out.println("waiting....");
StreamConnection con = notifier.acceptAndOpen();
System.out.println("Got connection..");
InputStream is=con.openInputStream();
//byte b[]=new byte[40];
/*
while(is.available()>0){
System.out.print((char)is.read());
}*/
//is.read(b, 0, 40);
int size=is.read();
byte b[]=new byte[size];
is.read(b, 0, size);
File f=new File("d://test.xml");
FileOutputStream fo=new FileOutputStream(f);
fo.write(b,0,b.length);
fo.close();
con.close();
System.out.println(new String (b));
}
//printing(f);
} catch(Exception e){
JOptionPane.showConfirmDialog(new JFrame(), e.getMessage());
}
I tried this coding for data transfer but it is not a successful one because when the string which we sent is too long then there is problem in receiving side. How can I solve this?
Is there any other way to transfer the data in rms to j2se, if so please help me.... please make your reply quick...
The way you are writing and reading here, only strings up to 255 characters in length, which additionally only take the same number of bytes in your default encoding, are written right.
On the writing side:
The statement byte size=(byte) s.length(); converts the length of the string in a byte, thus only takes the lower 8 bits of the length. So, only lengths up to 255 are written right.
Then you are converting the String to a byte array with s.getBytes() - this array could be longer (in bytes) than the original string in characters. This conversion uses the default encoding of your sending device.
On the reading side:
The statement int size=is.read(); reads the length written before, then you are creating a byte array.
is.read(b, 0, size); reads some bytes into this array - it does not necessarily fills the complete array.
Then you are converting your byte array (which may not even be filled completely) to a string, using the default encoding of the receiving device.
So, we have:
All strings longer than 255 characters are written wrongly.
If sending and receiving side are using different encodings, you may get a wrong output.
If the sending side uses an encoding like UTF-8 where some characters take more than one byte, the string is cut off at the end (if such characters occur).
How to solve this:
If you can use a DataInputStream and DataOutputStream on both sides (I don't know anything about J2ME), use them there, with their readUTF and writeUTF methods. They solve all your problems (if your strings take at most 65535 bytes in the modified UTF-8 encoding used here).
If not:
make a decision on how long the strings can be, and encode your length with the right number of bytes. 4 bytes are enough for every Java String.
measure the length after converting to a byte[], not before.
use a loop for reading into the array, to be sure to capture the whole string.
for the getBytes() and new String(...), use the variants which take an explicit encoding name and give them the same encoding (I recommend "UTF-8").