Read large input through Scanner - java

I am trying to take some user input and process them in my program. For that using the Scanner class as below.
Scanner scan = new Scanner(System.in);
System.out.print("Input : ");
String input = scan.nextLine();
// Process the Data
scan.close();
The program works fine with small amount of data. But if the input string length is huge (~100K characters), Scanner stops responding and fails to read any data.
Is there any different way or workaround to this problem ?
Note : These is no possible way to store the data in a file and read from there. It would be a nice option to read chunks of data from a file. But unfortunately there is no such implementation in my application.
EDIT : As mentioned earlier, I need to read data directly from user (not from a file). Anyway, already tried to use the BufferReader. But does not seem like can read some data of around 100K characters.
Here is the code below.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Input : ");
String input = br.readLine();
// Remaining Code

Well this behavior might be normal, you'll have to wait for a moment before the Scanner code does anything. It's a big input and I guess the OS has to put it somewhere, so there is certain amount of time between the moment you press enter and the moment the JVM can read it.
You should benchmark it to see how much reading time evolves depending on you input.
I've made a code that read character per character from input. It is not a good solution as it surely is slower (and dirtier) than using nextLine(), but it will show how fast is the buffering and reading on your computer:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Log.d("Input : ");
StringBuilder test = new StringBuilder();
String input = "";
long measure = 0;
while(input != null){
input = scan.findInLine("."); // Should consume input one char per one char.
measure++;
if(input != null)
test.append(input.charAt(0));
if(measure == 1 || measure % 1000 == 0) // displays the reading time of first reads and the next thousand ones
Log.d("Reading at:"+measure);
}
Log.d("End");
scan.close();
Log.d("size: "+test.toString().length());
}
}
(note: you can replace Log.d(yourString) by System.out.println( new Date() +":" +yourString ) )
Test with this on your computer and gradually increase the input. I'm not sure the response is linear. It works well with 50000 char but it's in fact quite long with 100.000 (still, only a few minutes before I can read the first character).
edit: the time between reads also increases with input size ... it takes 80 seconds for 1000 char reads with an 100.000 chars input (and a few seconds with 50.000). At this rate, it will take more than 2 hours to read everything.
I'm not sure, looping on System.in.read(); might have better results (I don't know what the line end character is however ... \EOF maybe ?), but you can still try that too. Again, I don't think it's a good solution, but reading from the comment, it's all you got left.

Related

How can I make it so my program, for each word read in a string, also reads the following word?

