catching <CR><LF> in a bytes array - java

I have wrote an event listener that suppose to read any messages of a specific type from a receiver.
here is my event listener:
class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR() && event.getEventValue() > 0) {
try {
byte[] buffer = SP.readBytes(6);
String type = new String(buffer);
if (type.equals("$GPGGA")){
String line = "";
line = line + type;
buffer = SP.readBytes(66);
String values = new String(buffer);
line = line + values;
writer.write(line + "\n");
}
}
catch (SerialPortException ex) {System.out.println(ex);}
catch (IOException ex) {System.out.println(ex);}
}
}
}
right now after i check that the message is of the correct type i just read 80 bytes off data, which is roughly the size of the message.
however, sometimes the message is not full and there for it is shorter then usual.
this is the message structure:
as you can see, the message end s with <CR><FL>.
i would like to modify my method so it would read each byte at a time and stop reading once it hits the end of the message. how can i catch the <CR><FL> inside the byte array?
any help would be appreciated. thank you.

It depends on the definition of "messages": are they fixed-length or delimited by a certain sequence? In your current code, you're reading a "header" that is 6 bytes long and a "message" that is 66 bytes long. However, it appears that you actually don't know the length a priori, and instead the message is newline-terminated. A couple of pointers:
You're reading bytes from the stream, then turning them into a String by using the String(byte[]) ctor. The documentation states that this uses the default charset for your platform, which may be UTF-8, Latin-1 or whatever regional default. If you are communicating with a device over a serial port, this is probably not what you want since the device is likely to have a single, specific charset for messages (maybe ASCII?). Investigate that point and use either this String ctor or, if you want to be notified when the input contains undecodable garbage, the CharsetDecoder class.
If the messages are text-based and newline-delimited, you should definitely use a BufferedReader to read from the stream. Assuming that your SP serial port is an InputStream, you could create a BufferedReader over it, and then call the readLine() method on the reader. The reader will keep requesting bytes from the stream until it sees a newline, then return the whole line to you as a String. Reader objects also encapsulate the Charset I was talking about before.

I have managed to solve my problem.
pretty easy solution:
String tmp = SP.readString();
String[] msgs = tmp.split("\r\n");
after reading the string from the serial port, i just split it by the end of line.

Related

Is there a way to determine which OutputStream is currently sending through to my sockets inputstream?

