Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

timout on readLine

Posted on 2000-04-12
16
Medium Priority
?
427 Views
Last Modified: 2008-03-06
Hello,
   How would you write java code to timeout on a call to BufferedReader.ReadLine() ?

I would like to make the call and if nothing comes back in a minute then terminiate the read.


0
Comment
Question by:calvinrsmith
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +2
16 Comments
 
LVL 16

Accepted Solution

by:
imladris earned 27 total points
ID: 2708394
Do the readLine in a separate thread. Then, when the main thread has waited long enough, it can carry on. It may want to kill the "read" thread. This can be done with the stop method, or (since stop has been deprecated in 1.2) by calling interrupt and the read thread catching the InterruptedException.
0
 
LVL 5

Expert Comment

by:mbormann
ID: 2708897
readymade code,pls look and use it...
Notice that this code is JDK1.2 compliant ,I am closing the underlying InputStream in ,so

if you have to close the socket read/write
you have to close() the underlying input/output stream.
Get a reference like
InputStream in=sock.getInputStream();
Use in program like
BufferedReader buff = new BufferedReader(new InputStreamReader(sock.getInputStream()));

The reason is that both read() and close() are synchronized in
Wrapper classes like BufferedReader & BufferedInputStream in JDK 1.2
& up ,so this above program will only work in JDK 1.1.

Translated into simpler terms when you call close() ,it will block
forever.

So use

in.close() instead of buff.close()

public class AsyncReadBuffer
{
    private StringBuffer result;

    public AsyncReadBuffer()
    {
        result = new StringBuffer(500);
    }

    //Get the string already read from the socket so far.
    //This method is used by the Applet or external thread
    //to obtain the data in a synchronous manner.
    public synchronized String getResult()
    {
        String retval = result.toString();
        result.setLength(0);
        return retval;
    }

    //Put new data into the buffer to be returned
    //by the getResult method
    public synchronized void update(char c)
    {
        result.append(c);
    }

public synchronized void update(String s)
    {
        result.append(s);
    }
}


import java.util.*;
import java.io.*;
import java.net.*;

public class ClientHandler extends Thread
{
    private InputStream in;
    private BufferedReader buff;
    private Socket sock;
    private AsyncReadBuffer aReader;
    private boolean isDone = false;
    private Object lock = new Object();
private int timeout;
private boolean isReadLineMode=false;

    class ClientHandlerThread extends Thread
    {
        public void run()
        {
            String s;
int c;
            try
            {
if(isReadLineMode)
{
while ((s = buff.readLine()) != null)
    aReader.update(s);
}
else
{
while ((c = buff.read()) != -1)
    aReader.update((char)c);
}
}
            catch (Exception e)
            {}

            isDone = true;
            synchronized(lock)
            {
                lock.notify();
            }
        }
    }

    public ClientHandler(AsyncReadBuffer a, Socket s,int t,boolean isReadLine)throws Exception
    {
this.aReader=a;
        this.sock=s;
this.isReadLineMode=isReadLine;
if(t<0 || t==Integer.MAX_VALUE)
throw new Exception("Specify correct timeout value");
this.timeout=t;
    }

    public void run()
    {
try
{
    in=sock.getInputStream();
    this.buff = new BufferedReader(new InputStreamReader(in));
    Thread t = new ClientHandlerThread();
    t.start();
    synchronized(lock)
    {
        while (!isDone)
        {
            try
            {
                lock.wait(this.timeout);
            }
            catch (InterruptedException ie)
            {
                isDone = true;
                try
                {
                    t.interrupt();
                    this.in.close();this.in=null;
                    this.sock.close();this.sock=null;
                }
                catch (Exception e)
                {}
            }
        }
    }
}
catch(Throwable t)
{
System.out.println("Caught Exception during run() in timeout main thread");
t.printStackTrace();
}
}
}
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2709276
I've been working on trying to find a non-threaded solution. After a good bit of experimentation, I determined that the code appearing below SHOULD work. Unfortunately, it does not work on win32 systems because the BufferedReader implementation -- at least in jdk1.3rc2 -- does not correctly (or at least to my liking) implement the semantics of readLine().

The API docs for readLine state: "Read a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed." This gives one (one being me in this case) the impression that the entire line-termination sequence will consumed. On win32 systems, line-termination is "\r\n", two characters. Unfortunately, the implementation does not consume both characters immediately. It finds the carriage return but leaves the newline in the buffer. As a result, ready() returns true but the subsequent read blocks when the only content in the buffer is the second half of the win32 line termination sequence.

This same problem does not appear to plague the InputStreamReader so it would be possible to use the technique implemented below with that reader. Perhaps I should provide a readLine() implementation for InputStreamReader? If anyone is interested, let me know.

Here is the correct but, on win32 systems, non-working code:

---------- TimedReader.java ----------
import java.io.InputStreamReader;
//import java.io.BufferedReader;
import java.io.Reader;
import java.io.IOException;

