简体   繁体   中英

How to count characters in a dat file?

Here is my code:

import java.util.Scanner;
import java.io.*;

public class BaseballStats
{

    public static void main (String[] args) throws IOException
    {
        Scanner fileScan, lineScan;
        String fileName;

        Scanner scan = new Scanner(System.in);

        System.out.print ("Enter the name of the input file: ");
        fileName = scan.nextLine();
        fileScan = new Scanner(new File(fileName));

        while (fileScan.hasNext())
        {
          fileName =fileScan.nextLine();
          System.out.println("Name: " + fileName);

          lineScan = new Scanner (fileName);
          lineScan.useDelimiter(",");
          while (lineScan.hasNext())
            System.out.println(" "+lineScan.next());

          System.out.println();
        }

    }
}

When you run the stats.dat file

Willy Wonk,o,o,h,o,o,o,o,h,w,o,o,o,o,s,h,o,h
Shari Jones,h,o,o,s,s,h,o,o,o,h,o,o,o,o
Barry Bands,h,h,w,o,o,o,w,h,o,o,h,h,o,o,w,w,w,h,o,o
Sally Slugger,o,h,h,o,o,h,h,w
Missy Lots,o,o,s,o,o,w,o,o,o
Joe Jones,o,h,o,o,o,o,h,h,o,o,o,o,w,o,o,o,h,o,h,h
Larry Loop,w,s,o,o,o,h,o,o,h,s,o,o,o,h,h
Sarah Swift,o,o,o,o,h,h,w,o,o,o
Bill Bird,h,o,h,o,h,w,o,o,o,h,s,s,h,o,o,o,o,o,o
Don Daring,o,o,h,h,o,o,h,o,h,o,o,o,o,o,o,h
Jill Jet,o,s,s,h,o,o,h,h,o,o,o,h,o,h,w,o,o,h,h,o

I get this output:

Name: Willy Wonk,o,o,h,o,o,o,o,h,w,o,o,o,o,s,h,o,h
 Willy Wonk
 o
 o
 h
 o
 o
 o
 o
 h
 w
 o
 o
 o
 o
 s
 h
 o
 h

Name: Shari Jones,h,o,o,s,s,h,o,o,o,h,o,o,o,o
 Shari Jones
 h
 o
 o
 s
 s
 h
 o
 o
 o
 h
 o
 o
 o
 o

Name: Barry Bands,h,h,w,o,o,o,w,h,o,o,h,h,o,o,w,w,w,h,o,o
 Barry Bands
 h
 h
 w
 o
 o
 o
 w
 h
 o
 o
 h
 h
 o
 o
 w
 w
 w
 h
 o
 o

Name: Sally Slugger,o,h,h,o,o,h,h,w
 Sally Slugger
 o
 h
 h
 o
 o
 h
 h
 w

Name: Missy Lots,o,o,s,o,o,w,o,o,o
 Missy Lots
 o
 o
 s
 o
 o
 w
 o
 o
 o

Name: Joe Jones,o,h,o,o,o,o,h,h,o,o,o,o,w,o,o,o,h,o,h,h
 Joe Jones
 o
 h
 o
 o
 o
 o
 h
 h
 o
 o
 o
 o
 w
 o
 o
 o
 h
 o
 h
 h

Name: Larry Loop,w,s,o,o,o,h,o,o,h,s,o,o,o,h,h
 Larry Loop
 w
 s
 o
 o
 o
 h
 o
 o
 h
 s
 o
 o
 o
 h
 h

Name: Sarah Swift,o,o,o,o,h,h,w,o,o,o
 Sarah Swift
 o
 o
 o
 o
 h
 h
 w
 o
 o
 o

Name: Bill Bird,h,o,h,o,h,w,o,o,o,h,s,s,h,o,o,o,o,o,o
 Bill Bird
 h
 o
 h
 o
 h
 w
 o
 o
 o
 h
 s
 s
 h
 o
 o
 o
 o
 o
 o

Name: Don Daring,o,o,h,h,o,o,h,o,h,o,o,o,o,o,o,h
 Don Daring
 o
 o
 h
 h
 o
 o
 h
 o
 h
 o
 o
 o
 o
 o
 o
 h

Name: Jill Jet,o,s,s,h,o,o,h,h,o,o,o,h,o,h,w,o,o,h,h,o
 Jill Jet
 o
 s
 s
 h
 o
 o
 h
 h
 o
 o
 o
 h
 o
 h
 w
 o
 o
 h
 h
 o

Question: Now I need to modify the inner loop that parses a line in the file so that instead of printing each part it counts (separately) the number of hits, outs, walks, and sacrifices. Each of these summary statistics should be printed for each player.