This is my client right now:
#Override
public void run()
{
try
{
#SuppressWarnings("resource")
InputStream socketIn = socket.getInputStream();
Scanner in = new Scanner(socketIn);
PrintWriter out = new PrintWriter(socket.getOutputStream());
ObjectInputStream oin = new ObjectInputStream(socketIn);
gui = new GuiController(out);
while (true)
{
System.out.println(socketIn);
if(in.hasNext()){
gui.updateResponse(in.nextLine());
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
As you can see, I have both an ObjectInputStream as well as a Scanner. This is because I am both sending simple Strings from my Server, which should be caught by the string, as well as Hashtable-Objects, which are dealt by the ObjectInputStream.
However, now I need to determine whether my Servers PrintWriter or ObjectOutputStream sent the data, so I can react to it. If I don't make any check, my Scanner will just grab the object and print it as a string, which is obviously very wrong.
I need something like this:
if(socketIn.origin == ObjectOutputStream){
}
else{
}
Note that this is just some pseudo code, but I think you get the idea.
Disclaimer: This is certainly not the recommended way of doing this for that look at EJP's answer.
But what you could do:
Before you send anything through your object stream or string stream, send a string through the string stream telling the client what to expect. After that you send the actual data via either the string stream or the object stream. So in pseudocode this would be:
read string with string input stream
if string==object then
read data with object input stream
handle object
else if string==string
read data with string input stream
handle string
This would work as you first receive what is coming, and then you read the actual data.
For the sake of completeness here's the pseudo code for the sender:
if the data to send==object
print 'object' to the string output stream
print object to the object ouput stream
else if data to send==string
print 'string' to the string output stream
print data string to the string ouput stream
I hope this helps you :)
NOTE: Be very carefull doing this when your socket is used by multiple threads.
NOTE: You could also wrap your string in an object and just send it through the object stream.
No. There is only one data stream. This will never work, for a number of reasons. Use a single stream, or reader/writer pair, or DataInput/OutputStream pair, or ObjectInput/OutputStream pair.

Read Complete Line Java Serial Port

I have implmented JSSC API so I can communicate with the Com Port.
I send a command like "N\r\n"
and what i receive in a normal hyperterminal should look like this:
0100071CA79215021803164442180000
0100071C9F5415021803164514520000
0100071CDF5115022106142956600000
NOK
But when i do the same with the JSSC API i receive this (only the first code)
010
0071CA79
2150218
0316444
218
The Problem is that i randomly receive bit parts and at the end of the code i lose some parts. But thats not important i only need the first 12 digits of every code.
The Question is now how do i get the function to only receive the full line and not bitparts?
This is the receiving part of the class
class PortReader2 implements SerialPortEventListener {
#Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()&& event.getEventValue() > 2) {
try {
// получение ответа от порта
String receivedData = serialPort.readString();
System.out.println(receivedData.length() + ":" + receivedData);
}
catch (SerialPortException ex) {
System.out.println("Error in receiving response from port: " + ex);
}
}
}
}
This is the sending part
public void sendCodeCommand(SerialPort serialPort) {
// writing string to port
try {
Thread.sleep(3000);
serialPort.writeBytes("N\r\n".getBytes());
} catch (SerialPortException | InterruptedException ex) {
Logger.getLogger(ComPortSendReceive.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("String wrote to port, waiting for response..");
}
To fix the stated problem you need to concatenate the strings you receive into another string that accumulates the string fragments you receive from the readString() function, which is in the serialEvent handler. Because it is it's owm thread it gets a certain amount of cpu time to get serial data so it effectively gets partial sequential reads of the serial port input data. So this example puts the partial inputs together to create the "whole" input.
String serialString;
So within the serialEvent handler:
try {
serialStringFragment = serialPort.readString();
serialString.concat(serialStringFragment);
}
Either the string you get from readString() or the accumulation string can be scanned for tokens like eol condition. For Example:
String [] dlLines = serialString.split("\r\n");
will break each line out to an element in the dlLines string array.
However I have found that if I have fixed length output from my target device this works better:
serialPort.readString(int bytecount);
inline with the write serial string, eliminating the serialEvent handler.
This is a bit contrived but In other words:
String expectedStringLength "0100071CA79215021803164442180000";
int serialstrlen = expectedStringLength.length();
So the serialstrlen should obviously become constants for each expected line.
serialPort.writeString("N\r\n");
serialPort.readString(serialstrlen+2); // assuming cr lf
should get you the first line.
Put the readString() in a loop, change serialstrelen argument value according to the expected strings. Check the strings for alternate content for error handling. This has worked for me.

What value is there after we read values from InputStream

I wanted to know that when we read something from InputStream after that what value is there in stream? Is it deleted or same value is retained?
For eg I have one code which reads something from InputStream and prints on the screen. Here is the code:
char[] data = new char[1024];
while (!isInterrupted()) {
try {
in.read(data); // Step 1
} catch (IOException e) {
continue;
}
msg = new String(data);
System.out.println(msg); // Step 2
}
So when first time step 1 reads something and step 2 prints it, it is okay. But when again it is coming to Step 1 and IF sender has NOT sent anything then what Step 1 will do? Will it wait till it gets new value (or sender sends anything) or it will read the same value and print the same value? Or it will throw an Exception? Please help.
The javadoc says:
This method blocks until input data is available, end of file is detected, or an exception is thrown.
So, unless the sender closes the stream, it will block until data is available, as per the documentation.

Buffered writer writes memory trash on text file

My buffered writer is writting some randomly trash in my txt file. I use int nodes = Integer.valueOf(NODES_TEXT_FIELD.getText()); to store the value of one TextField that should only accept ints.
this is my writer:
private static void writeOnFile(BufferedWriter writer, int nodes){
try {
System.out.println(nodes);
System.out.println("Last check before write");
writer.write(nodes);
System.out.println(nodes);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Failed to write data on file");
e.printStackTrace();
}
}
My output:
2
Last check before write
2
and in the text file I found: '?' (which changes to another memory trash depending on what number you input
Anybody has any Idea of what might be wrong? I stuck here for 5 hours until now..
Because write() writes a character .
Writes a single character. The character to be written is contained in the 16 low-order bits of the given integer value; the 16 high-order bits are ignored.
Parameters:
c - int specifying a character to be written
You can use Writer#write(String):
writer.write(String.valueOf(nodes));
Try this:
Writer wr = new FileWriter("thefileToWriteTo.txt");
wr.write( String.valueOf(nodes) );
wr.close();
you can always extract the writing into a loop if that is what you are doing with your nodes or some kind of escaping, it would be more helpful if you explain what is it that you are actually trying to achieve by writing this to a file, as we might advise you on that.

Client socket read "freezes"

I want to write a simple web proxy, for exercise. Here's the code I have so far:
def g = new Proxy()
g.serverPort = 9000
println "starting"
g.eachClient { Socket client ->
println "got a client"
try {
client.withStreams { input,output ->
String text = input.text
println "received $text from client"
client.close()
}
} catch(IOException io) {
println "IO error. Probably client disconnected"
//io.printStackTrace()
}
}
the thing is, the line :
String text = input.text
consumes all the available data in the Socket's InputStream. If the client isn't closing the connection, that method will just wait until it can read a end of file character ( if I remember correctly ). What do I have to prevent this from happening, and have the client's string available ASAP?
I think you'll want to check the documentation on ObjectInputStream. Do length = input.available to get the number of available bytes at the present time, then use input.read(buffer, offset, length) to read in exactly as many bytes are available. You'll probably want to launch a new thread for every new connection which transparently manages this buffer in the background, unless you're making a single-threaded proxy to begin with.

Categories

Resources