/* CSVQuery.java ** ** Java program that allows the user to run "queries" on the records in ** a Comma Separated Values (CSV) file, the name of which is expected to ** be provided via a command line argument (aka a "run argument" in jGrasp's ** terminology). The fields in a CSV-record are understood to be numbered ** beginning at zero. To run a query on a CSV-record is simply to enter an ** integer k for the purpose of asking for field #k of that record to be ** displayed. ** Initially, the record that is subject to being queried is the first one in ** the file. The user can advance from one record to the next by entering an ** appropriate response at the program's prompt. The user can also quit. ** ** CMPS 134 Fall 2024 Prog. Assg. #4 ** Authors: P.M.J., R.W.M., and < STUDENT's NAME > ** Date: October 2024 ** Collaborated with: ... ** Known Defects: ... */ import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; public class CSVQuery { // Constants static final String QUIT = "Q"; // command to quit static final String NEXT = "N"; // command to advance to next record in file static final String COMMA = ","; static final String QUESTION_MARK = "?"; /* The name of a correctly formatted "CSV file" is expected as the single ** command-line argument (a.k.a. run argument, in jGrasp's terminology). */ public static void main(String[] args) throws FileNotFoundException { // Establish a Scanner that is able to read from the file whose name // was provided via the command-line argument. String fileName = args[0]; Scanner fileInput = new Scanner(new File(fileName)); // Read the first line from the file, making it the record initially // subject to having queries applied to it. String line = fileInput.nextLine(); // Establish a Scanner to read input from the keyboard. Scanner keyboard = new Scanner(System.in); // Each iteration of the following loop prompts the user to enter a // command, which is expected to be either the code to advance to the // next record ('N'), the code to quit ('Q'), or a nonnegative integer k // that serves to request that the k-th field of the current record be // displayed. boolean done = false; do { String query = getString("\nEnter query:>",keyboard).trim(); if(isValidQuery(query)) { if(query.startsWith(QUIT)) { done = true; } else if(query.startsWith(NEXT)) { if(fileInput.hasNext()) { line = fileInput.nextLine(); } else { done = true; System.out.println("---End of file reached!!!"); } } else { int position = Integer.parseInt(query); System.out.println(fieldOf(line,position)); } } else { System.out.println("--->Invalid query; try again."); } } while(!done); System.out.println("\nDone!"); } /* Reports whether or not the given query string is valid, which is to ** say that it specifies an integer numeral or the code either for ** quitting or for advancing to the next record in the input file. */ public static boolean isValidQuery(String query) { return (query.length() > 0) && (query.startsWith(QUIT) || query.startsWith(NEXT) || isValidInt(query)); } /* Reports whether or not the given query string describes an integer. */ public static boolean isValidInt(String query) { boolean result = true; try { // This call to Integer.parseInt() results in Integer.parseInt(query); // an exception being thrown unless 'query' } catch (Exception e) { // has the form of an integer literal result = false; } return result; } /* Returns the field occupying the specified position within the given ** CSV-record. If the given CSV-record has no such field (e.g., because ** the value of 'position' exceeds the number of fields in the record), ** QUESTION_MARK is returned. */ public static String fieldOf(String record, int position) { String result = QUESTION_MARK; // STUB!!! return result; } /* Prints the given prompt and then reads and returns the full line of ** input (as a string) entered by the interactive user. */ public static String getString(String prompt, Scanner input) { System.out.print(prompt); return input.nextLine(); } }