Explanation regarding skipping of alternate lines while reading from a file? - java

I just want to know, have I interpreted the code in right manner?
The file Bharath.txt has the following content:
Hello ! B . We created your file succesfully . We have updated you file , Sir ! Bharath Nikhil Friends Indeed
Consider the below code:
import java.util.Scanner;
import java.io.*;
class FilInpStr
{
public static void main(String arg[]) throws Exception
{
FileInputStream obj=new FileInputStream("Bharath.txt");
Scanner input=new Scanner(obj);
String n="";
while((n=input.nextLine())!=null)
{
System.out.println(n);
}
}
}
The above code works well this way. But when I do not consider storing input.nextLine() in a String, it begins to skip line alternatively. Is it that it is taking even the Enter from keyboard as input?
So, when I press Enter, it is passing the escape sequence too, as an input, which is why it is skipping one and printing the other?
And another doubt was regarding the while loop: is that one line wasted while comparing whether it is null or not?
Bharath
Nikhil
Friends Indeed
So, when I quote:
while((input.nextLine()) != null)
{
System.out.println(input.nextLine());
}
It will check whether Bharath==null or not, and if not, it will only then print Nikhil? And post Nikhil, it will skip next line, because it takes Enter as an escape sequence.
Please, correct me! I might have mixed up two different approaches. A beginner hence.
Also, do mention in distinction the difference between passing the input.nextLine() into a String, and as standalone code.

But , when I do not consider storing " input.nextLine()" in a String , it begins to skip line alternatively . Is it , that , it is taking even the ENTER from keyboard as input ?
Well no, it's just reading the next line every time you call input.nextLine(). That shouldn't be surprising. Ignore escape sequences etc. For the sake of simplicity, assume that input.nextLine() is just reading from a list of strings somewhere... it has a cursor showing where on the list it is. Every time you call input.nextLine(), it returns the current line and moves the cursor down.
If you call input.nextLine() twice in each iteration (once in the while condition and once inside the body) then you'll only execute half as many iterations as if you call it once per iteration (as per your original code).

input.nextLine()
Does two things :
Return the value of the current line
Advance the cursor past the current line
Scanner.nextLine()
Advances this scanner past the current line and returns the input that
was skipped.
So, if you don't store the result of input.nextLine(), it will be lost.
Each call to input.nextLine() advances past the current line, so each call will read a different part of the input.

The issue in the second snippet isn't the storing, but the fact you call nextLine() twice in each iteration. First, you call it in the while loop - the line is read and is then ignored (i.e., not saved anywhere), but the internal cursor of the input stream is advanced to the next line. Then, in the println line, you read another line and return it to System.out.println, effectively having all the odd-numbered lines just ignored.

Related

Why does sc.next() or sc.nextLine() not work inside a loop?

Question
Every line of input will contain a String followed by an integer.
Each String will have a maximum of 10 alphabetic characters, and each integer will be in the inclusive range from 0 to 999
Output Code
In each line of output there should be two columns:
The first column contains the String and is left justified using exactly 15 characters.
The second column contains the integer, expressed in exactly 3 digits; if the original input has less than three digits, you must pad your output's leading digits with zeroes.
Check out this link for more info:
hackerrank/challenges/java-output-formatting
This is the code(Java) I wrote:
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("================================");
for(int i=0 ; i<3 ; i++){
String s1=sc.next();
int x=sc.nextInt();
System.out.printf("%-15s%03d\n",s1,x);
}
System.out.println("================================");
}
}
My exact doubt/question
While the above code compiled and ran perfectly, I decided to make some changes and try out something different. I added the following line of code just after the line
int x=sc.nextInt();
The line that I added was:
sc.next();
However, after adding that line of code, the program would no longer accept input after the first line. That is only the first line of input would be printed and the next line ignored(not printed).
I changed the code sc.next() to sc.nextLine() but now the program would only print the first 2 lines and skip printing the last line(the code I wrote should accept 3 lines of text and print those three lines to standard output using printf).
Could anyone please explain why this is happening?
I read online that if I have to read a string after reading integer using next() and nextInt() respectively, then I need to add an extra next() or nextLine() call after reading the integer and before reading the string.
(This is to move the scanner to the next character as the escape character was ignored by nextInt()).
In my program, during the first iteration of the loop, the last reading from the standard input happens while reading the integer. At the beginning of the second iteration string is the first to be read. Hence noticing this I made the changes and the program didn't run as planned. However if I remove the extra read in between, the program works perfectly.
Could anyone please explain why this is happening?
Thanks in advance
If you put sc.next() after your code, Scanner will read and consume the next string, then your loop will start from the integer of the second line--that's why it's not working correctly. Now if you put sc.nextLine(), it will read and consume the next line, so your loop will start with the third line, and that's why you have two lines only. You shouldn't use sc.next() or sc.nextLine() after your loop; just leave it as it is.