The problem I am having is that I do not know how to make it count specific characters and I do not know how to make it not count the characters in the name.

If someone could guide me that would be great.

You have just a few types of characters to count. You could simply use a separate counter for each:

      int wCount = 0;
      int hCount = 0;
      // ...
      while (lineScan.hasNext()) {
        switch (lineScan.next()) {
            case 'w': wCount++; break;
            // ...
        }
      }
      // print the stats

Here is a full implementation of your main() method using the approach I would use myself given your input data. First, I split each line of the stats.dat file on comma. This leaves us with an array, the first element of which is the player name, and the remaining elements which are individual game event statistics (eg out, walk). Next, I simply tally up the stats for each player and then display this to the console.

public static void main (String[] args) throws IOException {
    Scanner fileScan;
    String fileName;

    Scanner scan = new Scanner(System.in);

    System.out.print ("Enter the name of the input file: ");
    fileName = scan.nextLine();
    fileScan = new Scanner(new File(fileName));

    while (fileScan.hasNext()) {
        String currLine = fileScan.nextLine();
        String[] parts = currLine.trim().split(",");

        String playerName = "";
        int hits=0, outs=0, walks=0, sacs=0;

        if (parts.length > 0) {
            playerName = parts[0];
        }

        for (int i=1; i < parts.length; ++i) {
            String stat = parts[i].trim();
            if (stat.equals("h")) {
                ++hits;
            }
            else if (stat.equals("o")) {
                ++outs;
            }
            else if (stat.equals("w")) {
                ++walks;
            }
            else if (stat.equals("s")) {
                ++sacs;
            }
        }

        // display aggregated player stats to the console
        System.out.println(playerName + ":");
        System.out.println("hits : "  + hits);
        System.out.println("outs : "  + outs);
        System.out.println("walks : " + walks);
        System.out.println("sacs : "  + sacs);
    }
}

Scanner is a heavyweight, so using it to simply read lines, and to split a line, is overkill. Use BufferedReader.readLine() and String.split() instead. Also, don't pre-declare the variables, declare where initialized, whenever possible.

Calling split() will give you an array, where you know that first element is the name, so you skip it.

Scanner sysin = new Scanner(System.in);
System.out.print("Enter the name of the input file: ");
String fileName = sysin.nextLine();

try (BufferedReader fileIn = new BufferedReader(new FileReader(fileName))) {
    for (String line; (line = fileIn.readLine()) != null; ) {
        String[] values = line.split(",");
        int hits = 0, outs = 0, walks = 0, sacrifices = 0;
        for (int i = 1; i < values.length; i++)
            switch (values[i].charAt(0)) {
                case 'h': hits++;        break;
                case 'o': outs++;        break;
                case 'w': walks++;       break;
                case 's': sacrifices++;  break;
            }
        System.out.println(values[0] + ": " + hits + " hits, " +
                                              outs + " outs, " +
                                              walks + " walks, " +
                                              sacrifices + " sacrifices");
    }
}

For this I would simply use a Map to count the different types of data on each line. I'd split the data, the first item would always be the persons name and then tally up the count in the HashMap. Adding different types of data is also easiest with this approach because all you need to do is add a type in the item lookup and you're done. An example is if you wanted to add ab for Bunt then you'd simply need to add

itemLookup.put("b", "Bunt"); 

to the code and you'd be done. Here's the implementation.

I simply created a method that would process each line. I'm assuming that the user can pass in the line from whatever feed they want.

import java.util.HashMap;
import java.util.Map;

public class CountCharacters {

    public static void main(String[] args) {
        CountCharacters.processLine("Willy Wonk,o,o,h,o,o,o,o,h,w,o,o,o,o,s,h,o,h");
    }

    static Map<String, String> itemLookup = new HashMap<>();

    static {
        itemLookup.put("s", "Strike");
        itemLookup.put("w", "Walk");
        itemLookup.put("o", "Out");
        itemLookup.put("h", "Hit");

    }

    public static void processLine(String currentLineReadFromFile) {
        String inputData[] = currentLineReadFromFile.split(",");
        HashMap<String, Integer> characterCount = new HashMap<>();

        for (String key : inputData) {
            Integer value = characterCount.get(key);
            if (value == null) {
                characterCount.put(key, 1);
            } else {
                value++;
                characterCount.put(key, value);
            }
        }

        // show counted characters of all items collected
        boolean firstItem = true;
        for (String character : characterCount.keySet()) {
            Integer value = characterCount.get(character);
            if (firstItem == true) {
                System.out.println(character);
                firstItem = false;
                continue;
            }
            System.out.println(itemLookup.get(character) + ":" + value);
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM