Scanner is skipping text file lines - java

I'm new to java and I need help with this problem I encountered. This class reads data from text file and adds it to the array Movie. The problem is that when it reads the text file, it skips every other line.
public class ReadFile{
private File f;
Scanner sc;
int index;
public ReadFile(){
f = new File("db.txt");
try {
sc = new Scanner(f);
} catch (FileNotFoundException e) {
System.out.println("An Error occured, File couldn't be opened.");
}
}
public int FileRead(Movie[] film, int index){
sc.useDelimiter(",");
this.index = index;
while(sc.hasNext()){
film[index] = new Movie();
film[index].setTitle(sc.next());
film[index].setYear(sc.next());
film[index].setRuntime(sc.next());
film[index].setActorOne(sc.next());
film[index].setActorTwo(sc.next());
film[index].setDirector(sc.next());
if(sc.hasNextLine()){
sc.nextLine();
}
index++;
}
System.out.println("count is "+ index);
sc.close();
return index;
}
}

nextLine() doesn't actually do what you think it does.
Furthermore, neither does .useDelimiter(",") - presumably, your file is something like:
Jurassic Park,1993,128,Jeff Goldblum,Jeff Goldblum's looks,Steven Spielberg
The Fly,1986,96,Jeff Goldblum,A fly,David Cronenberg
The problem is, computer is as computer does. You said the separator between tokens is a comma. And nothing else. So, this whole thing is a single token:
Steven Spielberg
The Fly
As in, "Steven Spielberg\nThe Fly" is what your sc.next() call returns for the first movie in the setDirector line. Seems stupid? Well, you told the computer: Tokens are things separated by commas. That whole thing is surrounded by commas so, you asked for it, you got it: That's the next() token in the file. Then you do an otherwise useless nextLine call which eats the rest of that The Fly line, thus, resulting in not only skipping every other movie, but having a mangled combo of the directory and the name of the movie on the next (otherwise skipped) line, mangled together. You know, like The Fly? Get it? [Note to self: It's a movie from 1987, no, they wont get it!]
The fix is possibly to tell scanner that either a comma or a newline counts as a separator; .useDelimiter(",|\r?\n") would do that. And forget about the hasNextLine + nextLine part, that does nothing, you should just get rid of that. Your code will fail if there's a 'broken' line in there (one that doesn't include precisely 5 commas), and that nextLine stuff isn't going to fix that problem, thus, get rid of it.
Alternatively, forget scanner - read line by lines using e.g. Files.readAllLines, then process line-by-line, using .split(",") to break it into parts.

Related

Why am I getting an InputMismatchException with?

