14: Input and Output

What We Will Cover


Illuminations

Questions from last class or the Reading?

Homework Questions?

Final Boss Event Approaching

  • Final Examinations Schedule
  • Note: If you need the proctoring center, schedule it two weeks early and overlapping the scheduled final exam time

14.1: Worlds and Files

Learner Outcomes

At the end of the lesson the student will be able to:

  • Read text files with a loop
  • Read and display a map file in a tile world

14.1.1: Review of Files and Streams

  • Sometimes we want to save data after our scenario finishes
  • For instances, we could store a high score list of players
  • Sometimes we want to use stored data so it is easier to make changes to scenarios
  • For example, we can read information from files to create tile maps
  • Reading a tile map from a file would let us change maps without recompiling
  • Also, we could have multiple tile map files to allow us to more easily create multiple levels in a scenario

Types of Files

  • All data in a file is ultimately just zeros and ones (bits)
  • However, we can classify the files based on their data into two broad categories: text and binary
  • In text files, the bytes in the file represent printable characters
  • Text files usually store Latin based characters (like English) in one byte
  • The byte for each character is defined by a standard such as ASCII (ASCII table) or UTF-8
  • Every line of text is delimited by end-of-line characters:
    • Unix/OS-X: "\n"
    • Windows: "\r\n"
  • We can read text files because each byte is interpreted by a program as textual characters
  • Data other than text is usually referred to as binary data
  • Each bit represents some type of encoded information like program instructions or integer data
  • Binary files are easily read by the computer but not by humans

Streams

  • To read and write files, we use a stream
  • A file stream is used to connect a file to a program
  • Input stream: accepts bytes from a source and delivers them to to a program

    Input stream

  • Output stream: accepts bytes from a program and delivers the data to a destination

    Output stream

  • We use character streams to read and write text files:

Layering Streams

  • Usually, any one stream does have not all the functionality we want
  • Instead, it is common to "layer" two or more streams
  • We add buffers to our streams to make reading and writing faster

Buffer

  • When writing, we add a stream to convert from binary to character data like PrintWriter
  • When reading, we add an object to convert the character data into other types like int, double and String using a Scanner
  • The following instructions include the layers normally used to write and read text files

Step by Step Procedure for Writing Text Files

  1. Import the API libraries for file output.
    import java.io.*;
  2. Create the layered output stream.
    String fileName = "data.txt";
    PrintWriter out = new PrintWriter( // encode data as characters
                      new BufferedWriter( // buffer data for speed
                      new FileWriter(fileName))); // write bytes
    
  3. Write the data like printing to a terminal window.
    out.println("This is a string");
    out.println('c');
    out.println(1234);
    out.println(1.234);
    for (int i = 0; i <= 10; i++) {
        out.print(i + ",");
    }
    out.println();
    
  4. Close the file.
    out.close(); // flush buffer and free up resources
    

Step by Step Procedure for Reading Text Files

  1. Import the API libraries for file input.
    import java.io.*;
    import java.util.Scanner;
    
  2. Create the input stream.
    String fileName = "data.txt";
    Scanner in = new Scanner( // parse characters into data types
                 new BufferedReader( // buffer data for speed
                 new InputStreamReader( // read bytes as characters
                 getClass().getResourceAsStream(fileName)))); //JAR
    
  3. Read the data.
    String str = in.nextLine();
    char ch = in.nextLine().charAt(0);
    int x = in.nextInt();
    double d = in.nextDouble();
    while (in.hasNextInt()) {
        x = in.nextInt();
    }
    
  4. Close the file.
    in.close();  // flush buffer and free up resources
    

Check Yourself

  1. To store information, the computer saves the data in a __________.
  2. True or false: data in a file is restricted to characters only.
  3. When we want to write binary data to a file as character, we add the "layer" named ________.
  4. When we want to read character data and convert it to data types like int, double and String , we add a(n) ________.

14.1.2: Using Loops to Read a File

  • Sometimes we do not know how many data items are in a file
  • To solve this, the typical approach is to use a loop to read the file data
  • Within the loop we check whether or not more data is available from the input stream
  • The Scanner object has methods like hasNext() to see if there is any more input in the stream
  • We can use these methods to signal when your program reaches the end of a file
  • The following table shows some methods of the Scanner class for detecting if more data is available
  • Following the table is an example of a method that read an indefinite number of lines from a file

