When I run my code it says that there is an InputMismatchException? Works for the two first read-lines, but hwne I try to read the int and double-lines it doesn't and the string-line doesn't actually read anything into the variable, it is empty as it doesn't print anything at the system.out.println(a +b)... Any tips?
import java.util.*;
import java.io.*;
class Uke55{
public static void main(String[]args){
Scanner input=new Scanner(System.in);
try{
PrintWriter utfil=new PrintWriter(new File("minfil55.txt"));
utfil.println('A');
utfil.println("Canis familiaris betyr hund");
utfil.println(15);
utfil.printf("%.2f", 3.1415);
utfil.close();
}catch(Exception e){
e.printStackTrace();
}
try{
Scanner innfil=new Scanner(new File("minfil55.txt"));
char a=innfil.next().charAt(0);
String b=innfil.nextLine();
System.out.println(a +b);
int c=(int)innfil.nextInt();
double d=(double)innfil.nextDouble();
innfil.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
That's because when you use next(), nextInt(), and nextDouble(), it doesn't go to a new line. Only newLine() moves the cursor to the next line. Do this:
try{
Scanner innfil=new Scanner(new File("minfil55.txt"));
char a=innfil.nextLine().charAt(0); //first error was here. calling next() only
//read A and not the \r\n at the end of the
//line. Therefore, the line after this one was
//only reading a newline character and the
//nextInt() was trying to read the "Canis" line.
String b=innfil.nextLine();
System.out.println(a +b);
int c=(int)innfil.nextInt();
innfil.nextLine(); //call next line here to move to the next line.
double d=(double)innfil.nextDouble();
innfil.close();
}
catch(Exception e){
e.printStackTrace();
}
next(), nextInt(), nextDouble(), nextLong(), etc... all stop right before any whitespace (including the end of a line).
That is because you have in file:
A\n
Canis familiaris betyr hund\n
15\n
3.14
Where \n represents new line character.
When you call first time
innfil.nextLine().charAt(0)
it reads A, and scanner reading points to first \n
Then you call
innfil.nextLine()
it reads till \n (nextLine() reads till \n and puts scanner reading pointer past \n), and makes reading pointer past \n. Reading pointer will be at C in next line.
Then you call
innfil.nextInt()
duh! scanner can't recognize Canis as integer, input mismatch!
According to the documentation on Scanner.nextLine() it
"Advances this scanner past the current line and returns the input that was skipped."
So, after calling char a=innfil.next().charAt(0); the "cursor" is at the end of the first line. Calling String b=innfil.nextLine(); reads until the end of the current line (where there is nothing left to read) and advances to the next line (where the actual String is).
Solution
You need to advance to the next line before calling String b=innfil.nextLine();:
...
char a=innfil.next().charAt(0);
innfil.nextLine();
String b=innfil.nextLine();
...
Note:
Although Scanner.nextInt() and Scanner.nextDouble() behave the same way as Scanner.next(), you don't face the same problem, because those methods will read the next complete token (where "A complete token is preceded and followed by input that matches the delimiter pattern") and white-space characters (such as newline-characters) are considered delimiters. So, those methods will automatically advance to the next line if needed, in order to find the next complete token.
Did you check something is actually written to your file? I doubt that. Try calling flush() before you close your PrintWriter. EDIT: sorry I was wrong here because I was thinking of the auto line flush.
Related
Consider the following java code which opens a file, reads all of the data, then tries to read one more line.
public static void main ( String[] argv) {
FileInputStream inFile = null;
try {
inFile = new FileInputStream("DemoRead.txt");
}
catch ( FileNotFoundException ex) {
System.out.println("Could not open file "+ ex.getMessage());
System.exit(0);
}
Scanner inputStream = new Scanner( inFile);
while ( inputStream.hasNext()) {
System.out.println( inputStream.nextLine());
}
System.out.println(inputStream.nextLine());
inputStream.close();
}
I would expect that the final inputStream.nextLine() would throw an exception as there is nothing else to read.
Indeed if I change the while loop to:
while ( true) {
System.out.println ( inputStream.nextLine());
}
It does throw an exception as expected.
This is not making any sense to me. Any insight would be appreciated.
hasNext() can return false before the end of the file if there are no more tokens left. This is the case when there are only delimiters left at the end of the file.
Compare this with hasNextLine(). If you're using nextLine() then the condition should be hasNextLine(). hasNext() is used with next().
1stly hasNext()--Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.But in case of while loop we always get true.
2ndly in case of nextLine()--Advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.
Since this method continues to search through the input looking for a line separator, it may buffer all of the input searching for the line to skip if no line separators are present.
so,in case of while(true) we are getting always true and at certain point the nextLine() method finds no line separator so gives exception, but in case of while(hasNext()) method it returns false when there is no token in the file so loop breaks so no Exception comes..
Hope this may help you out.
package mygradeloops;
import java.io.IOException;
public class MyGradeLoops {
public static void main(String[] args) throws IOException {
char x = 'A';
for (x='0';x<'9';x++){
System.out.println("Please enter in one of your grades.");
System.in.read();
System.out.println("Keep going!");
}
}
}
This code keeps double printing after the first "grade". Does anyone know why it double prints? Have I done the "For Loop" wrong?
It's "double printing" because when you enter a character by pressing return, you're actually writing two characters: the character you typed, and \n (newline character).
Add a second System.in.read(); call to read the newline character:
for (x='0';x<'9';x++){
System.out.println("Please enter in one of your grades.");
System.in.read(); // your character
System.in.read(); // newline
System.out.println("Keep going!");
}
Also, initializing x to 'A' in not needed, char x; is fine. In fact, it doesn't make sense to use a char in this loop, using an int would be preferred.
The read method for System.in (an InputStream) only reads one byte of data from the input stream. Because you must hit "Enter" to send your input to the stream, you have two characters on the stream - the character you typed plus a newline.
The for loop loops twice, and "double prints" Keep going! and Please enter in one of your grades. because each iteration reads one of the two characters on the stream.
It would be easier to wrap System.in in a InputStreamReader then a BufferedReader or just initialize a Scanner with System.in. With a BufferedReader you can just call readLine(), and with a Scanner you can call nextLine().
Also, it's unclear why you are looping from '0' to '9' with chars. It would be clearer to use an int for a and loop from 0 until 9.
My professor tends to do the following to get a number from the user:
Scanner scanner = new Scanner(System.in);
Integer.parseInt(scanner.nextLine());
What are the benefits as opposed to simply doing scanner.nextInt() ?
java.util.Scanner.java has the following in it:
public int nextInt() {
return nextInt(defaultRadix);
}
public int nextInt(int radix) {
// Check cached result
if ((typeCache != null) && (typeCache instanceof Integer)
&& this.radix == radix) {
int val = ((Integer)typeCache).intValue();
useTypeCache();
return val;
}
setRadix(radix);
clearCaches();
// Search for next int
try {
String s = next(integerPattern());
if (matcher.group(SIMPLE_GROUP_INDEX) == null)
s = processIntegerToken(s);
return Integer.parseInt(s, radix);
} catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
throw new InputMismatchException(nfe.getMessage());
}
}
As I see it, Scanner calls Integer.parseInt() itself as well, on top of additional hocus pocus. Are there significant performance gains in doing simply Integer.parseInt(scanner.nextLine()) ? Are there on the other hand any drawbacks?
How about when scanning through a file with significant amount of data, and not a user input?
There are 2 observations :
Using myScannerInstance.nextInt() leaves behind a new line character. So, if you call nextLine() after nextInt(), the nextLine() will read the new line character instead of the actual data. Consequently, you will have to add another nextLine() after the nextInt() to gobble up that dangling new-line character. nextLine() doesn't leave behind a new line character.
code :
int age=myScannerInstance.nextInt();
String name = myScannerInstance.nextLine();// here the actual name will not be read. The new line character will be read.
nextInt() will again go back to the underlying stream and read. IO calls take time (expensive). It will do lot of checks to get the next integer. nextLine() will do those checks only once. So, if you call nextLine() once and read 5 integers (as a single line String), split them and parse them as integers (using Integer.parseInt()), it will be faster and more efficient than reading each int individually.
Using nextLine() + parseInt() will give you enormous performance benefit when you are running a very large loop.
Usage :
Using nextInt() gives you an additional advantage wherein you will get an exception if the input text is not an integer. example 123 is accepted.. 123sdsa will throw an InputMismatchException. So, you can catch it and handle it appropriately.
Using nextLine() will read the entire line, so, it will read the entire String sada1231 and then fail with NumberFormatException if it cannot parse the String as a number. You will have to handle that exception.
Generally, one nextLine() / nextInt() call won't make much of a difference. If you have a loop or if you are reading lot of data, then using readLine() with parseInt() will be very efficient.
nextInt() reads a number, but doesn’t consume line separator. While nextLine() reads the String and consumes the new-line character. According to Java Docs:
… This method returns the rest of the current line, excluding any line
separator at the end. The position is set to the beginning of the next
line.
In other words when you enter a number then press Enter, input.nextInt() consumes only the number, not the "end of line", primitive data types like int, double etc does not consume "end of line", due which this "end of line" remain in buffer ane When input.next() executes, it consumes the "end of line" from buffer from the first input. So you professor is trying to get to the next line after he reads the user input. You have to look at the logic of his codes only then you can understand it.
I also used to face this problem often. So i use to code like this..
public static void main(String[] args) {
Scanner key= new Scanner(System.in);
String name;
int age;
age = key.nextInt();
key.nextLine();
name = key.nextLine(); //to carry the new line character left behind nextInt()
System.out.println("Age : "+age);
System.out.println("Name: "+name);
}
here as the key.nextInt() leaves a new line character we are using key.nextLine() to carry the new Line character and then move to the nextline where the actual data is present. As we discussed above using Integer.parseInt() will be more efficient than using nextInt(). But this is also one of the way to code to overcome the problem.
nextInt() leaves behind a new line character. So, if you call nextLine() after nextInt() , the nextLine() will read the new line character instead of the actual data. Consequently, you will have to add another nextLine() after the nextInt() to gobble up that dangling new-line character.
public class Solution {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
double d = scan.nextDouble();
scan.nextLine();
String s = scan.nextLine();
scan.close();
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
}
}
I am trying to write a method that prints out whatever character the user is entering character by character appended with the previous ones as he enters and throws an exception when he presses enter. I have written the following code but when i enter, it appends what ever character I have written and does not throw an exception. I would appreciate your help and suggestion.
public static void inputM(StringBuffer a) throws EntExc, IOException{
char c;
String m;
while(true){
Scanner s = new Scanner(System.in);
m=s.next();
c=m.charAt(0);
if(c=='\r'){
throw new EntExc();
}
System.out.println(a.append(m));
}
}
There are a few issues here. First s.next() grabs a whitespace-delimited token and returns the entire token as a single string. Second, because Scanner uses whitespace as a delimiter, it will never return \r, it will just skip it and read the next token.
Why not use s.readLine() and simply echo the whole line? While it won't process characters as they are entered (Scanner can't really do this, it always buffers lines), it will be closer to your described requirement.
I have written the following code to print file content and print the number of character and words from file
import java.io.*;
import java.util.*;
class Ass53
{
public static void main(String args[]) throws Exception
{
File file=new File("sample.txt");
Scanner sc=new Scanner(new FileInputStream(file));
String line,line1;
int count1=0;
int count=0;
/*Loop for printing contents of file*/
while(sc.hasNextLine())
{
line=sc.nextLine();
System.out.println(line);
}
/*loop for counting number of character in file*/
while(sc.hasNext())
{
line1=sc.next();
for(int i=1;i<=line1.length();i++)
count1++;
}
System.out.println(count1);
/*loop for counting number of words in a file*/
while(sc.hasNext())
{
sc.next();
count++;
}
System.out.println("Number of words: " + count);
}
}
The problem is that only first while loop is executing.I guess the reason may be the sc.nextLine for first while loop.After first while loop sc points to nothing i guess?.
Is there any way to fix it?
I want that my other while loop also work
Every time you are doing nextLine() you are advancing the scanner past the current line. When the first loop is over, you are at the end of the file and there is nothing to scan.
A solution would be to recreate the scanner before each loop. Just repeat this before second and third while:
sc=new Scanner(new FileInputStream(file));
Another solution would involve more work but is more elegant: use a single loop to store all lines in a List<String>, then analyse all lines to count words and characters.
The first loop say "until I run out of lines in the file, read the line and print it." Then the second loop looks for more characters in the file, and of course there's nothing there.
One option is to reset the scanner before each loop. Before each loop after the first, just close and discard the scanner, and create a new one.
There's a better way, though. You can walk through the file character-by-character (e.g. with a BufferedReader), and increment the character count on each character, and the newline count on each newline character. Don't forget to account for files that don't end with a newline. Only one loop is required, and you've calculated both the total character count and the line count.
You need to set your sc back to the beginning of the stream after you're done looping over it each time.
I won't post the code because this looks like homework, and I'm guessing the class name Ass53 is "Assignment53". It shouldn't be too hard to look up and figure out how to set the stream back to the beginning.
Of you could try to combine this into a single loop, because as it stands right now, you're actually reading the same file 3 times. It might not be that bad if it's a small file, but if it's a larger file that would be slow.