🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.jbuilder.java.swing
Article #8946

Re: Redirecting System.in

#8946
From: Jeroen Zwartepoorte
Date: Wed, 14 Jun 2000 00:00
105 lines
5236 bytes
"John P. McGrath" <JPMcGrath@fast.net> wrote in message
news:MPG.13b0e12eea71f5b29899c5@forums.borland.com...
> On Tue, 13 Jun 2000 15:54:51 +0200, Jeroen Zwartepoorte wrote:
>
> > I'm trying to have System.in point to a JTextArea instead of
> > the command prompt. To accomplish this, i've written my own
> > InputStream class. The class works partly: System.in.read()
> > does return character typed in the JTextArea, but when i
> > use BufferedReader.readLine(), the method never returns
> > (System.in.read() DOES return '\n' characters).
>
> You do not show the code that points System.in to your input stream
> object or the code creates the buffered reader.  My guess is that your
> problem is with this code.  If you post it, I will take a look.

That code is very simple:

    System.setOut(new Pl0PrintStream(textArea));
    System.setIn(new Pl0InputStream(textArea));

BufferedReader creation is also trivial:

    String sTest = new BufferedReader(new
InputStreamReader(System.in)).readLine();

> I have a few other comments:
>
> You use a stack to buffer the characters that have been read.  If someone
> were to quickly type "ABC" before any of the characters were read, the
> input stream would return "C", "B", "A" in that order.  I think you
> should be using a queue rather than a stack.

Hmm, i must have been sleeping while writing that code. Stack uses LIFO and
i want FIFO. Thanks!

> You synchronize the code that adds a character to your buffer, but not
> the code that removes a character from the buffer.  I don't believe this
> will help if you do not do it in both places.

Why not? If i make sure that when i add something to the Queue, i'm the only
thread currently accessing that Object, then there is no reason to add
another synchronized in the read() method?!

> The synchronization will probably not cause a problem as written, since
> you are using a Stack, which extends Vector, which is synchronized.  But
> if you change this to a queue of some kind, the synchronization will be
> important.
>
> Your code currently polls in the read() method, waiting for a character
> to be added to the buffer.  A better approach would use wait() and
> notify().  Information on using wait/notify is available at the following
> URL.  Note that the URL is too long to fit on a line, so clicking on it
> will not work.
>
>     http://java.sun.com/docs/books/tutorial/essential/
>         threads/waitAndNotify.html

I haven't read the document (yet), but the jdk docs state that read() should
block until there is something to return. That's why i've added the
Thread.sleep method. You do have a valid point about dead-locking: the
read() method is currently called from a non-AWT thread, so i'm safe here.

> Regardless of how you synchronize the threads, you will run into a
> problem if someone calls your read() method from the AWT event dispatch
> thread.  If the buffer is empty, it will block waiting for a character to
> be added to the buffer, but that can only happen in your KeyListener,
> which will run on the event dispatch thread.  So it cannot happen until
> your read returns.  You would have a deadlock.  You may want to add a
> safeguard like the following:
>
>     if ( EventQueue.isDispatchThread() ) {
>         throw new IOException(
>             "Pl0InputStream.read() called from event dispatch thread" );
>     }
>
> You require a JTextArea as the input component, but I do not see anything
> that would require that specific component.  You could change this to a
> JTextComponent and make it a little more general.
>
> Have you considered how your component / input stream will behave if
> someone tries to back up using the arrow keys and edit the text in the
> text component.  I am not sure how you will be using the text component,
> but my guess is that it will not behave as you would like.  You may want
> to consider catching just the ENTER key, and then stuffing the current
> line into the input buffer.  That would allow the user to edit the input
> and to repeat previous lines.

I thought about this, but the only solution that comes to mind is to write a
highly customized version of JTextArea (or write my own Document class)
which limits where you can input the text. Since it's only a small project,
i don't think this makes sense. Maybe i'll try some hack like you described
above, but for now i'm more interested in getting the InputStream to
actually work :)

> I hope this helps.
>
> --
> John P. McGrath
> <JPMcGrath@fast.net>
> <jpm@nscs.fast.net>

Thanks!

Jeroen
Technical Details
Message-ID: <8i7tuh$msd7@bornews.borland.com>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <8i5dnc$j27@bornews.borland.com> <MPG.13b0e12eea71f5b29899c5@forums.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 111d45,ed9d203ce9e9692c
X-Google-Attributes: gid111d45,public
From: "Jeroen Zwartepoorte" <Jeroen@xs4all.nl>
Subject: Re: Redirecting System.in
Date: 2000/06/14
Message-ID: <8i7tuh$msd7@bornews.borland.com>
X-Deja-AN: 634412969
References: <8i5dnc$j27@bornews.borland.com> <MPG.13b0e12eea71f5b29899c5@forums.borland.com>
X-Priority: 3
X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6700
Organization: Another Netscape Collabra Server User
X-MSMail-Priority: Normal
Newsgroups: borland.public.jbuilder.java.swing