I created a Scanner in java to read through a file of data regarding a city. The file is formatted as such:
Abbotsford,2310,2
Adams,1967,1
Algoma,3167,2
When reading through the file, I get an InputMismatchException when scanning the last item on each line (This item needs to be an int).
public void fileScanner(File toScan) throws FileNotFoundException {
Scanner sc = new Scanner(toScan);
sc.useDelimiter(",");
System.out.println(sc.next());
System.out.println(sc.nextInt());
System.out.println(sc.nextInt());
Any ideas as to why? I'd imagine it has something to do with my use of the "," delimiter.
You are using only one delimiter i.e. , but your file contains \r or \n so try to use multiple delimiters. Also, use a loop to read the entire file:-
Scanner sc = new Scanner(toScan);
sc.useDelimiter(",|\\r\\n");
while (sc.hasNext()) {
System.out.println(sc.next());
System.out.println(sc.nextInt());
System.out.println(sc.nextInt());
}
OUTPUT:-
Abbotsford
2310
2
Adams
1967
1
Algoma
3167
2
The delimiter you're using is comma(,)
The system looks for the next comma, which comes only after Adams. So the input for the system looks like 2 Adams which is obviously not an Int , rather a String and hence the inputMisMatch.
If you make your data something like below, your code would work great.
Abbotsford,2310,2,
Adams,1967,1,
Algoma,3167,2,
Also I see there's no loop to read all the data. Your code will read just the first line.

Runtime Error Using Scanner class [duplicate]

I got an run time exception in my program while I am reading a file through a Scanner.
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at Day1.ReadFile.read(ReadFile.java:49)
at Day1.ParseTree.main(ParseTree.java:17)
My code is:
while((str=sc.nextLine())!=null){
i=0;
if(str.equals("Locations"))
{
size=4;
t=3;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Professions"))
{
size=3;
t=2;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Individuals"))
{
size=4;
t=4;
str=sc.nextLine();
str=sc.nextLine();
}
int j=0;
String loc[]=new String[size];
while(j<size){
beg=0;
end=str.indexOf(',');
if(end!=-1){
tmp=str.substring(beg, end);
beg=end+2;
}
if(end==-1)
{
tmp=str.substring(beg);
}
if(beg<str.length())
str=str.substring(beg);
loc[i]=tmp;
i++;
if(i==size ){
if(t==3)
{
location.add(loc);
}
if(t==2)
{
profession.add(loc);
}
if(t==4)
{
individual.add(loc);
}
i=0;
}
j++;
System.out.print("\n");
}
with Scanner you need to check if there is a next line with hasNextLine()
so the loop becomes
while(sc.hasNextLine()){
str=sc.nextLine();
//...
}
it's readers that return null on EOF
ofcourse in this piece of code this is dependent on whether the input is properly formatted
I also encounter with that problem.
In my case the problem was that i closed the scanner inside one of the funcs..
public class Main
{
public static void main(String[] args)
{
Scanner menu = new Scanner(System.in);
boolean exit = new Boolean(false);
while(!exit){
String choose = menu.nextLine();
Part1 t=new Part1()
t.start();
System.out.println("Noooooo Come back!!!"+choose);
}
menu.close();
}
}
public class Part1 extends Thread
{
public void run()
{
Scanner s = new Scanner(System.in);
String st = s.nextLine();
System.out.print("bllaaaaaaa\n"+st);
s.close();
}
}
The code above made the same exaption, the solution was to close the scanner only once at the main.
You're calling nextLine() and it's throwing an exception when there's no line, exactly as the javadoc describes. It will never return null
https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html
For whatever reason, the Scanner class also issues this same exception if it encounters special characters it cannot read. Beyond using the hasNextLine() method before each call to nextLine(), make sure the correct encoding is passed to the Scanner constructor, e.g.:
Scanner scanner = new Scanner(new FileInputStream(filePath), "UTF-8");
Your real problem is that you are calling "sc.nextLine()" MORE TIMES than the number of lines.
For example, if you have only TEN input lines, then you can ONLY call "sc.nextLine()" TEN times.
Every time you call "sc.nextLine()", one input line will be consumed. If you call "sc.nextLine()" MORE TIMES than the number of lines, you will have an exception called
"java.util.NoSuchElementException: No line found".
If you have to call "sc.nextLine()" n times, then you have to have at least n lines.
Try to change your code to match the number of times you call "sc.nextLine()" with the number of lines, and I guarantee that your problem will be solved.
Need to use top comment but also pay attention to nextLine(). To eliminate this error only call
sc.nextLine()
Once from inside your while loop
while (sc.hasNextLine()) {sc.nextLine()...}
You are using while to look ahead only 1 line. Then using sc.nextLine() to read 2 lines ahead of the single line you asked the while loop to look ahead.
Also change the multiple IF statements to IF, ELSE to avoid reading more than one line also.
I ran into this problem, my structure was:
1 - System
2 - Registration <-> 3 - validate
I was closing Scanner on each of the 3 steps. I started to close the Scanner only in system and it solved.

How do I change the delimiter from a text file?

Let's say I got a textfile.txt that I want to read from. This is the text in the file:
23:years:old
15:years:young
Using the useDelimiter method, how can I tell my program that : and newlines are delimiters? Putting the text in one line and using useDelimter(":"); works. The problem is when I got several lines of text.
Scanner input = new Scanner(new File("textfile.txt));
input.useDelimiter(:);
while(data.hasNextLine()) {
int age = input.nextInt();
String something = input.next();
String somethingelse = input.next();
}
Using this code I will get an inputMisMatch error.
Try
scanner.useDelimiter("[:]+");
The complete code is
Scanner scanner = new Scanner(new File("C:/temp/text.txt"));
scanner.useDelimiter("[:]+");
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
The output is
23
years
old
15
years
young
Use this code
Scanner input;
String tokenizer[];
try {
input = new Scanner(new File("D:\\textfile.txt"));
input.useDelimiter("\\n");
while(input.hasNextLine()) {
tokenizer = input.next().split(":");
System.out.println(tokenizer[0]+" |"+tokenizer[1]+" | "+tokenizer[2]);
}
}catch(Exception e){}
It will give you output like
23 |years | old
15 |years | young
You have two ways to do this:
Concatenate the string to make it one line.
delimit "newline" first, then delimit ":" each return string token.
If all you want is to get everything split up all at once then I guess you can use
useDelimiter(":\\n")
That should split on both : and newspace but it is not the most efficient way of processing data, especially if each line of text is set out in the same format and represents a complete entry. If that is the case then my suggestion would be to only split on a new line to begin with, like this;
s.useDelimiter("\\n");
while(s.hasNext()){
String[] result = s.next.split(":");
//do whatever you need to with the data and store it somewhere
}
This will allow you to process the data line by line and will also split it at the required places. However if you do plan on going through line by line I recommend you look at BufferedReader as it has a readLine() function that makes things a lot easier.
As long as all the lines have all three fields you can just use input.useDelimiter(":\n");
you probably wants to create a delimiter pattern which includes both ':' and newline
I didn't test it, but [\s|:]+ is a regular expression that matches one or more whitespace characters, and also ':'.
Try put:
input.useDelimiter("[\\s|:]+");

Read data in from text file, convert each word to PigLatin

I'm having trouble printing out the final result without each word being on its own line. The output should be formatted just as the input was. Here is the code I used to read the data and print it:
Scanner sc2 = null;
try {
sc2 = new Scanner(new File(dataFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (sc2.hasNextLine()) {
Scanner s2 = new Scanner(sc2.nextLine());
boolean b;
while (b = s2.hasNext()) {
String s = s2.next();
System.out.println(pig(s));
}
}
The actual instructions were as follows: "Translate the Declaration of Independence ("declaration.txt") into PigLatin. Try to preserve the paragraphs. There are several ways to do this, but they all use nested loops. You may want to look at nextLine, next, split, or StringTokenizer."
We haven't been taught how to use any of the methods listed there, though.
The println method is short for "print line". It prints the given output to the target output device followed by a newline. Check out the other methods in that class for the solution.
Update
The problem here is that to my knowledge java.util.Scanner throws out the whitespace (delimiter) between words. Check out java.util.StringTokenizer for a similar class that can be configured to return the whitespace characters one at a time.

How to test for blank line with Java Scanner?

I am expecting input with the scanner until there is nothing (i.e. when user enters a blank line). How do I achieve this?
I tried:
while (scanner.hasNext()) {
// process input
}
But that will get me stuck in the loop
Here's a way:
Scanner keyboard = new Scanner(System.in);
String line = null;
while(!(line = keyboard.nextLine()).isEmpty()) {
String[] values = line.split("\\s+");
System.out.print("entered: " + Arrays.toString(values) + "\n");
}
System.out.print("Bye!");
From http://www.java-made-easy.com/java-scanner-help.html:
Q: What happens if I scan a blank line with Java's Scanner?
A: It depends. If you're using nextLine(), a blank line will be read
in as an empty String. This means that if you were to store the blank
line in a String variable, the variable would hold "". It will NOT
store " " or however many spaces were placed. If you're using next(),
then it will not read blank lines at all. They are completely skipped.
My guess is that nextLine() will still trigger on a blank line, since technically the Scanner will have the empty String "". So, you could check if s.nextLine().equals("")
The problem with the suggestions to use scanner.nextLine() is that it actually returns the next line as a String. That means that any text that is there gets consumed. If you are interested in scanning the contents of that line… well, too bad! You would have to parse the contents of the returned String yourself.
A better way would be to use
while (scanner.findInLine("(?=\\S)") != null) {
// Process the line here…
…
// After processing this line, advance to the next line (unless at EOF)
if (scanner.hasNextLine()) {
scanner.nextLine();
} else {
break;
}
}
Since (?=\S) is a zero-width lookahead assertion, it will never consume any input. If it finds any non-whitespace text in the current line, it will execute the loop body.
You could omit the else break; if you are certain that the loop body will have consumed all non-whitespace text in that line already.
Scanner key = new Scanner(new File("data.txt"));
String data = "";
while(key.hasNextLine()){
String nextLine = key.nextLine();
data += nextLine.equals("") ? "\n" :nextLine;
}
System.out.println(data);
AlexFZ is right, scanner.hasNext() will always be true and loop doesn't end, because there is always string input even though it is empty "".
I had a same problem and i solved it like this:
do{
// process input
}while(line.length()!=0);
I think do-while will fit here better becasue you have to evaluate input after user has entered it.

Categories