Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4071281
Votes 103
Synopsis java.io.BufferedReader.readLine: Does not work well with System.in on Win95
Category java:classes_io
Reported Against 1.1.3 , 1.1.4 , 1.1.5 , 1.1.6 , 1.1.7 , merlin-beta2
Release Fixed
State 11-Closed, Will Not Fix, bug
Priority: 4-Low
Related Bugs 4080163 , 4092733 , 4093424 , 4123004 , 4523764
Submit Date 12-AUG-1997
Description




import java.io.BufferedReader;
import java.io.InputStreamReader;
class Test {
   public static void main(String args[]) throws Throwable {
      BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
      String s;
      while ((s = inReader.readLine()) != null) System.out.println(s);
   }
}
Then, typing in "Line 1"..."Line 9"
should result in duplicates e.g.
Line 1 // input
Line 1 // output
Line 2 // input
Line 2 // output
etc. but they come out as e.g.
Line 1 // input
Line 2 // input
Line 1 // output
Line 2 // output
(this varies?!)

======================================================================
  xxxxx@xxxxx   1997-09-09
Another example of this bug
he following sample program illustrates
the problem (file - Test.java):

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

class Test {
	public static void main (String[] args) {
		BufferedReader buf;
		InputStreamReader inp;
		
		buf = new BufferedReader(new InputStreamReader(System.in));
		String line = "";
		int count = 1;
		
		while (!line.equals("exit")) {
			System.out.print ( count + "> ");
			System.out.flush();
			try {
				line = buf.readLine();
			}
			catch (IOException ex) {
				System.out.println (ex.getMessage());
			}
			count++;
		}
	}
}


The program basically just reads and prints 
lines typed in. If you type slowly, you get the 
expected behaviour:
c:\test>java Test
1> a
2> b
3> c
4> d
5> e
6> f
7> g
8> exit

If you enter data quicker you may get, for example,
c:\test>java Test
1> a
b
2> 3> c
4> d
e
5> 6> f
g
7> 8> exit

The input seems to be buffered, but readLine is not 
detecting the EOL until another CR-LF is sent.

This doesn't seem to happen under Solaris.
It may be another manifestation of bug #4071281.



==============================================================================

Yet another report, which unlike the previous reports asserts that
DataInputStream works fine.  --   xxxxx@xxxxx   8/3/1998



Subject: BufferedReader problem
Date: Wed, 15 Jul 1998 23:05:38 +0100
 
I am using jdk1.1.6 and have experienced problems writing programs that
form part of the study of Professor Winder and Graham Roberts' book
"Developing Java Software" (published by Wiley ISBN 0-471-97655-5). I
attach two versions of one trivial program with their compilation and test
reports. The program merely reads integers from the keyboard and repeats
them back to the screen being terminated with an input zero. 

The test results of Ex166a (using BufferedReader) are mystifying, whereas
the results from Ex166b (using DataInputStream) are as expected.

Professor Winder is the head of the Computer Department at King's College
and I first referred the problem to him as he suggests using BufferedReader
in his book. He confirms that he obtains similar results. However he has
found that both programs run as expected on the Solaris platform, and has
suggested that the problem may lie with the interface between Window95 and
the JVM.

----

import java.io.*;

class Ex166a
    {public static void main (String[] arguments) throws IOException
        {int inno=1;
         String inChars="";
         BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
         while (inno!=0)
            {inChars=in.readLine();
             inno=Integer.parseInt(inChars);
             System.out.print("Input "+inno+"\n");
            }
        }
    }

/*

****       ***** Compilation:
  
C:\King's\Java\programs\Winder>javac Ex166a.java

C:\King's\Java\programs\Winder>

****       ****    Test results
C:\King's\Java\programs\Winder>java Ex166a
23
Input 23
34
Input 34
234
Input 234
231       The following lines were not put in rapidly ! but the program seems       
345            to get stuck whatever key is struck.
643
7554
4
5
0
434
Input 231
Input 345
Input 643
Input 7554
Input 4
Input 5
Input 0

C:\King's\Java\programs\Winder>
*/

----

import java.io.*;

class Ex166b
    {public static void main (String[] arguments) throws IOException,
                                                  NumberFormatException  
        {int inno=1;
         String inChars="";
         DataInputStream in=new DataInputStream(System.in);
         while (inno!=0)
            {inChars=in.readLine();
             inno=Integer.parseInt(inChars);
             System.out.print("Input  "+inno+"\n");
            }
        }
    }