Some Test Methods of a Scanner Object

Method Description
hasNext() Returns true if this scanner has another token in its input.
hasNextLine() Returns true if there is another line in the input of this scanner.
hasNextDouble() Returns true if the next token can be interpreted as a double value.
hasNextInt() Returns true if the next token can be interpreted as an int value.

Method to Read a File

public void readMap(String fileName)
{
    Scanner in = new Scanner(
                 new BufferedReader(
                 new InputStreamReader(
                 getClass().getResourceAsStream(fileName))));
    while (in.hasNext())
    {
        String line = in.nextLine();
        System.out.println(line);
    }
    in.close();
}

Try It: Read a File with a Loop (4m)

  1. Download the following scenario file, save it to a convenient location like the Desktop and unzip the file.

    Scenario file: platformer6.zip.

  2. Double-click the project.greenfoot file in the unzipped folder to start Greenfoot and open the scenario.
  3. Open the editor for the GameManager class and import the API libraries for file input.
    import java.io.*;
    import java.util.Scanner;
    
  4. In the GameManager class, add the readMap() method listed above.
  5. Compile the program to verify you implemented the new method correctly.
  6. To test the method, right-click on the scenario background and select the readMap(), entering an argument of: "maps/map1.txt".

    Remember to include the double-quote marks (") because the entry is a string. You should see the map file in the terminal window. If you have problems, ask a guild mate or the instructor for help as needed.

  7. Save your updated scenario as we will be adding to it as the lesson continues.
  8. When finished, please help those around you.
  9. Be prepared to answer the following Check Yourself questions when called upon.

Check Yourself

  1. When the number of file data items is unknown you can use a ________ statement to read all the data.
  2. Of the following, the answer that is NOT a method of the Scanner class for testing the input stream is ________.
    1. hasNext()
    2. hasNextLine()
    3. hasNextInt()
    4. hasNoInput()
  3. When typing the file name, double-quotes are required to indicate a data type of ________.

14.1.3: Loading Files with ArrayList

  • We can read data from a file but we still need to store the data into the map array
  • We could load each line of the file directly into an array like:
    int i = 0;
    while (in.hasNext()) {
        String line = in.nextLine();
        map[i] = line;
    }
    
  • However, an array must be set to the correct size before we read from the file
  • Unless we know the number of lines in the map ahead of time, we need a list type that can grow as needed
  • One list type that can grow as needed is an ArrayList

Array Lists

  • An ArrayList is a class that organizes data into a List
  • We discussed the List type in lesson 8.1.4: Interacting with Lists of Actors
  • The ArrayList class is part of the standard library classes of Java
  • To make use of an ArrayList, we must import the class library
    import java.util.ArrayList;
  • The general syntax for declaring an ArrayList is:
    ArrayList<elementType> objectName;
    
  • Where:
    • elementType: the type of data stored in the list
    • objectName: the name you make up for the ArrayList
  • For example, to store a list of String objects we can declare:
    ArrayList<String> list;
  • After declaring an ArrayList, we construct one using the new operator
  • For example, to declare and construct an ArrayList to store strings:
    ArrayList<String> list = new ArrayList<String>();
    
  • The above declaration creates an ArrayList with zero slots
  • However, we can add items to the list with the method add():
    list.add(element);
    
    Where element is a variable or literal of the correct type.
  • Each time we call the add() method, a new element is added to the end of the list

Some Commonly Used Constructors and Methods of the ArrayList<type> Class

Constructor/Method Description
ArrayList() Creates an empty list.
add(object) Adds the specified object to the end of the list.
get(index) Returns the object at the specified index in the list.
set(index, element) Returns the number of elements in the list.
size() Replaces the element at index with the new element.
toArray(array) Returns an array containing all of the elements in proper sequence.

Converting an ArrayList to an Array

  • Notice that the last method above returns an array from the ArrayList
  • After we have loaded all the lines from the file into an ArrayList, we call the toArray() method like:
    map = list.toArray(new String[0]);
    
  • Using an ArrayList we can read any number of lines from a file
  • After reading the lines, we then convert the lines to an array
  • We will update readMap() to complete this task in the next exercise

Updated Method readMap()

public void readMap(String fileName)
{
    ArrayList<String> list = new ArrayList<String>();
    Scanner in = new Scanner(
                 new BufferedReader(
                 new InputStreamReader(
                 getClass().getResourceAsStream(fileName))));
    while (in.hasNext()) {
        String line = in.nextLine();
        list.add(line);
        //System.out.println(line);
    }
    in.close();
    map = list.toArray(new String[0]);
    createPlatforms(map);
}

Try It: Load a File into an ArrayList (5m)

  1. Start Greenfoot and open the scenario from the last Try It exercise.

    If you did not keep the scenario, then complete Try It: Read a File with a Loop now and then continue with these instructions.

  2. Open the editor for the GameManager class and import the API library for the ArrayList.
    import java.util.ArrayList;
    
  3. In addition, add the following instance variable::
    private String[] map;
    
  4. In the GameManager class, update the readMap() method as shown below.
    public void readMap(String fileName)
    {
        ArrayList<String> list = new ArrayList<String>();
        Scanner in = new Scanner(
                     new BufferedReader(
                     new InputStreamReader(
                     getClass().getResourceAsStream(fileName))));
        while (in.hasNext()) {
            String line = in.nextLine();
            list.add(line);
            //System.out.println(line);
        }
        in.close();
        map = list.toArray(new String[0]);
        createPlatforms(map);
    }
    
  5. Also in the constructor of GameManager, add the following method call before calling createPlatforms(map)
    readMap("maps/map1.txt");
    
  6. Now remove the MAP variable and replace all the uses of the MAP variable with map.

    Hint: use the search and replace function in the editor menu: Tools : Replace...

  7. Compile the GameManager class to verify you implemented the variable changes correctly.
  8. Compile and run your updated scenario and verify the map is still displayed.

    If you have problems, ask a guild mate or the instructor for help as needed.

  9. Save your updated scenario as we will be adding to it as the lesson continues.

Check Yourself

  1. Of the following statements, the one that constructs a new ArrayList that stores String data is ________.
    1. ArrayList<GreenfootImage> images = new ArrayList<GreenfootImage>();
    2. ArrayList<String> strList = new ArrayList();
    3. ArrayList<String> strList = new ArrayList<String>;
    4. ArrayList<String> strList = new ArrayList<String>();
  2. To add an item to an ArrayList, call the method ________.
  3. To convert an ArrayList to an array, call the method ________.

14.1.4: Choosing Files

  • Java provides a graphical way to browse for and choose a file: JFileChooser
  • To use JFileChooser, we import the library:
    import javax.swing.JFileChooser;
  • Since we only need one JFileChooser per scenario, we declare it as a final instance variable:
    private final JFileChooser fc = new JFileChooser();
    
  • Displaying a declared standard open dialog requires one line of code:
    int returnVal = fc.showOpenDialog(null);
    
  • A user may decide to cancel the dialog, so we test for the APPROVE_OPTION
    if (returnVal == JFileChooser.APPROVE_OPTION)
    {
        file = fc.getSelectedFile();
        // Do something with the File object after this
    }
    
  • By default, a new JFileChooser displays files and folders from the users home directory
    • The home directory depends on the file system
    • On Windows, the home directory is My Documents
  • We can specify the starting directory using the setCurrentDirectory() method
  • For example, we can set the starting directory to the current working directory with:
    fc.setCurrentDirectory(new File("."));
    
  • A File object is a way Java stores information about a filepath on a computer's file system
  • Sometimes we want to restrict the type of files the JFileChooser displays
  • For example, we can restrict the JFileChooser to show only text files by adding a filter:
    FileNameExtensionFilter filter =
        new FileNameExtensionFilter("Text files (*.txt)", "txt");
    fc.addChoosableFileFilter(filter);
    
  • To use the FileNameExtensionFilter we need to import it:
    import javax.swing.filechooser.FileNameExtensionFilter;
    

Method chooseFile()

public String chooseFile()
{
    File file = null;
    int returnVal = fc.showOpenDialog(null);
    if (returnVal == JFileChooser.APPROVE_OPTION)
    {
        file = fc.getSelectedFile();
    }
    String fileName = "";
    if (file != null)
    {
        fileName = file.getName();
    }
    return fileName;
}

Check Yourself

  1. To provide a graphical "open dialog" for a scenario use the ________ component.
  2. The library to import for a JFileChooser is ________.
  3. To show the select file dialog and get the user's file selection, call the JFileChooser method ________.
  4. To check if the user has selected a file, instead of canceling, compare the return value against the JFileChooser constant ________.

Exercise 14.1: Choosing a Map File (5m)

In this exercise, we load map data from a file and display the tile map in a scenario using a file chooser.

Specifications

  1. Start Greenfoot and open the scenario from the last Try It exercise.

    If you did not keep the scenario, then complete Try It: Load a Map from a File now and then continue with these instructions.

  2. Start Greenfoot and open the scenario from the last exercise.
  3. Open the editor for the GameManager class and verify the import of the API library for the List is present.
    import java.util.List;
    
  4. Add the import statement for the API library for FileChooser.
    import javax.swing.JFileChooser;
    
  5. In the GameManager class, add the instance variable shown below.
    private final JFileChooser fc = new JFileChooser();
    
  6. In the constructor of GameManager, set a filter for the file chooser:
    fc.setCurrentDirectory(new File("./maps"));
    
  7. In the GameManager class, add the chooseFile() method shown below.
    public String chooseFile()
    {
        File file = null;
        int returnVal = fc.showOpenDialog(null);
        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            file = fc.getSelectedFile();
        }
        String fileName = "";
        if (file != null)
        {
            fileName = file.getName();
        }
        return fileName;
    }
    
  8. Add another method to the GameManager class to choose a map file.
    public void chooseMap()
    {
        fc.setCurrentDirectory(new File("./maps"));
        String fileName = chooseFile();
        if (!fileName.equals(""))
        {
            readMap("maps/" + fileName);
            List<Platform> platforms = getObjects(Platform.class);
            removeObjects(platforms);
            createPlatforms(map);
        }
    }
    
  9. Compile the scenario to verify you implemented the changes correctly.
  10. Test the changes by right-clicking on the background, selecting the chooseMap() method and verifying the world background changes.
  11. Save the GameManager.java file to submit as part of lab 14.

