Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read bytes from Java NIO socketchannel until marker is reached

I´m searching for an efficient way to read bytes from a socket channel using Java NIO. The task is quite easy, I have a solution, though I´m searching for a cleaner and more efficient way to solve this. Here´s the scenario:

  1. Data is read from a socket channel
  2. This data is a UTF-8 encoded string
  3. Every line is ended by \r\n, the length is unknown up front
  4. After every line read, I want to do something with the message

My solution reads the data byte per byte and compares every byte to my marker (which is has the value 10 in UTF-8 code pages). Here´s the code:

ByteBuffer res = ByteBuffer.allocate(512);
boolean completed = false;
try {
    while (true) {
        ByteBuffer tmp = ByteBuffer.allocate(1);
        if(soc.read(tmp) == -1) {
             break;
        }

        // set marker back to index 0
        tmp.rewind();
        byte cur = tmp.get();
        res.put(cur);

        // have we read newline?
        if (cur == 10) {
            doSomething(res);
            res.clear();
        }
    }

} catch(Exception ex) {
     handle(ex);
}

Even though this does the job, there might be a better way, that doesn't need those per byte comparisons after every iteration.

Thanks for your help!

like image 202
Patze Avatar asked Sep 27 '22 07:09

Patze


1 Answers

The way I would do it is to read as much as is available, such as 32 KB, and once you have read this, you copy the data byte-by-byte to another buffer, e.g. a StringBuilder. If there is data left in the buffer from the last time you read, you can continue using the buffer until it it is all consumed, at which point you read more data.

Note: each system call is expensive. It could take 2-5 micro-seconds. This doesn't sound like much unless you call it millions of times and it will add seconds to reading 1 MB.

like image 102
Peter Lawrey Avatar answered Oct 05 '22 05:10

Peter Lawrey