/*

****    ****     Compilation:

C:\King's\Java\programs\Winder>javac Ex166b.java -deprecation
Ex166b.java:10: Note: The method java.lang.String readLine() in class java.io.Da
taInputStream has been deprecated.
            {inChars=in.readLine();
                                ^
Note: Ex166b.java uses a deprecated API.  Please consult the documentation for a
 better alternative.
2 warnings

C:\King's\Java\programs\Winder>

****    ****      Test results:

C:\King's\Java\programs\Winder>java Ex166b
12
Input  12
234
Input  234
32345
Input  32345
12
Input  12
67
Input  67
2
Input  2
3
Input  3
4
Input  4
67890
Input  67890
1234567
Input  1234567
0
Input  0

C:\King's\Java\programs\Winder>

*/
Work Around




1) Use the deprecated DataInputStream.readLine()
2) Don't use Windows 95 (works OK on NT 4.0)
======================================================================

With JDK 1.2, everything works fine as long as you wait for the program to
start up before typing at it.  --   xxxxx@xxxxx   9/14/1998
Evaluation
This is not a bug in JDK, but a Win95 bug. I was able to reproduce it on Win95
using both the native api and the c runtime library.  WinNT does not have this problem.

A small test shows this problem:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

void main()
{
    int i = 0;
    char buf[256];
    int length = 256;
    int len;
    
    for(; i < 100000000;i++) {
	/* do nothing, just waste some time*/
    }

    
    ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, length, &len, 0);
    //fscanf(stdin, "%s", buf);
    fprintf(stderr, "GOT %s\n", buf);
    ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, length, &len, 0);
    //fscanf(stdin, "%s", buf);
    fprintf(stderr, "GOT %s\n", buf);
    ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, length, &len, 0);
    //fscanf(stdin, "%s", buf);
    fprintf(stderr, "GOT %s\n", buf);
    ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, length, &len, 0);
    //fscanf(stdin, "GOT %s", buf);
    fprintf(stderr, "GOT %s\n", buf);
}

  xxxxx@xxxxx   1998-05-04


While this may be a Win95 bug, we really must try to find a workaround for
the JDK.  --   xxxxx@xxxxx   8/3/1998

Further research has produced no effective workaround for this Win95 bug.
Lowering priority to 4.  --   xxxxx@xxxxx   9/14/1998
Comments
  
  Include a link with my name & email   

Submitted On 06-NOV-1997
c23kab
It appears that by using the BufferedReader constructor that
allows the buffer size to be specified (instead of using the
constructor that sets the default size) and by setting the
buffer size to '1', the problem goes away:  BufferedReader
in = new BufferedReader(new InputStreamReader(System.in),1);
It acts as if the Windows '95 implementation uses full
buffering instead of line buffering and this will not work
for an interactive stream.  The readLine() documentation
certainly implies line buffering.


Submitted On 20-NOV-1997
stevenmz
Specify a buffer size of one byte in the constructor.
BufferedReader in = new BufferedReader(new FileReader(&quot;foo.in&quot;), 1)


Submitted On 22-NOV-1997
dorvocho
What is the point of having a buffer if you set
it's size to 1? Is this the same bug as 4093424?


Submitted On 28-FEB-1998
s_t_e_v_e
Looks like a duplicate of 4080163 to me.


