This week's book giveaway is in the Python forum.
We're giving away four copies of Python Continuous Integration and Delivery and have Moritz Lenz on-line!
See this thread for details.
Win a copy of Python Continuous Integration and Delivery this week in the Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Paul Clapham
  • Jeanne Boyarsky
Sheriffs:
  • Devaka Cooray
  • Junilu Lacar
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Ron McLeod
  • Tim Holloway
  • Claude Moore
  • Stephan van Hulst
Bartenders:
  • Winston Gutkowski
  • Carey Brown
  • Frits Walraven

org.apache.commons.net.telnet.TelnetClient - InputStream available() always returns either 1 or 0.  RSS feed

 
Eric Burdon
Greenhorn
Posts: 4
Java Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello.
I'm trying to create an android Telnet client. I'm using the TelnetClient class and create an object. Then i get an InputStream with getInputStream() and from it i create an InputStreamReader. This runs on a separate from the main thread. The TelnetInputAvailable() of a TelnetInputListener object is called every time the input buffer goes from zero to none zero bytes. So inside this method i try to get the data calling the read() method of the InputStreamReader object.
The problem is that the InputStreamReader's read() method returns ALWAYS ONLY one character. Then the TelnetInputAvailable() method has to be called for a new character to be fetched.
The same happens also if i just use an InputStream and get bytes. Only one byte i get every time.
Do you know how can i get more than one character?

Code:


 
Rob Spoor
Sheriff
Posts: 21642
101
Chrome Eclipse IDE Java Spring Ubuntu VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you use the read() method, you are explicitly asking for a single byte or character. To read more than one, use the read method that takes an array. There are actually two overloaded versions, but I hardly ever use the indexed one.

Regardless of the one you're using, the read will fill elements from the offset (0 for the non-indexed overloaded version), and return the number of elements filled. This can be 0, but the only return value that indicates nothing was left is -1.

A small example of how to read everything from a Reader (for InputStream, replace char with byte, the process is the same):
 
Eric Burdon
Greenhorn
Posts: 4
Java Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Rob Spoor.
I had already used the method you describe in your post. Also in this case only one character is read
in the buffer. Using your EXACT code snippet after reading the first character the while loop is stuck
in the condition evaluation for ever. Only if i use reader.reset() in the while body it continues reading
all the characters (although it raises errors for not supported method).
What i understand is that the TelnetClient class somehow prevents the InputStream it uses from reading more
than one byte/character even if i give it a buffer as argument. This makes the TelnetInputListener class
useless as its telnetInputAvailable() method runs only once for the whole program flow.
For now i use the following code to do my job:



Thanks for the help!
 
Rob Spoor
Sheriff
Posts: 21642
101
Chrome Eclipse IDE Java Spring Ubuntu VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've dived into the code a bit, and it seems that the listener can indeed be triggered for each single byte. The listener is notified by calling (package private) method TelnetClient.notifyInputListener(). This is done by (package private) class TelnetInputStream in a background thread. This calls a private method, __processChar. If this method returns true, the client notifyInputListener() method is called. And this method returns only true if the object's internal buffer was empty before. There is some buffering possible (because TelnetInputStream extends BufferedInputStream) but I think that can only be used if you don't use the listener.

Now your code looks pretty good, but I would suggest some small changes, mostly for performance reasons. You're now:
1) Creating a new InputStreamReader every time. This may even lead to bugs in case the InputStreamReader consumes several bytes without reporting them immediately.
2) Converting the char you read into a String.
3) Using String concatenation for probably quite a lot of chars. That means that your message += s is actually quite a few occurrences of message = new StringBuilder().append(message).append(s).toString()
4) If there's an IOException while reading you will append the String "null" (because that's what will happen if append null to a String).
5) You're using new String(message) where message already is a String. That creates a new String unnecessarily.
6) You're using == true, something that's never necessary.

The following is a quick attempt to fix the above (with not-so-great error handling though):

There is one thing I would suggest you try in the above - instead of doing a single read, do a read while sreader.ready(). That way you will still read all chars if the listener is triggered for more than one char.
 
Eric Burdon
Greenhorn
Posts: 4
Java Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Rob spoor! So it seems i have to tackle the TelnetClient code to make the TelnetInputStream public or something like this. But i'll just make the corrections that you suggested in the code and not mess with the libraries internals. Thank you very much for the corrections too!
 
Rob Spoor
Sheriff
Posts: 21642
101
Chrome Eclipse IDE Java Spring Ubuntu VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're welcome. And you indeed shouldn't mess with library internals, I only took a look to see if you were missing something or not.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!