Java scanner.hasNextInt() explanation?

I need explanation about how does scanner's hasNextInt() works. In next example:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean foo = sc.hasNextBoolean();
System.out.println(sc.nextLine());
}
when program gets to hasNextBoolean(), it waits for my input. Then I press Enter for newline and type true and press Enter again,so the buffer looks like this: [ \n true \n ].
Now the pointer is on word true, and so foo becomes true. But then, the pointer should still be hanging on true, and when next line comes, program should print true, but what happens is that it just prints newline. Why is that case, may I ask?
On the other hand, doing same thing but using nextInt(), works the way that i expected:
public static void main(String[] args) {
Scanner skener = new Scanner(System.in);
try{
int stagod = skener.nextInt();}
catch(Exception e){
System.out.println(skener.nextLine());}
}
Here when program come to skener.nextInt(), I press Enter then type A then press Enter, so the buffer looks like this: [ \n A \n ].
And now, after catching the exception, pointer stays on A and System.out.println(skener.nextLine()); prints A.
sc.hasNextBoolean() is working just fine. The problem is that you failed to account for sc.hasNextBoolean() not advancing past the input that it reads.
sc.hasNextBoolean() reads the input but does not advance past it. So after that call, the input buffer would be "\n", one line. sc.nextLine() DOES advance the scanner past the input after reading it. But in this case, it also waits for the user to enter another line. For you, that would be "true\n" which would make the buffer "\ntrue\n" as expected. But the buffer is 2 lines long. sc.nextLine() only reads one line (the next line). That next line is "\n", it's just a line break. After the System.out.println() call. There is still data in the buffer, which is now "true\n". There's still one line left.
You will find that if you add one more System.out.println(sc.nextLine()), your code will work as expected.
The reason why sc.nextInt() works is because it DOES advance the scanner past the input it reads. It waits for a line of input and then reads it. At this point, the buffer is "\n". But then it also advances past that input that it just read, so the buffer is now empty. The next time you call sc.nextLine(), the scanner is at the position before the line you type, rather than a line behind. So you only need one call to sc.nextLine().
The key to your problem is not that the Scanner methods aren't working as expected. Your problem is simply that your failed to consider that one minor, but crucial, detail about the Scanner.hasNextBoolean() method. There's little things in the documentation like that which can make or break a program. Next time, just remember to read the full documentation of the method you are using before you implement it.

How to keep spaces where they were after modifying string

So I have to get words from a text file, change them, and put them into a new text file.
The problem I'm having is, lets say the first line of the file is
hello my name is bob
the modified result should be:
ellohay myay amenay isay bobay
but instead, the result ends up being
ellomynameisbobhay
so scanner has .nextLine() but I want to have a method that is .nextWord() or something, so that it will recognize something as a word until it has a space after it. how can I create this?
nextLine() gives you the whole line.
What you should use is just next(), that will give you the next word.
Also see String.split() or StringTokenizer if you wanted to post-process whole lines. It sound s as though in your situation just using the scanner is fine, but I though i'd mention it because I assumed you'd have just used those methods if you knew about them.

java calculator randomly outputted line