Submitted On 09-APR-1998
ptomblin
Similar, but not identical (because it *doesn't* work on NT 4.0)
The following program works fine on Linux JDK 1.1.5, but on NT it
doesn't consume the input buffer at all, so when you control-C out,
everything you typed comes out as commands to the shell:
/* vim:set si sw=4 ts=4: */
import java.io.*;
import java.net.*;
import java.util.*;
public class ReadStdinNoThread
{
	public static void main(String[] argv) throws Throwable
	{
		BufferedReader	_is = new BufferedReader(new
									InputStreamReader(System.in), 1);
		PrintWriter		_ps = new PrintWriter(System.out, true);
		_ps.println(&quot;ready for input:&quot;);
		try
		{
			while (true)
			{
				String in = _is.readLine();
				if (in != null)
				{
					if (in.equals(&quot;.&quot;))
						break;
					_ps.println(in);
				}
			}
		}
		catch (IOException e)
		{
		}
		_ps.println(&quot;exiting&quot;);
	}
}


Submitted On 09-APR-1998
ptomblin
I withdraw my previous comment - turns out it works
fine with a regular DOS shell, it just doesn't work
with a Cygwin bash shell.


Submitted On 31-MAY-1998
jgf1
I don't think this is a bug in BufferedReader.readLine().
I also don't think it's a Windows API bug - it's quite possible to write 
console applications for Windows 95 in C or Java that don't suffer from 
this problem.  (Even if the API was faulty, it's the low level Java code's 
job to work round it - Java is meant to be portable and easy to code).
I think the bug is in System.in.available()

It seems that System.in.available() is returning an incorrect value for 
the number of characters that are ready and waiting to be read.  Quite 
often the return value is too large, such as being 1 when there is no data
available.  (Note that I haven't tested this with redirected input, just 
keyboard input.  Also this is all Win95 specific.)  
Here's some typical keyboard input code:
// Open standard (keyboard) input as a buffered character stream.
BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
String aLineOfText = stdin.readLine(); // get a line
The InputStream reader should, in this example, read a line at a time and 
pass it to the BufferedReader.  However, if two or more lines are available 
then it has been designed to read in everything at once for efficiency.  
Since it is sometimes being told (by System.in.available()) that there is 
another line ready when there isn't, it is asking for the second line and 
having to wait for the user to type it in, before the first line has been 
processed.

Workaround
~~~~~~~~~~
I've come up with a few workarounds.  Most elegent is to create a wrapper 
class for System.in that has the same type as System.in (by inheritance 
and polymorphism) and passes on every function call except available().
Since I can't find a way to get the correct value of System.in.available(),
I just return 0.  This is OK if you're just using a BufferedReader.readLine()
to read the data, but is obviously not ideal.
To use this class, wrap it around System.in.  For example, the code above
becomes:

// Open standard (keyboard) input as a buffered character stream.
BufferedReader stdin = new BufferedReader (new InputStreamReader (
                       new SystemInWrapper (System.in)));
String aLineOfText = stdin.readLine(); // get a line

This has the advantage of being portable - if you're using UNIX then the 
extra wrapper class will cause a slight slowdown, but not much.  
Here is the code for SystemInWrapper:

// SystemInWrapper.java
//
// By Jonathan Foster 1998
// Donated to the public domain.
//
// This class fixes the problems with newlines from System.in not being 
// acted on immediately, which is a symptom of the fact that 
// System.in.available() is unreliable, frequently claiming that characters 
// are available when they aren't.
//
// Instead of using this to read the keyboard:
//
// // Open standard (keyboard) input as a buffered character stream.
// BufferedReader stdin = new BufferedReader (
//                        new InputStreamReader (
//                        System.in));
//
// Use this code instead:
//
// // Open standard (keyboard) input as a buffered character stream.
// BufferedReader stdin = new BufferedReader (
//                        new InputStreamReader (
//                        new SystemInWrapper (
//                        System.in)));
//
import java.io.*;
public class SystemInWrapper extends InputStream
{
    private InputStream in;
    public SystemInWrapper (InputStream newin)
    {
        in = newin;
    }
    public int read() throws IOException
    {
        return in.read();
    }
    
    public int read(byte b[]) throws IOException
    {
        return in.read(b, 0, b.length);
    }
    
    public int read(byte b[], int off, int len) throws IOException
    {
        return in.read(b, off, len);
    }
    
    public long skip(long n) throws IOException
    {
        return in.skip(n);
    }
    
    public int available() throws IOException
    {
        return 0; // in.available() is unreliable, so assume that
		  // 


Submitted On 13-JUL-1998
lareed
You can add &quot;reported against 1.1.6&quot; to the list
but since it sounds like a Windows 95 problem it
may be a moot point.


Submitted On 31-JUL-1998
Dbr549
It seems that jgfl is on the right track. Looking atSystem.in points us to
InputStream.  The source code
for InputStream shows available simply returns 0,
and is intended to be overidden.
// from java source code.... see comment in original code
 public int available() throws IOException {
   return 0;
 }
Since this always returns zero, it seems redundant
to override this in jgfl's wrapper. Looking next
at InputStreamReader source we see this strangeness:
/**
* Tell whether the underlying byte stream is ready to be read.  Return
* false for those streams that do not support available(), such as the
* Win32 console stream.
*/
private boolean inReady() {
  try {
       return in.available() &gt; 0;
      } catch (IOException x) { 
        return false;
      }
   }
So, since InputStream.available always returns 0,
InputStreamReader.inReady must apparently always
return false??
Also, not being a Win95 wizard what does the comment
about Win95 console mean??




Submitted On 05-OCT-1998
jgf1
Dbr549 hasn't noticed that the type of System.in is NOT InputStream.  It's
actually some other class which is a subclass of InputStream, which can be
treated as an InputStream by polymorphism.  The actual type varies - it's a
networking class if I run it under the Jikes debugger, or a different class in
a console window.  These classes override available() so that it can return
non-zero.  (To demonstrate this, do &quot;System.out.printf(System.in);&quot;
and observe the result)
The comment in the JDK source that Dbr549 quoted implies that when this code
was written Sun had a perfectly good solution to this problem.  It suggests
that the Win32 console streams should be throwing an IOException when their
available() method is called.  There is already code in the JDK to silently
handle the exception, and this is probably the easiest way for Sun to fix this
bug.  It doesn't require Sun to write a &quot;real&quot; System.in.available(),
or any API changes.
It isn't a perfect fix - a &quot;real&quot; System.in.available() would be very
nice, but one that just throws an exception would work with most programs, and
those programs that fall over when System.in.available() throws an exception
would probably be affected by the existing bug anyway.  


Submitted On 01-NOV-1998
dconry
I've had problems with the available() method using
all types of input streams under Win95.  Under Unix
it seems to work fine, but when reading a string typed
from a DOS window it always originally returns 2.  If 
you read two bytes and call it again, it returns the
length of the remaining String.  Puzzling.
I usually just call available and read twice to read 
each line.  I've found setting the buffer size to 1
takes care of readLine() pretty well, although of
course this removes any performance advantage 
readLine might have had.


Submitted On 07-SEP-1999
mwoolley
I think jgf1 has analysed this problem perfectly. However, I would suggest a
simpler way of phrasing the workaround is to use an anonymous inner class
overriding FilterInputStream, ie
BufferedReader stdin = new BufferedReader (new FilterInputStream(System.in)
{
    public int available() throws IOException
    {
        return 0;
    }
});


Submitted On 20-SEP-1999
p.lavarre
Just now in the recognised Related Bugs there are 18, 1, 5, and 1 votes ...
suggesting this should be ranked higher among the Top 25 Bugs?


Submitted On 20-SEP-1999
p.lavarre
 I get the idea you're not supposed to try and use the console on Win95.
We have not only this issue relegated to &quot;priority 4&quot; but we also at
least have the &quot;closed, will not be fixed&quot; issue titled
&quot;System.err.println discards line after EOF keystroke&quot; at
http://developer.java.sun.com/developer/bugParade/bugs/4151071.html


Submitted On 04-NOV-1999
ltmiilr
A normal implementation of available(), based on
GetNumberOfConsoleInputEvents and PeekConsoleInput,
gets trapped by the following problem: After the line's contents
and the following CR have been read, available() will return
false, although the following LF byte is still in the input buffer.
A workaround for this problem is to have a &quot;boolean
ignore_next_LF&quot; in the input stream, which is set when a CR
byte is read (and converted to '\n') and cleared when any
other byte is read. And when you want to read a character
and it is LF and ignore_next_LF is true, you set it to false and
retry. This way, the function available() will be reliable.


Submitted On 08-NOV-1999
miles
the failure to provide an easy, reliable readLine for System.in 
was a major oversight from the beginning.
I ALWAYS have to look up how to do this.  (it's bad enough
you have to use TWO subclasses to get at readLine, then
javasoft changed the whole layout between java 1.0 - 1.1.)
Why are System.in &amp; System.out so asymmetrical in 
functionality?  
Inputting a line is a common test case.  
We really SHOULD have had
System.in.readLine()
all along.  The c example is dandy, but how about 
   char *str;
   gets(str);
At least the c libraries did this more elegantly.
 -= miles =-


Submitted On 06-DEC-1999
Parkway
One aspect of the problem is due to Sun's use of WaitForSingleObject to see if
input is
available. Firstly, this API only works with ReadConsole, not with ReadFile, so
that it will
indicate non-typing events such as shift and control keys. Secondly, this API
is broken
on Windows 95 and will never reset to indicate that no input events are
available.


Submitted On 08-MAR-2000
p.lavarre
I see here we're up to 85 votes = 60 + 18 + 1 + 5 + 1 if we 
counted this together with its recognised Related Bugs.

I'd say even more bugs fall under &quot;console does not work&quot; 
e.g. the closed-and-will-not-be-fixed 
http://developer.java.sun.com/developer/bugParade/bugs/41510
71.html
says you can't trust System.err to trace execution reliably 
if you also use System.in for input.

&gt; gets(str);

Having a bug in Sun Java Windows System.in readLine 
disappoints me so intensely in part because I'd like to get 
away from code like C gets.  That routine is sweet poison: 
if the supplier of input happens to enter more chars than 
(sizeof str) then suddenly my program is writing storage 
maybe it does not own, whoops.

ANSI C gave us stdio.fgets to limit the size of an entry, 
Sun Java gives us more robust code to use with files, but 
this supposedly more robust code breaks down if used with 
an interactive stream like the Windows System.in stream.



Submitted On 07-DEC-2000
p.lavarre
The BugParade vote to supply console i/o that works is up 
to 103 = 78+18+1+5+1 now.  (An off-topic post in a *java* 
Usenet group inspired me to check.)


Submitted On 06-FEB-2001
ChennaR
I am getting java.exe error while running a client program, consists of bufferReader. 


Submitted On 30-MAY-2001
j-son
There's a known bug in Visual C++ 6.x (and 5.x?) with
getline( cin, ...); this may have something to do with the
described problem if the JDK native libraries were compiled
with VC++. See

http://support.microsoft.com/support/kb/articles/Q240/0/15.ASP?LN=EN-US&SD=gn&FR=0&qry=getline%20cin&rnk=2&src=DHCS_MSPSS_gn_SRCH&SPR=VCC

This even proposes a C++ workaround; perhaps this can be
worked around in Java instead?


Submitted On 16-JUN-2001
p.lavarre
I don't yet see a cross-ref here to:

"java.io: Add support for non-blocking I/O"
http://developer.java.sun.com/developer/bugParade/bugs/40750
58.html

Mind you, that bug Sun has now closed in favour:

"JSR-51: New I/O APIs for the JavaTM Platform"
http://java.sun.com/aboutJava/communityprocess/jsr/jsr_051_i
oapis.html



Submitted On 22-JUN-2001
p.lavarre
I see here we're up to 118 votes = 93 + 18 + 5 + 1 + 1 if 
we counted this together with its recognised Related Bugs.


Submitted On 22-JUN-2001
p.lavarre
> > WED MAY 30 03:18 P.M. 2001
> > j-son
> > 
http://support.microsoft.com/support/kb/articles/Q240/0/15.A
SP?LN=EN-US&SD=gn&FR=0&qry=getline%
20cin&rnk=2&src=DHCS_MSPSS_gn_SRCH&SPR=VCC
>
> [In MS VC 6 ...]
> The Standard C++ Library template getline
> function reads an extra character
> after [EOL] ...

Ouch.  I hope this is not directly relevant.  I can believe 
getting confused over what System.in.available should say 
after reading the CR of a CR LF is part of what we're 
discussing here, per the analysis and workaround in the web 
Comment here above stamped "SUN MAY 31 06:03 A.M. 
1998", "jgf1".

Strange that the Evaluation here above stamped "9/14/1998" 
claims there is "no effective workaround" ... I wonder 
what's wrong with the "... MAY 31 ... 1998" workaround 
claimed here?


Submitted On 22-JUN-2001
p.lavarre
Ahhhh, sorry to be so confused.  I think the closed-as-
duplicate-trail is corrupt here.  I now believe the root 
entry in the bugParade/ for:
        New I/O APIs for the JavaTM Platform
        http://jcp.org/jsr/detail/051.jsp
is:
        bugs/4286936.html

There I've just added as a web comment my claim that email 
from jsr-51-comments at jcp.org assures me we shouldn't 
read jsr/detail/051.jsp to suggest any intention of 
providing cross-platform console i/o that works even as 
well as the fgets/fputs of C.



Submitted On 14-FEB-2002
supalov
Hi!

Looks like Sun prefers to forget about Win 95 (and many
other Windows, I suppose). If a bug is still there since
August 1997 (I submitted a related one as late as November
2001!!!), something must be wrong.

And, frankly, effectively disabling the buffering may not be
considered a good workaround. It's just easier than to put a
flush after every write, but it's still UGLY as it defeats
the whole reason for having a buffer in the first place.

Best regards.

Alexander


Submitted On 03-JUN-2002
dconry
Closed, will not be fixed?  I guess Windows 9x isn't an important enough platform...


Submitted On 17-DEC-2002
p.lavarre
This bug is "closed, will not be fixed" with 103 votes.
I wonder how many of those votes would happily move to:

Improved interactive console I/O ...
http://developer.java.sun.com/developer/bugParade/
bugs/4050435.html


Submitted On 25-JUL-2007
minati
Please provide  me the code how to compare two file . Suppose there are 3 file.We compare file1 with file2 line by line(Row wise). Suppose i compare  logonid(unique) of file1 with file2. If logonid is match then copy the entire row  to file3. Please tell me the what is the code for it.



PLEASE NOTE: JDK6 is formerly known as Project Mustang