Reputation: 355
I am writing a program to take in a file and output a file. The input file contains like:
1 cat dog rabbit
3 cat dog rabbit rabbit rabbit
2 yellow red blue white black
0 three two one
and the output file would be:
dog rabbit rabbit rabbit blue white black three two one
(the program takes in the integer at the beginning of each line and then skip the number of words in each line and then save the rest words and output them to a file)
Initially, I have
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.PrintWriter;
public class Scanner2{
public static void main(String args[]) {
String c = "";
try{
File file = new File(args[0]);
Scanner scanner = new Scanner(file);
PrintWriter writer = new PrintWriter(args[1]);
// as long as the scanner reads that the file has a next line
while (scanner.hasNextLine()) {
// read the next line of string as string s
String s = scanner.nextLine();
// split each word from the string s as an array called "words"
String[] words = s.split(" ");
// for loop executed length of "words" times
for(int x = 0; x < words.length; x++) {
// declare int, "count"
int count;
// parse the first element (the number) from "words" to be an integer, "count"
count = Integer.parseInt(words[0]);
// if the loop is executed more than "count" number of times
if (x > count){
// add respective element to string, "c"
c += words[x];
c += " ";
}
}
}
// close the scanner
scanner.close();
// output string "c" to the output file
writer.println(c);
// close the writer
writer.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
and these codes work perfectly. However, now I want to switch from using the split method to another second scanner class to read each sentence to each word.
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.PrintWriter;
public class ScannerDemo{
public static void main(String args[]) {
String c = "";
try{
File file = new File(args[0]);
Scanner scanner = new Scanner(file);
PrintWriter writer = new PrintWriter(args[1]);
// as long as the scanner reads that the file has a next line
while (scanner.hasNextLine()) {
// read the first line of string in scanner s2
Scanner s2 = new Scanner(scanner.nextLine());
// read the first word of first line from s2 as string "counts"
String counts = s2.next();
// parse the string "counts" as int, "count"
int count = Integer.parseInt(counts);
// as long as s2 has the next element
while (s2.hasNext()){
// for loop executed "count" number of times to skip the words
for (int x = 0; x < count; x ++){
String b = s2.next();
}
// else add the next words to string, "c"
c += s2.next();
c += " ";
}
}
// close the scanner
scanner.close();
// output string "c" to the output file
writer.println(c);
// close the writer
writer.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
However, it gives out error message
Exception in thread "main" java.util.NoSuchElementException
I felt this error message is due to the second scanner class not closed properly. However, I did not figure out how to solve it after I added
s2.close();
in the for loop.
Any help is appreciated. Thank you but I am really new to Java,
Upvotes: 1
Views: 1985
Reputation: 22224
There is a bug in the nested while and for loops that causes the s2.next() in the for loop to go of the end of the line. Try as follows
// parse the string "counts" as int, "count"
int count = Integer.parseInt(counts);
// for loop executed "count" number of times to skip the words
for (int x = 0; x < count && s2.hasNext(); x++){
String b = s2.next();
}
// as long as s2 has the next element add the next words to string
while (s2.hasNext()) {
c += s2.next();
c += " ";
}
Also, it is recommended to use try with resources
instead of closing yourself. Simplified example :
try (Scanner scanner = new Scanner(file);
PrintWriter writer = new PrintWriter(args[1]);) {
scanner.next();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
This way the scanner
and writer
will be closed automatically even if an exception is thrown.
Upvotes: 1
Reputation: 83
For example you can use a StringTokenizer instead of a second Scanner:
while(scanner.hasNextLine())
{
StringTokenizer tokenizer = new StringTokenizer(scanner.nextLine());
int count = Integer.parseInt(tokenizer.nextToken());
while(tokenizer.hasMoreTokens())
{
String b = tokenizer.nextToken() + " ";
if(count <= 0)
{
c += b;
}
count--;
}
}
scanner.close();
I think your problem with the second scanner was the inner loop and the scanner position - you want to advance it the number of words it has and only add some to your output string.
Upvotes: 1