0

I've created a Java program in Eclipse. The program counts the frequency of each word. For example if the user entered 'I went to the shop' the program would produce the output '1 1 1 2' that is 1 word of length 1 ('I') 1 word of length 2 ('to') 1 word of length 3 ('the') and 2 words of length 4 ('went' , 'shop').

I've created this program to read a string entered by the user but I'm wanting to adjust the code to read each line of a text file. Any help would be great.

import java.util.Scanner;

public class WordLengthFrequency
{

    public static void main(String[] args)
    {
        Scanner scan = new Scanner(System.in);

        while (true)
        {
            System.out.println("Enter text: ");

            String s;
            s = scan.nextLine();
            String input = s;
            String strippedInput = input.replaceAll("\\W", " ");

            System.out.println("" + strippedInput);

            String[] strings = strippedInput.split(" ");
            int[] counts = new int[6];
            int total = 0;
            for (String str : strings)
                if (str.length() < counts.length)
                    counts[str.length()] += 1;
            for (String s1 : strings)
                total += s1.length();   
            for (int i = 1; i < counts.length; i++){    
                StringBuilder sb = new StringBuilder(i).append(i + " letter words: ");
                for (int j = 1; j <= counts[i]; j++) {
                    sb.append('*');
                    System.out.println(i + " letter words: " + counts[i]);
                    System.out.println(sb);
                    System.out.println(("mean lenght: ") + ((double) total / strings.length));
                }
            }
       }
    }
}
  • possible duplicate of [Best way to read a text file](http://stackoverflow.com/questions/4716503/best-way-to-read-a-text-file) – vefthym Jul 09 '15 at 10:58
  • 1
    just replace `Scanner scan = new Scanner(System.in);` with `Scanner scan = new Scanner(new File("file path here"));`. easy and quick way – Abdo Adel Jul 09 '15 at 11:06
  • Thanks! but now im getting an error of: Exception in thread "main" java.util.NoSuchElementException: No line found at java.util.Scanner.nextLine(Scanner.java:1516) at mallinson_Liam_8.main(mallinson_Liam_8.java:16) –  Jul 09 '15 at 11:18
  • you could make your logic for counting the wordLenghts easier (if you can use java8) `Map collect = Arrays.stream(strippedInput.split(" ")).collect( Collectors.groupingBy(String::length, Collectors.counting()));` . Where The Integer Value in the Map is the lenght of the word and the long-value the number of occurrences – griFlo Jul 09 '15 at 11:33

2 Answers2

1

First tip, a little code formatting can make a HUGE difference to readability. Also, for reading files, I would suggest using a BufferedReader. In this case, I would recommend using a HashMap. Currently, your are being limited to the length of words that you can keep track of because you are using a list which has a finite index. With a map, you can keep track of any amount of lengths of words. Something like the following would be good.

public static void main(String[] args) {
    HashMap<Integer, Integer> lengthCount = new HashMap<Integer, Integer>();
    BufferedReader br;
    try {
        String currentLine;
        br = new BufferedReader(new FileReader("text.txt"));

        // Gets new line, if it is the end of the file, it ends
        int totalNumberWords = 0;
        while ((currentLine = br.readLine()) != null) {
            String[] words = currentLine.split(" ");
            totalNumberWords += words.length;

            // Iterates through the words in the line and
            // increments the map appropriately
            for (String word : words) {
                int currentNumber = 0;
                if (lengthCount.get(word.length()) != null)
                    currentNumber = lengthCount.get(word.length());
                lengthCount.put(word.length(), currentNumber + 1);
            }
        }

        // Iterates through the map and prints the amount of strings
        // for each length and the percent of words with each length
        for (Map.Entry<Integer, Integer> curEntry : lengthCount.entrySet()) {
            double percentWithThisLength = ((double) curEntry.getValue() / totalNumberWords) * 100;
            System.out.print(curEntry.getValue() + " string(s) with length " + curEntry.getKey());
            System.out.println(" (" + percentWithThisLength + "%)");
        }

        br.close();
    } catch (IOException e) {
        System.out.println("Could not find specified file");
    }
}

Which when text.txt contains:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Yay

produces:

3 string(s) with length 2 (15.0%)
3 string(s) with length 3 (15.0%)
6 string(s) with length 5 (30.0%)
3 string(s) with length 6 (15.0%)
2 string(s) with length 7 (10.0%)
2 string(s) with length 10 (10.0%)
1 string(s) with length 11 (5.0%)
JDrost1818
  • 964
  • 5
  • 21
0
Scanner scan = new Scanner(System.in);

This code creates a Scanner that scans system.in for things to read. System.in is typically the console. Instead you want to read from somewhere else, so you need to point the scanner to your desired text.

This can easily be done by

Scanner scan = new Scanner(new File("filePath"));

You also need to change the loop, since you can no longer just go on for ever (files, unlike console input, eventually ends). Scanner has a nice little method, hasNext(), that will tell you if it has more lines to read.

Astrogat
  • 1,519
  • 10
  • 21
  • Thanks but im getting this error now: " Exception in thread "main" java.util.NoSuchElementException: No line found at java.util.Scanner.nextLine(Scanner.java:1516) at mallinson_Liam_8.main(mallinson_Liam_8.java:16) " –  Jul 09 '15 at 11:25
  • You will get that error once it reaches the end of the line. You can stop this by changing while(true) to while(scan.hasNext()), whch will return whether or not the scanner has more lines. – Astrogat Jul 09 '15 at 12:35