Close
Register
Close Window

Programming Basics: Background and Repetition

Chapter 1 Java Programming, repetition

Show Source |    | About   «  1.5. Debugging In Eclipse   ::   Contents   ::   1.7. Testing  »

1.6. Reading Input (from Files or Otherwise)

1.6.1. The Scanner Class

There are a number of ways in Java for properly reading in a file. The Scanner class is an excellent class for this purpose as it provides a quickly parse through a String. See the Scanner class API. So how do we properly read in a file? There are a number of ways. This page shows a simple demonstration of how to use the Scanner class to read in a command file.

In this project we are given four commands that our program must handle:

  1. debug – prints information about the tree in the program

  2. search {x} {y} {radius} – searches a region based off coordinates given

  3. add {x} {y} {name} – adds a node at the coordinates given

  4. delete {x} {y} – deletes a node at the specific point

See input file for some example input. Consider the following code snippet.

import java.io.File;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {     
        String filename = args[0]; // Pass the function a full filepath.
        beginParsing(filename); // Call the parsing function.
    }
   
    public static void beginParsing(String filename) {
        try {
            Scanner sc = new Scanner(new File(filename)); // Create our new scanner.
            while (sc.hasNext()) { // While the scanner has information to read.
                String cmd = sc.next(); // Read the next term.
                double x; double y; double radius;
                switch (cmd) {
                case "debug" :
                    System.out.println("debug cmd activated");
                    break;
                case "add": // Found an add command.
                    x = sc.nextDouble();
                    y = sc.nextDouble();
                    String name = sc.next();
                    System.out.println("Insert node at "+x+" "+y+" with name "+name);
                    break;
                case "delete": // Found a delete command.
                    x = sc.nextDouble();
                    y = sc.nextDouble();
                    System.out.println("Remove node at "+x+" "+y);
                    break;
                case "search": // Found a search command.
                    x = sc.nextDouble();
                    y = sc.nextDouble();
                    radius = sc.nextDouble();
                    System.out.println("Search for node near "+x+" "+y+" within radius of "+radius);
                    break;
                default: // Found an unrecognized command.
                    System.out.println("Unrecognized input "+cmd);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

This code will parse through a command file, read in each command and each of their parameters (if it has any). It is important to note, however, that this code is not necessarily safe. It assumes that the command file given is properly formatted, and as such if a user decides to give the program a malformed file the program will behave in a possibly unknown way.

Depending on the structure of your file you may wish to simply do the token method. Another approach would be to read in an entire line and then work from there. Consider this input file. We now have 3 commands that we must support.

1. insert {artist-name}<SEP>{song-name} – inserts a song using the information provided in the fields

  1. remove {artist|song} {name} – removes a song given a song name or artist name

3. print {artist|song|blocks} – depending on the parameter value, you will print out either a complete listing of the artists contained in the database, or the songs, or else the free block list for the memory manager

So this time we have less commands to support, but more options for each command. No worries! We simply need to change our code just a little bit. We see this time that the insert command has no spacing between artist/song tokens. Rather it uses the separator <SEP>.

public static void beginParsingByLine(String filename) {
    try {
        Scanner sc = new Scanner(new File(filename));
        Scanner scancmd; // Declare two scanners one to read the file and one to read the text pulled from the file.
        while (sc.hasNextLine()) { // While we have text to read.
            String line = sc.nextLine(); // Get our next line.
            scancmd = new Scanner(line); // Create a scanner from this line.
            String cmd = scancmd.next(); // Get the first word (the command) on each line.
            String type;
            switch (cmd) {
            case "insert": // In the case of insert change our delimiter from white space to <SEP>.
                scancmd.useDelimiter("<SEP>");
                String artist = scancmd.next(); // Get the artist since it is before <SEP>.
                String song = scancmd.next(); // Get the song title that follows <SEP>.
                System.out.println("Insert " + artist + " \\ " + song);
                break;
            case "remove":
                type = scancmd.next(); // Get the mode of deletion artist/song.
                String token = scancmd.nextLine();
                // Since both artist titles and song titles have spaces
                // get the rest of the line for the song/artist name.
                switch (type) {
                case "artist":
                    System.out.println("Artist Delete: " + token);
                    break;
                case "song":
                    System.out.println("Song Delete: " + token);
                    break;
                default: // Error: bad token.
                    System.out.println("Error bad remove type " + type);
                    break;
                }
                break;
            case "print": // Print command.
                type = scancmd.next(); // Get the type of print command.
                switch (type) {
                case "artist":
                    System.out.println("Print artist mode");
                    break;
                case "song":
                    System.out.println("Print song mode");
                    break;
                case "blocks":
                    System.out.println("Print block mode");
                    break;
                default:
                    System.out.println("Error bad print type" + type);
                    break;
                }
                break;
            default :
                System.out.println("Unrecognized input");
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Separating artists and song names on the same line can prove to be rather difficult due to the fact that names might include a space or other traditional delimiters. By separating these fields using <SEP>, we drastically reduce the possibilty of a valid name containing the delimiter.

   «  1.5. Debugging In Eclipse   ::   Contents   ::   1.7. Testing  »

nsf
Close Window