My input txt file has this content:
aa1 aa2
bb1 bb2
cc1 cc2
After cursor is going to the last line, how does hasNextLine() method give true while reading cc1 and cc2? I thought I would only get aa1 to bb2.
Output:
aa1
aa2
bb1
bb2
cc1
cc2
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) throws FileNotFoundException {
File f = new File("K:\\Test\\a.txt");
System.out.println(f.exists());
Scanner reader = new Scanner(f);
while (reader.hasNextLine()) {
System.out.println(reader.next());
}
}
}
Either use hasNextLine() with nextLine(), or use hasNext(), with next(). Mixing those can result in undesired behavior (unless used deliberately). See their documentation here. Quoting the next() method:
Returns the next token if it matches the specified pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext(Pattern) returned true. If the match is successful, the scanner advances past the input that matched the pattern.
And also, in the Scanner class documentation, you can find this:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
So, the scanner reads the first line, it advances to the first delimiter (the white space) and prints the first part (aa1). Then, still on the same line, it prints the second part (aa2). Then, it moves to the second line, prints (bb1), then it prints (bb2), and still the while condition is true, since there is also a next line. So, finally, at the third line, it prints the first part (cc1), it prints the second part (cc2) and then stops, since there is no other line.
Related
This question is linked to a previous question I asked regarding the same program, which can be viewed here:
Writing to a file code causing an endless loop
I have fixed the problem above and rewritten the function as a while loop rather than do while, but now I have the opposite problem that nothing is being written to the file. I've inserting a print statement to tell me the status of hasNextLine, and it is always returning as true even when a blank line has been entered, which is when I want the writer to terminate.
Here is the updated code:
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.PrintWriter;;
public class Lab_Week8_WriteAStory {
public static void main(String[] args) throws FileNotFoundException {
Scanner whatToWrite = new Scanner (System.in);
PrintWriter writing = new PrintWriter ("Read and Write Files/output.txt");
while (whatToWrite.hasNextLine()){
String writeToFile = whatToWrite.nextLine();
writing.println(writeToFile);
System.out.println (whatToWrite.hasNextLine());
}
writing.close();
whatToWrite.close();
}
}
Check the documentation for Scanner.hasNextLine():
Returns true if there is another line in the input of this scanner. This method may block while waiting for input. The scanner does not advance past any input.
This is what's happening. Since you are using System.in as input source, the method is waiting for your input and once you provide it, it returns true and proceed to the next line and the process repeats itself.
Scanner kb=new Scanner(System.in);
System.out.println("\nDo you want to continue");
char answer=kb.next().charAt(0);
if(Character.toUpperCase(answer)=='Y') {
System.out.println("\nType any message to get Value");
String input=kb.nextLine();
class2 obj=new class2(input);
System.out.println("\n"+obj.getValue());
}
My program is not passing input to class2, it's just executing my method with empty input. I just tried every method, but none are working.
This will be solved by changing
char answer = kb.next().charAt(0);
to
char answer = kb.nextLine().charAt(0);
This is the solution because the next() method in Java does not advance the Scanner to the next line while nextLine() does.
You have two options:
1) make char answer=kb.nextLine().charAt(0);
2) make String input=kb.next();
Option 1: If you make it nextLine() it will consume the whole line and moves the cursor to next line. Thus there is no remaining string to be consumed.
Option 2: next() only consumes line till it finds a space and also it does not advances cursor to the next line. Thus for the first input if you type "yopo" the nextLine() will consume the remaining blank and you will not get anything.
In your case you should prefer the 1st option.
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.
why does this piece of code go into an infinite loop when I try to give it a basic text file?
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class TestFile
{
public static void main(String args[]) throws IOException
{
// Read in input file
File input = new File(args[0]);
Scanner freader = new Scanner(input);
while (freader.hasNextLine()) {
System.out.println("hi");
}
freader.close();
}
}
The print line just keeps going.
Because hasNexLine() does neither get the line nor change the state of the scanner. if it's true once, and no other methods of the scanner are called, it'll always be true.
Because you have to consume the nextLine so the code should be:
while ( theScanner.hasNextLine() ) {
String theLine = theScanner.nextLine();
}
If you don't invoke nextLine() you will always be watching at the same line and it will always answer true to that.
Add a call to nextLine or any other Scanner method that'll read in some input inside the while loop.
At the moment you're just repeatedly calling hasNextLine (which only returns a boolean, it doesn't modify the stream) without retrieving any input from freader, so if freader initially has another line within its input hasNextLine will always return true and your loop is essentially while (true).
In java i would like to read a file line by line and print the line to the output.
I want to solve this with regular expressions.
while (...)
{
private static java.util.regex.Pattern line = java.util.regex.Pattern.compile(".*\\n");
System.out.print(scanner.next(line));
}
The regex in the code is not correct, as i get InputMismatchException.
I am working on this regex for 2 hours. Please help with it.
With regex powertoy i see that ".*\n" is correct. But my program runs incorrectly.
The whole source is:
/**
* Extracts the points in the standard input in off file format to the standard output in ascii points format.
*/
import java.util.regex.Pattern;
import java.util.Scanner;
class off_to_ascii_points
{
private static Scanner scanner = new Scanner(System.in);
private static Pattern fat_word_pattern = Pattern.compile("\\s*\\S*\\s*");
private static Pattern line = Pattern.compile(".*\\n", Pattern.MULTILINE);
public static void main(String[] args)
{
try
{
scanner.useLocale(java.util.Locale.US);
/* skip to the number of points */
scanner.skip(fat_word_pattern);
int n_points = scanner.nextInt();
/* skip the rest of the 2. line */
scanner.skip(fat_word_pattern); scanner.skip(fat_word_pattern);
for (int i = 0; i < n_points; ++i)
{
System.out.print(scanner.next(line));
/*
Here my mistake is.
next() reads only until the delimiter,
which is by default any white-space-sequence.
That is next() does not read till the end of the line
what i wanted.
Changing "next(line)" to "nextLine()" solves the problem.
Also, setting the delimiter to line_separator
right before the loop solves the problem too.
*/
}
}
catch(java.lang.Exception e)
{
System.err.println("exception");
e.printStackTrace();
}
}
}
The beginning of an example input is:
OFF
4999996 10000000 0
-28.6663 -11.3788 -58.8252
-28.5917 -11.329 -58.8287
-28.5103 -11.4786 -58.8651
-28.8888 -11.7784 -58.9071
-29.6105 -11.2297 -58.6101
-29.1189 -11.429 -58.7828
-29.4967 -11.7289 -58.787
-29.1581 -11.8285 -58.8766
-30.0735 -11.6798 -58.5941
-29.9395 -11.2302 -58.4986
-29.7318 -11.5794 -58.6753
-29.0862 -11.1293 -58.7048
-30.2359 -11.6801 -58.5331
-30.2021 -11.3805 -58.4527
-30.3594 -11.3808 -58.3798
I first skip to the number 4999996 which is the number of lines containing point coordinates. These lines are that i am trying to write to the output.
I suggest using
private static Pattern line = Pattern.compile(".*");
scanner.useDelimiter("[\\r\\n]+"); // Insert right before the for-loop
System.out.println(scanner.next(line)); //Replace print with println
Why your code doesn't work as expected:
This has to do with the Scanner class you use and how that class works.
The javadoc states:
A Scanner breaks its input into tokens
using a delimiter pattern, which by
default matches whitespace.
That means when you call one of the Scanner's.next* methods the scanner reads the specified input until the next delimiter is encountered.
So your first call to scanner.next(line) starts reading the following line
-28.6663 -11.3788 -58.8252
And stops at the space after -28.6663. Then it checks if the token (-28.6663) matches your provided pattern (.*\n) which obviously doesn't match (-28.6663). That's why.
If you only want to print the file to standard out, why do you want to use regexps? If you know that you always want to skip the first two lines, there are simpler ways to accomplish it.
import java.util.Scanner;
import java.io.File;
public class TestClass {
public static void main(String[] args) throws Exception {
Scanner in=new Scanner(new File("test.txt"));
in.useDelimiter("\n"); // Or whatever line delimiter is appropriate
in.next(); in.next(); // Skip first two lines
while(in.hasNext())
System.out.println(in.next());
}
}
You have to switch the Pattern into multiline mode.
line = Pattern.compile("^.*$", Pattern.MULTILINE);
System.out.println(scanner.next(line));
By default the scanner uses the white space as its delimiter. You must change the delimiter to the new line before you read the line after the first skips. The code you need to change is to insert the following line before the for loop:
scanner.useDelimiter(Pattern.compile(System.getProperty("line.separator")));
and update the Pattern variable line as following:
private static Pattern line = Pattern.compile(".*", Pattern.MULTILINE);
Thank everybody for the help.
Now i understand my mistake:
The API documentation states, that every nextT() method of the Scanner class first skips the delimiter pattern, then it tries to read a T value. However it forgets to say that each next...() method reads only till the first occurrence of the delimiter!