Reputation: 6992
How to read all available characters to a String
using BufferedReader
?
I have a Socket
from which I want to read data, when available, and store it in a String
. The thing is, I can't use readLine
because the data I receive not always contains a newline or caret return, and readLine
blocks thread until it can read a full line. How to use read
instead?
thread = new Thread(() ->
{
try {
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
while(true)
{
if (in.ready())
{
String someString = // ? read available data
delegate.didReadData(this, someString);
}
}
} catch (IOException e) {
delegate.didDropSocket(this);
}
});
thread.start();
edit
1. delegate doesn't care how long the string is, it just needs to handle any hada that arrives via socket - and full contents of it
2. I don't need to cut data into chunks - I want to read everyhing that arrives
3. Yes, I have an infinite loop for I need to stay connected to the socket and listen for data until client drops the connection - when I get an IOException
. I use a separate thread for socket because there will be much more sockets to listen to.
Upvotes: 0
Views: 3276
Reputation: 73578
You need to always explicitly specify which encoding you're using, you don't need to check before reading, and of course you have to keep track of how much you've read and whether the other end has closed the connection.
Exception handling and closing of resources is omitted. Buffer size can be increased if necessary. Otherwise this is a pretty idiomatic read-loop.
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8));
char[] buf = new char[4096];
int size = 0;
while((size = in.read(buf)) != -1) {
String someString = new String(buf, 0, size);
delegate.didReadData(this, someString);
}
Upvotes: 2
Reputation: 264
BufferedReader#readLine(0)
treats '\n', '\r', and "\r\n" as line-separators. This behaviour cannot be changed, so as you say, we need to use one of the two overloads of read
instead.
What does delegate
need? Does it care how long someString
is? Do you need to 'chunk' the data you read from in
? Are you sure that String
is appropriate?
I suspect that you want the read(char[] cbuf, int off, int len) method.
Assuming you don't need to read one char at a time, you'll get better performance using that chunk-at-a-time overload of read
, than using the one-char-at-a-time overload.
Also, you have an infinite loop. Even when ready
returns false, your code won't terminate, as you never leave your while(true)
loop.
Or is the intent here to have the thread constantly check for more data, without end? I'm not familiar enough with the Java standard library to give details, but I'm confident there's a better way to do it than to have a thread run one of your cores at 100% load, checking for additional data. The simple hack would be to add a sleep
call, but I'm sure there's a better way, perhaps involving the Stream
class.
Upvotes: 1