I want my Java program to do the following thing:
Whenever it reads a file like the following
Bob went to the store to buy apples.
To read each word in the string (delimited by only a single space character) and to also read the next word, but without "moving" the main reader as well. So it would do something like this:
for word in string{
print word + nextWord;
}
And its output would be
Bob went
went to
to the
the store
store to
to buy
buy apples.
Edit: IMPORTANT! I don't want to read the whole file and load it into memory. I want this operation to happen DIRECTLY on the file. Imagine I am dealing with something huge, like a whole book, or more.
No. Scanner doesn't let you peek at future input.
However, it's trivial to code:
Scanner s = new Scanner(new FileInputStream("myfile.txt");
String previous = s.next();
while (s.hasNext()) {
String next = s.next();
System.out.println(previous + " " + next);
previous = next;
}

Java Scanner or Buffered Reader

I have a requirement where I will have to read inputs from console not from file
The input format is as below.I understand I can use any character to exit .But i cannot give any other input than this.Can i write some thing like wait for a specific amount of time and if there is no input break the loop or else what else can be done to read input whose length we never know before hand.
Hello,Agnes
Minion,Bedo
Vector,Shrink Ray
This following logic will make the readline wait forever for the input and wouldn't help because every enter I press will again be another input character and it never ends.
I neither wanna give any exit character to determine end of input like "exit". How to handle this??
ArrayList<String> emp=new ArrayList<String>();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
h=br.readLine();
while((h=br.readLine()) != null)
{
emp.add(h);
}
You could add a thread that requests the users input, and then a Timer that's started over on each new input. When the timer expires, it shuts the user input thread down.
Scanner reader = new Scanner(System.in);
System.out.println("Enter something: ");
String s=reader.nextLine();
System.out.println("You enetered: " + s);
Which results in:
Enter something:
Mike,Elofson
You enetered: Mike,Elofson
Generally speaking, and from my experience, scanners are easier and more commonly used for input.
How about a "" input(namely press Enter directly), or two/three consecutive "" inputs.
I don't think waiting for some time is a good idea. Anyway, you need some input to indicate the end.

findWithinHorizon(".",0).charAt(0) Clarification

I'm having trouble understanding the source below:
myChar1 = myScanner.findWithinHorizon(".",0).charAt(0);
System.out.println(myChar1);
myChar2 = myScanner.findWithinHorizon(".",0).charAt(0);
System.out.print(myChar2);
I understand what it does, but I'm just having a bit of a trouble understanding how it works.
The actual prompting of the user for input is done at the first line right? but the real meaning of the first line is: "put the first char of input in myChar1". Then what happens? It seems the input still stays inside myScanner because when I use it in myChar2 I get the second char, but why? why not the first char? Does findWithinHorizon(".",0).charAt(0) deletes the char that is assigned to the variable?
And last question: if in the first line the program prompts the user for input why doesn't it do it again in the second line?
Also, a quick recap of the (".",0) would be helpful as well.
Perhaps the piece you are missing is that findWithinHorizon actually takes a regular expression as the String argument. In a regular expression, . matches any character (except a new line).
A call to findWithinHorizon(".", 0) simply finds the next character in the input and advances the Scanner past whatever was found.
So for example,
Scanner in = new Scanner("abc123");
for(;;) {
String found = in.findWithinHorizon(".", 0);
if(found == null) break;
System.out.println(found);
}
the output is:
a
b
c
1
2
3
The reason it does not prompt for input at the second line is that is the way Scanner and System.in work together. They will only block and prompt for input if there is no more existing input to consume. As a short example, try this out:
Scanner in = new Scanner(System.in);
while(true) {
System.out.println(in.findWithinHorizon(".", 0));
}
That will loop infinitely, repeating back whatever you input, character by character. It will only prompt for more when it's done with the prior input. On the first iteration, Scanner will call read on System.in which will block and wait for input. When the input runs out, read will block again.

Reading lines of input from user using SCANNER

I have a program that needs to read lines of input. It needs to be many lines at once. For example:
As I enter my time machine or
maybe not,
I wonder whether free will exists?
I wonder whether free will exists
maybe not
as I enter my time machine or.
That all gets entered at one time by the user. I was trying to use .hasNextLine() method from Scanner class, but it is not returning false.... it waits for input again. Ive been looking around for a solution and it appears that .hasNextLine() waits for input, but i do not know what alternative to use. Any suggestions? The actual code looks like:
while(input.hasNextLine());
{
line += input.nextLine();
}
Thanks for your help
Perhaps you should use some sort of "stop" sequence meaning when the user enters a particular character sequence, it will break out the loop. It might look something like:
public static void main(String args[]){
final String stopSequence = "/stop";
final Scanner reader = new Scanner(System.in);
String input = reader.nextLine();
while(!input.equalsIgnoreCase(stopSequence)){
//process input
input = reader.nextLine();
}
}

hasNext() - when does it block and why?

I'm trying to read commands via a Scanner Object. For checking the Input Syntax I use sc.hasNext() (for the case of missing commands). It did work fine for many cases already, but now I have the case that's described in the JavaAPI as "MAY block and wait for Input".
When does the hasNext() method block and how can I control it? The funny Thing is that it work's perfectly fine with 3 cases before the block. Also the JavaAPI describes hasNext() as the proper method for checking wether there is another Input or not so that the Method next() doesn't produce an Exception.
Here is the code I did produce till now:
if (sc.hasNext() && sc.next().equals("create")) {
if (sc.hasNextInt()) {
width = sc.nextInt();
if (width > 0) {
if (sc.hasNextInt()) {
heigth = sc.nextInt();
if (heigth > 0) {
if (sc.hasNext()) { //At this point the hasNext Statement blocks for //no reason till an Input is made.
charset = sc.next();
Image = new AsciiImage(width, heigth,charset);
} else {
ret = false;
System.out.println("INPUT MISMATCH");
}
} ...//and so on
Thanks in advance, I couldn't find anything on this Topic an my own.
Edit: The Scanner is defined as a System.in, but that shouldn't be a Problem - at least it hasn't been one till now.
There is a difference between testing via Console or via TextFile. If I read from Console the program expects a Stream and it will wait for further Input.
When testing via Input from Textfile (still with System.in for the Scanner, using Java Program ) the hasNext() will return false at the end of the file as no further Input can be done.
I can't really find documentation (in https://docs.oracle.com/javase/9/docs/api/java/util/Scanner.html#hasNext--) on this Topic. So if anyone finds a proper and technical correct answer I would be very greatfull.
If you have nothing else to do while waiting for user input, then it's fine to be blocked at that call until the next input arrives.
If you do want to run other code while waiting for input, spawn a new thread and call hasNext and other blocking scanner methods from there.
I'm not sure , but the following is my own experience :
when the Scanner object is fed with a file , it will not be blocking !
By the term "fed with a file " I mean that the scanner is constructed like this : Scanner scanner = new Scanner("myFile.txt");
But if the scanner is constructed using the getInputStream()method of a Socket object , like this :
input = socket.getInputStream();
Scanner scanner = new Scanner(input);
the scanner will be blocking !

Categories