mcgag
mcgag

Reputation: 355

Printing each word from a paragraph of words in Java while skipping some using Scanner class

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

Answers (2)

Manos Nikolaidis
Manos Nikolaidis

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

v4ssili
v4ssili

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

Related Questions