Lab#SE02-5: Movie/Review, simulate interactivity by console

Java SE Lab 02

javase
lab
interativity
console
controller
testing
Java SE Lab 02 part 5
Author

albertprofe

Published

Tuesday, June 1, 2021

Modified

Friday, November 1, 2024

📘 Linux Lab#LI02-5: interactivity and console

Once in previous Lab#SE02-4, the user enjoys some interactivity with our app, let’s test this new feature.

  1. To do so, with the class Movie in mind, we could create a createFromConsole() method, a method that eventually:

    • prompts the user for input in the console
    • creates a Movie object based on that input
    • uses the Scanner class to read the input from the console
    • sets the fields of the Movie object with the input data.
  2. And then, test this method createFromConsole() with a JUnit @Test:

    • a test that simulates a user input by setting the input stream to a string containing the input data,
    • and then creating a Movie object and calling the createFromConsole() method.


The lazy programmer will reuse whatever they can to get their work done. This virtue leads to code reuse by encouraging code to be written only once - Larry Wall, The three virtues of a programmer

Laziness, Impatience, Hubris

1 Overview

Stream I/O in Standard I/O (java.io Package)

Stream I/O in Standard I/O (java.io Package)

Package java.io, provides for system input and output through data streams, serialization and the file system.

Following are the important classes in Java.io package:

Programming simple I/O operations is easy, which involves only a few classes and methods. You could do it by looking at a few samples like our previous lab.

Programming efficient, portable I/O is extremely difficult, especially if you have to deal with different character sets.

1.1 Stream

A stream is a sequence of data. In Java, a stream is composed of bytes. It’s called a stream because it is like a stream of water that continues to flow.

In our app, java.io will create three streams automatically. All these streams are attached with the console.

  • System.out: standard output stream
  • System.in: standard input stream
  • System.err: standard error stream

InputStream and OutputStream

InputStream and OutputStream

Input stream refers to an ordered flow of data in the form of bytes. This flow of data can be coming from various resources such as files, network programs, input devices, etc.

In order to read such data, we have a Java InputStream Class in the Java IO API. Link

1.2 Discuss solution

These lines of pseudo-code, particulary the (2) line, are the key-solution to use InputStream to simulate a input console.

(1) String simulateInputByConsole = "Here\ngoes\nhe\nsimulate\nimput";
(2) InputStream in <<<<< simulateInputByConsole.getBytes();
(3) System.setIn(in);

It creates an InputStream in that reads from a byte array containing the bytes of the input string input.getBytes() (using the platform’s default charset), which allow us to use this InputStream as regular input stream into System.in.

It extends the InputStream abstract class.

It extends the InputStream abstract class.

A new InputStream object is being created by wrapping a ByteArrayInputStream around a byte array.

String input = "The Shawshank Redemption\n" +
InputStream in = new ByteArrayInputStream(input.getBytes());

A ByteArrayInputStream is a subclass of InputStream that reads data from a byte array.

The byte array is created by calling the getBytes() method on the input string. getBytes() is a method of the String class that returns a byte array containing the characters of the string encoded using the platform’s default charset.

1.3 getBytes()

    String myString = "I love Java";
    byte[] byteArray;

    // convert the string to a byte array
    // using platform's default charset
    byteArray = myString.getBytes();
    System.out.println(Arrays.toString(byteArray));

    // Output
    // [73, 32, 108, 111, 118, 101, 32, 74, 97, 118, 97]

We have used the Arrays class in the above example to print the byte array in a readable form. It has nothing to do with getBytes().

HTML Encoding Character Set
more examples

There are many other standard charset like:

  • US-ASCII: Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set
  • ISO-8859-1: ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
  • UTF-8: Eight-bit UCS Transformation Format
  • UTF-16BE: Sixteen-bit UCS Transformation Format, big-endian byte order
  • UTF-16LE: Sixteen-bit UCS Transformation Format, little-endian byte order
  • UTF-16: Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark.

1.4 ByteArrayInputStream

Class ByteArrayInputStream

   // Creates a ByteArrayInputStream that reads entire array
   ByteArrayInputStream input = new ByteArrayInputStream(byte[] arr);

The ByteArrayInputStream class of the java.io package ìs used to read an array of input data (in bytes).

more on ByteArrayInputStream

2 Core classes

2.1 createFromConsole()

The method createFromConsole() is used to prompt the user for input in the console and create a movie object based on that input.

It uses the Scanner class to read the input from the console and sets the fields of the Movie object with the input data.

You could then use these:

Movie.java
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Movie {
    private String title;
    private int year;
    private String director;
    private String actors;

    public void createFromConsole() {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter the title of the movie: ");
        title = scanner.nextLine();
        System.out.print("Enter the year the movie was released: ");
        year = scanner.nextInt();
        scanner.nextLine(); // consume the newline character
        System.out.print("Enter the name of the director: ");
        director = scanner.nextLine();
        System.out.print("Enter the names of the actors" +
                            " (separated by commas): ");
        actors = scanner.nextLine();
    }

    // getters adn setters by lombok
}

2.2 testCreateMovieFromConsoleInput()

The method testCreateMovieFromConsoleInput() is a JUnit test that is used to test the createFromConsole() method.

This test simulates user input by setting the input stream to a string containing the input data, and then creating a Movie object and calling the createFromConsole() method.

Then it uses the assertEquals method to check that the fields of the movie object are set to the correct values, based on the input provided.

MovieTest.java
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class MovieTest {

    @Test
    public void testCreateMovieFromConsoleInput() {
        // Set up input for the console
        String input = "The Shawshank Redemption\n" +
                        "1994\n" +
                        "Frank Darabont\n" +
                        "Tim Robbins, Morgan Freeman\n";
        InputStream in = new ByteArrayInputStream(input.getBytes());
        System.setIn(in);

        // Create the movie object
        Movie movie = new Movie();
        movie.createFromConsole();

        // Assert that the movie object was created with the correct data
        assertEquals("The Shawshank Redemption", movie.getTitle());
        assertEquals(1994, movie.getYear());
        assertEquals("Frank Darabont", movie.getDirector());
        assertEquals("Tim Robbins, Morgan Freeman", movie.getActors());
    }

}

It is important to test the createFromConsole() method because it is a core functionality of the Movie class, and it is essential to ensure that it is working properly.

If this method is not working as expected, it will not only affect the user experience but also could cause the application to fail.

This static method System.setIn() from the class java.lang.System is used to reassign the standard input stream.

Signature:

static void setIn(InputStream in)
Back to top