public class TimedReader {
    public static void main(String[] args) {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader in = new BufferedReader(isr);
        while (true) {
            try {
                System.out.print("Enter a String: ");
                if (ready(in, 5000)) {
                    String s = in.readLine();
                } else {
                    System.out.println("timeout");
                }
            } catch (IOException e) {
                // ignore until we know what to do
            }
        }
    }

    public static boolean ready(Reader in, long timeout) throws IOException {
        while (true) {
            long now = System.currentTimeMillis();
            try {
                while (in.ready() == false && timeout > 0) {
                    Thread.sleep(100);
                    timeout -= 100;
                }
                return in.ready();
            } catch (IOException e) {
                throw e;
            } catch (Exception e) {
                // ignore
            } finally {
                // adjust timer by length of last nap
                timeout -= System.currentTimeMillis() - now;
            }
        }
    }
}
---------- end ----------

Since you didn't state your platform, this code may work just fine for you. I hope so. I have a modified version of BufferedReader.java which fixes the problem -- but I don't know how robust that fix is or whether it would prevent this scenario in all circumstances.

Best regards,
Jim Cakalic
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Expert Comment

by:mbormann
ID: 2709345
I think Jim ur code would work on JDK 1.2.2 ,what do you think ?

Have they introduced a bug in JDK1.3?
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2709399
Amit, if you have a previous version of the JDK, would you care to give it a try? I only have 1.3 at my disposal presently.

You may be right, though, about changed behavior. In Harold's Java I/O book from O'Reilly, he states that BufferedReader.readLine() has "the potential to hang on a long carriage return that ends the stream. This problem is especially acute on networked connections, where readLine() should never be used." Browsing the bug database at JDC, I found quite a few complaints about the hanging carriage return problem. Perhaps they introduced a 'fix' in 1.3. Again, I don't have what I need to check this out so any help would be appreciated.

Jim
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2709420
Just realized that, since I have JBuilder 3 I have jdk1.2.2 installed. Found the source and the code for BufferedReader.readLine() has been changed. Compiled and tested the old code with my program above and it works!!!!! I'm not going crazy after all.

Guess I'll post something on the bug parade. Doubt if it will get into jdk1.3, though. They're already in rc2.

Jim
0
 
LVL 1

Author Comment

by:calvinrsmith
ID: 2709529
  I'm still using JDK1.1.8 I'll give the above ideas a try and let you know what I find.  
0
 
LVL 5

Expert Comment

by:mbormann
ID: 2709574
calvinrsmith,
Oops sorry I realized that I had cut-pasted wrong explanation in my long comment above. But the code is perfect. You can use that too .

But I think u would be happy with Jim's solution.
:)

Jim , it works. And I will post this code sometime later today to the question from which I cut-pasted the original code.

Cheers fellows
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2710487
Those guys at Sun are fast. I submitted a bug report this afternoon and already got back a reply that it is considered to be a new defect and has been assigned id 4329985. It may not show up on the bug parade for several days according to the email I received.
0
 
LVL 5

Expert Comment

by:mbormann
ID: 2712351
Wow ! Yes I also reported a 'bug' but it was submitted just sometime b4 I sent them a mail and they gave the same reply.

They work round the clock is what I think,must be having guys all over the world in differect time zones.

Cheers Jim
0
 
LVL 1

Author Comment

by:calvinrsmith
ID: 2713884
jim_cakalic,
  I tested your code with jdk1.1.8 on win98 and found that in.ready() always returns true, even if your ready function just started.
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2751117
Calvin, I don't know what to tell you about this other than jdk1.1.8 is notoriously buggy. Running in win95 or win98 doesn't help. Is it possible for you to use a more recent release of the jdk? Any of the 1.2 releases would be better. Frankly, many suggestions I have seen are to stick with 1.1.7 if 1.2 is not an option.

I've got IBM's port of 1.1.8 to AIX that I can look at. Barring that, I'd have to download and unpack (if not install) another jdk version. Painful but I'd consider doing it.

Anybody else have any ideas?
Jim
0
 

Expert Comment

by:leach072899
ID: 3965392
I checked this code on VisualAge with JDK 1.1.7 - works perfectly.
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 3968479
Hi, leach.

This one has certainly been around for awhile, hasn't it? Thanks for testing it. I figured Calvin had abandoned the question. Looked on the JDC and the bug has 21 votes but apparently never got fixed in the 1.3 release.

Jim
0
 

Expert Comment

by:leach072899
ID: 3968641
Hi Jim,
Well it was about something i was looking for.
Moving to Java 2 (any version) looks a bit farther then i want it to be, for us VisualAge users.
My problem is a bit more trickier so i opened another question on it - see if you can answer.

lee
0
 

Expert Comment

by:leach072899
ID: 3997345
I said it runs with JDK 1.1.7 - i must retrackt that.
At least on the IBM implementation the timeout works perfectly when needed - but when all is well - using the timeout after the connection was closed (from either end) will result in a timeout condition. And there is no way (that i found yet) to distinguish the two cases: timeout and connection closed.

lee
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Suggested Courses

609 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question