So I've just started java with a tiny bit of experience from a few other languages. I tried to make this basic calculator and had a lot of problems but managed to resolve most of them. The last thing that I can't seem to understand is a randomly triggered "This is an invalid input", every time my program runs once. "..." refers to irrelevant code. Everything else seems to work fine. Thanks in advance!
import java.util.Scanner;
public class Calc {
...
System.out.println("Would you like to use the calculator?(Y/N)");
while(use){
String usage=in.nextLine().toLowerCase();
if(usage.equals("n")){use=false;}
//input
//operations
else if(usage.equals("y")){
...(calculator code)
System.out.println("Continue use? (Y/N)");
}
else {System.out.println("That is not a valid input");}
}
}
}
After running my code a few times, my output is
Would you like to use the calculator?(Y/N)
Y
Please input an operation: +,-,*,/,%, ^, or root
+
Calculator: Please input your first number.
1
Now enter your second number.
2
Calculating
3.0
Continue use? (Y/N)
That is not a valid input <-- right there is the confusing part, why is that triggered?
Y
Please input an operation: +,-,*,/,%, ^, or root
Full code is on pastebin, if you somehow need it. http://pastebin.com/Qee2Hxe3
I checked the full code, and right before the loop first reiterates, there is a call to in.nextDouble(), this method reads a double but does not consume the line end, which makes the next in.readLine() return \n immidiately and the succeeding test fails.
A simple solution is to manually consume the line-end:
System.out.println(ans);
System.out.println("Continue use? (Y/N)");
in.nextLine();
I tested your code and found that a solution is to declare your scanner inside your while loop, like so:
while (use) {
Scanner in = new Scanner(System.in);
String usage = in.nextLine().toLowerCase();
Here's what the problem is: first, you are entering your while loop, and usage is set equal to in.nextLine(). Since there is no next line, it waits for you to enter one. You enter yes, after which you enter your formula. Then it returns the answer, and goes back to the top of the while loop. Once again, usage is set to equal in.nextLine, but there is already a next line (a blank one) and so usage is set to equal an empty String ("") which is neither "y" or "n". Then it immediately goes to the "else" option at the end and prints the "invalid" message.
Re-assigning your scanner through each iteration of your while loop fixes this problem.
The last input you read in your code when calculating is this:
num2=in.nextDouble();
This reads the next characters and convert it to a double. However when you input your number, you also hit enter.
This means that after the double is read, there is still a newline character left in the input buffer.
As the code goes back to the String usage=in.nextLine().toLowerCase(); , you will now read this newline.
You could just ignore empty input, by e.g. doing
String usage=in.nextLine().toLowerCase().trim();
if (usage.isEmpty()) {
continue;
}

Java Substring match is failing

I am using a text file to read values from and loading this file into a buffered reader. thereafter i am reading the file line by line and checking if any of line contains one of my keywords (i already have them in a list of String).
However, even though the line contains the keyword i am looking for it does not detects it and gives it a Miss. Here is the code
for(int i=0;i<sortedKeywordList.size();i++)
{
String tempString=sortedKeywordList.get(i);
while(US.readLine()!=null)
{
String str=US.readLine();
//System.out.println(str);
if(str.contains(tempString)){
System.out.println("Contains: "+tempString);
}
else{
System.out.println("Miss");
}
}
}
For each keyword, you're iterating through your buffer using readLine(). So after your first keyword, you'll have exhausted your buffer reading and the next keyword test won't even execute since US.readLine() is giving you null. You're not re-initialising your reader.
So why not iterate through your file once (using your readLine() structure), and then for each line iterate through your keywords ?
EDIT: As Hunter as pointed out (above) you're also calling readLine() twice per loop. Once in your loop test and once to check each line for a keyword. I would first of all ensure you're reading the file correctly (simply by printing out each line as you read it)
You're calling US.readLine() twice!
Try instead:
String tempString;
String str;
for(...)
{
tempString = sortedKeywordList.get(i);
while((str = US.readLine()) != null)
{
...
}
}
You are calling US.readLine() once in the while loop entrance and again inside. This moves the input to the next line. Also, compare strings with .equals() and to check for substrings using .contains()
I'm seeing two major problems.
You've got your loops backwards.
The way you've written it, it looks at keyword1, and then looks through the whole input, checking for keyword1. Now, there's no more input, and it moves to keyword2, but there's no input left for it to check, so it quickly iterates through the rest of your keywords and quits.
You want to loop through the input, checking for each keyword, not through the keywords, checking each line of input.
while(input){
for each keyword {
...
You're calling .readLine() twice for each iteration, effectively skipping every other line.
Try storing the first line outside of the loop, checking for null in your loop condition, and then calling readLine juuust before the end of your loop.
The dataset in question would be helpful. Without it, a couple thoughts -
Verify the case of the sorted keywords matches case from the text file. If they are mismatched and you need to support case-insensitive matching, convert both strings to the same case (e.g., use toUpperCase()) then use the contains() call.
Verify no extra characters (like linefeeds/etc) appended the end of the sorted keyword.

Categories