As time permits, read the following sections and be prepared to answer the Check Yourself questions in the section: 14.1.6: Review.

14.1.5: Review

Answer these questions to check your understanding. You can find more information by following the links after the question.

  1. What is the difference between a text file and a binary file? (14.1.1)
  2. What is an input stream? (14.1.1)
  3. What is an output stream? (14.1.1)
  4. What are three streams we typically layer for program output? (14.1.1)
  5. What are the steps for writing files? (14.1.1)
  6. What are the steps for reading files? (14.1.1)
  7. What technique can we use to read all the data from a file, if we do not know how much data is in the file? (14.1.2)
  8. Which of the following statements constructs a new ArrayList that stores String data? (14.1.3)
    1. ArrayList<GreenfootImage> images = new ArrayList<GreenfootImage>();
    2. ArrayList<String> strList = new ArrayList();
    3. ArrayList<String> strList = new ArrayList<String>;
    4. ArrayList<String> strList = new ArrayList<String>();
  9. Which of the following statements adds a new string to the end of the list? (14.1.3)
    1. add("foo");
    2. strList.add("foo");
    3. strList.addToEnd("foo");
    4. strList.addString("foo");
  10. What is the name of the Swing component that provides an "open dialog" for files? (14.1.4)

14.2: User Testing

Learner Outcomes

At the end of the lesson the student will be able to:

  • Provide feedback on other student' scenarios
  • Received feedback on your own scenario

14.2.1: About User Testing

  • The user-testable prototype is a complete and useable scenario
  • Some final touches, like opening screens, may be absent
  • However, the scenario is playable and testable
  • During testing, we have the opportunity to provide the developers with important feedback
  • With the feedback, they can improve the quality of the scenario before submitting the final project

User-Testable Prototype Developer Instructions

  1. Load your guild's project prototype onto at least three classroom computers
  2. Be prepared to let other students come and test your project
  3. Place written instructions next to each computer
  4. Open a browser with a link to the online form (see below)
  5. After the testing session is complete, you can view the reports online (see below)

Testing the Scenario

  • Do not discuss the game with a developer until after your play testing is complete.
  • Read the instructions for the game and then play the game through at least once.
  • Fill out the online form to record your observations (see below).
  • Make certain to correctly spell both your avatar name and the guild name to ensure credit.
  • Also make sure the instructor knows your avatar name

Instructor Evaluation of Project

  • During user testing, the instructor will also be evaluating projects
  • Because time is tight, please come and demo your project if your name is called
  • Instructor feedback will be reported in Canvas

14.2.2: Steer Clear of the Dark Path

  • Even if you enjoy talking trash with friends, do not indulge during the review
  • Avoid ridicule or dismissive language
    • NO: "I can't see around that ridiculous ball of puke-colored light."
    • YES: "The light around this character obstructs the view and is an unpleasant shade of yellow."
  • Do not use irony and sarcasm
    • NO: "The art for that makes me want to gouge out my eyes."
    • NO: "I'm so amazed by that effect, I just want to quit my job and worship the developer."
    • NO: "The fire effect is super impressive. It's the most amazing fire I've ever seen. Really."
    • YES: "The fire effect could be more impressive if it was larger and if it shimmered more."
  • Do not make it personal
    • NO: "If you can't see how this isn't fun, then you're stupid."
    • YES: "The scenario would be more enjoyable if I did not die every time I started.
    • NO: "Whoever coded this [particular feature] deserves to fail."
    • YES: "The player takes off like a rocket when falling and then dies."
  • The NO comments like these may see funny, but hurting others is never funny
  • Treat scenario creators with courtesy and respect
  • We will explore how to give constructive feedback in the next section

14.2.3: How to Give Constructive Scenario Feedback

  • The goal of reviewing a student's scenario is to help them improve
  • While they may want to improve, people are generally sensitive to criticism
  • We want to phrase our feedback so that it is valued by the recipient
  • Here are some suggestions on how to give constructive scenario feedback

Review as you want to be reviewed

  • Most people want the same thing: to have people enjoy their scenarios
  • Make sure your feedback is courteous and thoughtful
  • Review other scenarios as you would want other people to review your scenario
  • Avoid antisocial comments

Bundle suggestions with compliments

  • Overall, give at least as much positive feedback as you do negative
  • Start with a positive observation before offering a criticism
  • Make sure you follow criticism with a suggested solution
  • After the solution, offer a positive observation again
  • The courtesy of placing some praise before and after a suggestion for improvement makes receiving the criticism easier to take

Be specific

  • Describe specifically what you have observed
  • Where in the scenario did you observe something and what were you doing?
  • For example, "I was playing _____ and I tried _____ when ____ happened."
  • Describe how you reacted to what you observed

Put the feedback in perspective

  • Describe whether your criticism or suggestion is major or minor
  • When you are sending a message, make sure the tone of your words is appropriate

Starter Phrases for Giving Feedback

  • "I thought you did a good job with/of _____."
  • "One area I thought could be improved was _____."
  • "The core mechanic was _____. It made it fun to _____."
  • "The visual design was _____ and it made me think/feel _____."
  • "I was playing _____ and I tried _____ when ____ happened."

14.2.4: Forms and Feedback Results

Reading Feedback

  • Determine whether the comment is legitimate. Don't waste time if the comment is just to bully or offend you.
  • Pick out useful information. If someone is alerting you to a problem with your scenario that you were not aware of, then read it carefully.
  • Decide which points you agree with. Think about whether your scenario would be better if you followed the reviewer's advice.
  • Keep track of aspects you want to fix.
  • Think about what you are doing right.
  • Take note of concepts or techniques that should be extended or repeated.

Wrap Up

Due Next:
Q13: User-Testable Prototype (5/4/17)
Lab 14: Final Lab (5/9/17)
Q14: Final Project (5/11/17)
  • When class is over, please shut down your computer
  • You may complete unfinished lesson exercises at any time before the due date.
Home | Canvas | Schedule | Syllabus | Room Policies
Help | FAQ's | HowTo's | Links
Last Updated: May 09 2017 @01:37:58