1

I'm building a swing interface in Java, I build a middleware which keeps reading the serial port and saving what's coming to String, here it's how I'm doing this:

public class RFID {
  private static RFIDReader rReader;
  private static boolean state;

  public RFID(RFIDReader rReader) {
    this.rReader = rReader;
    this.state = true;
  }

  public void connect(String portName) throws Exception {
    CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
    if (portIdentifier.isCurrentlyOwned()) {
        System.out.println("Error: Port is currently in use");
    } else {
        CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);

        if (commPort instanceof SerialPort) {
            SerialPort serialPort = (SerialPort) commPort;
            serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

            InputStream in = serialPort.getInputStream();
            OutputStream out = serialPort.getOutputStream();

            (new Thread(new SerialReader(in))).start();
            //(new Thread(new SerialWriter(out))).start();

        } else {
            System.out.println("Error: Only serial ports are handled by this example.");
        }
    }
}

public static class SerialReader implements Runnable {

    InputStream in;

    public SerialReader(InputStream in) {
        this.in = in;
    }

    public void run() {
        byte[] buffer = new byte[1024];
        int len = -1;
        String code;
        try {
            while (state == true && (len = this.in.read(buffer)) > -1) {
                code = new String(buffer, 0, len);
                if (code.length() > 1)
                    rReader.setCode(code);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public void finish(){
    state = false;
}

public static class SerialWriter implements Runnable {

    OutputStream out;

    public SerialWriter(OutputStream out) {
        this.out = out;
    }

    public void run() {
        try {
            int c = 0;
            while ((c = System.in.read()) > -1) {
                this.out.write(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

So when I try to print what code is storing, it shows like this:

AC000F9
3
BB

What actually should look like this:

AC000F93BB

What am I doing wrong here ? This conversion from byte[] to String is not right ?

EDIT: I need to read a string with 10 characters at total.

2
  • Put a breakpoint on the line where 'code' is assembled. Read the value of len. Commented Apr 18, 2012 at 18:12
  • 1
    ..or, to put it another way, why should it look like 'AC000F93BB'? Why should read() not return after it has got the first 7 characters? Commented Apr 18, 2012 at 18:13

1 Answer 1

5

Don't use an InputStream to read from - use a Reader of some description. If you need to start with an InputStream, wrap it in an InputStreamReader. I would change your constructor to accept a Reader though, and allow clients to pass whatever reader they want in. That will make it easier to test (as you can just use a StringReader).

EDIT: Note - if you do need to create a reader from a binary InputStream, be explicit in your choice of Charset (encoding). So use the InputStreamReader constructor overload which specifies one. Even if you want to use the platform default, I'd be explicit about that to make it clear what you're doing.

EDIT: Beyond "where the string conversion happens" it's unclear what you're expecting to read. You're dealing with streaming APIs - what determines how much you really want to read before calling setCode? Is it a whole line? Is it some fixed number of characters? Is it characters before a particular delimiter?

EDIT: Now we know a bit more, I suggest you write a helper method like this:

// Assuming you now have a field of type Reader, called reader
private String readEntry() throws IOException {
    char[] buffer = new char[10];
    int index = 0;
    while (index < buffer.length) {
        int charsRead = reader.read(buffer, index, buffer.length - index);
        if (charsRead == -1) {
            throw new IOException("Couldn't read entry - end of data");
        }
        index += charsRead;
    }
    return new String(buffer);
}
Sign up to request clarification or add additional context in comments.

6 Comments

I'd also add: choose a Charset. That's the only way to be sure of your conversion between byte[] and String.
@JonSkeet, thank you for your help. I'm new with Java, so I put my class so you guys could look what it's really happening. I'm expecting to read a string with 10 characters at total. It's a fixed number of characters, always 10, there's no particular delimiter, the SERIAL_PORT library already take care of that, but that's just this annoying problem wich we are discussing here.
@ValterHenrique: Okay, if you always want to read 10 characters, you'll need to loop through reading "an amount" until you've got 10. Will edit.
@ValterHenrique: Have a look now.
@JonSkeet I still don't know how to initialize the reader, because I need to start with an InputStream because the serialPort object have only serialPort.getInputStream() which returns an InputStream. So I try to wrap with InputStreamReader but this class don't return a Reader object tough.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.