Ebooks

Java console application

Java console application tutorial shows how to create a Java console application. The application computes some statistics.

Java console example

The following example creates a Java console application which reads data from a CSV file and computes some basic statistics.

The example uses Apache Commons libraries to parse command line arguments, do math, and transform data. The OpenCSV library is used to read CSV data.

data.csv
2.3, 3.5, 5, 6.7, 3.2, 1.2, 6.7, 7.8
4.5, 2.1, 6.6, 8.7, 3.2, 1.0, 1.2, 3

Somewhere on the disk we have this file. The file name will be a console parameter to our program.

$ tree
.
├── nbactions.xml
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── zetcode
    │               ├── JavaStatsEx.java
    │               └── MyStatsApp.java
    └── test
        └── java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zetcode</groupId>
    <artifactId>JavaConsoleApp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>
        
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.4</version>
        </dependency>
        
        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>4.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.6.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.5.0</version>
                <configuration>
                    <mainClass>com.zetcode.JavaStatsEx</mainClass>
                    <cleanupDaemonThreads>false</cleanupDaemonThreads>
                    <arguments>
                        <argument>-f</argument>
                        <argument>/home/janbodnar/tmp/data.csv</argument>
                    </arguments>                    
                </configuration>
            </plugin>
        </plugins>
    </build>       
    
</project>

In the pom.xml file, we define the dependencies of the application. The commons-cli artifact is for parsing command line arguments, opencsv for reading CSV data, commons-math for statistical calculations, and commons-lang3 for transforming list into an array.

The exec-maven-plugin executes Java programs from Maven. In the arguments tag, we give the application the option and the filename.

JavaStatsEx.java
package com.zetcode;

/**
 * Starter class for MyStats application.
 * 
 * @author janbodnar
 */

public class JavaStatsEx {
    
    /**
     * Application entry point.
     * 
     * @param args application command line arguments
     */
    public static void main(String[] args) {
        
        MyStatsApp msp = new MyStatsApp();
        msp.run(args);
    }
}

JavaStatsEx is the application entry point. It creates the instance of MyStatsApp and passes it the application arguments.

MyStatsApp.java
package com.zetcode;

import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.math3.stat.StatUtils;


/**
 * MyStatsApp is a simple console application which computes
 * basic statistics of a series of data values. The application takes
 * a file of data as its single argument.
 * 
 * @author janbodnar
 */
public class MyStatsApp {

    /**
     * Runs the application
     *
     * @param args an array of String arguments to be parsed
     */
    public void run(String[] args) {

        CommandLine line = parseArguments(args);

        if (line.hasOption("filename")) {

            System.out.println(line.getOptionValue("filename"));
            String fileName = line.getOptionValue("filename");

            double[] data = readData(fileName);
            calculateAndPrintStats(data);

        } else {
            printAppHelp();
        }
    }

    /**
     * Parses application arguments
     *
     * @param args
     * @return <code>CommandLine</code> which represents a list of application
     * arguments.
     */
    private CommandLine parseArguments(String[] args) {

        Options options = getOptions();
        CommandLine line = null;

        CommandLineParser parser = new DefaultParser();

        try {
            line = parser.parse(options, args);

        } catch (ParseException ex) {

            System.err.println(ex);
            printAppHelp();

            System.exit(1);
        }

        return line;
    }

    /**
     * Reads application data from a file
     *
     * @param fileName
     * @return array of double values
     */
    private double[] readData(String fileName) {

        List<Double> data = new ArrayList();
        double[] mydata = null;

        try (Reader reader = Files.newBufferedReader(Paths.get(fileName));
                CSVReader csvReader = new CSVReaderBuilder(reader).build()) {

            String[] nextLine;

            while ((nextLine = csvReader.readNext()) != null) {

                for (String e : nextLine) {

                    data.add(Double.parseDouble(e));
                }
            }

            mydata = ArrayUtils.toPrimitive(data.toArray(new Double[data.size()]));

        } catch (IOException ex) {

            System.err.println(ex);
            System.exit(1);
        }

        return mydata;
    }

    /**
     * Generates application command line options
     *
     * @return application <code>Options</code>
     */
    private Options getOptions() {

        Options options = new Options();

        options.addOption("f", "filename", true, 
            "file name to load data from");
        return options;
    }

    /**
     * Prints application help
     */
    private void printAppHelp() {

        Options options = getOptions();

        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("JavaStatsEx", options, true);
    }

    /**
     * Calculates and prints data statistics
     *
     * @param data input data
     */
    private void calculateAndPrintStats(double[] data) {

        System.out.format("Geometric mean: %f%n", StatUtils.geometricMean(data));
        System.out.format("Arithmetic mean: %f%n", StatUtils.mean(data));
        System.out.format("Max: %f%n", StatUtils.max(data));
        System.out.format("Min: %f%n", StatUtils.min(data));
        System.out.format("Sum: %f%n", StatUtils.sum(data));
        System.out.format("Variance: %f%n", StatUtils.variance(data));
    }
}

This is MyStatsApp.

CommandLine line = parseArguments(args);

The parseArguments() method parses the command line arguments. It returns CommandLine, which represents a list of arguments parsed against a Options descriptor.

if (line.hasOption("filename")) {

    System.out.println(line.getOptionValue("filename"));
    String fileName = line.getOptionValue("filename");

    double[] data = readData(fileName);
    calculateAndPrintStats(data);

} else {
    printAppHelp();
}

The application has a mandatory filename option, which points to the file to be read and compute statistics from. If it is not present, we provide the application help message.

Options options = getOptions();

The getOptions() method returns the options of the application.

CommandLineParser parser = new DefaultParser();

try {
    line = parser.parse(options, args);

} catch (ParseException ex) {

    System.err.println(ex);
    printAppHelp();

    System.exit(1);
}

return line;

CommandLineParser parses the command line arguments. The application exits if there is a ParseException. The parser returns parsed arguments in CommandLine object.

try (Reader reader = Files.newBufferedReader(Paths.get(fileName));
        CSVReader csvReader = new CSVReaderBuilder(reader).build()) {

CSVReader is used to read CSV data.

String[] nextLine;

while ((nextLine = csvReader.readNext()) != null) {

    for (String e : nextLine) {

        data.add(Double.parseDouble(e));
    }
}

In this while loop, we read the CSV file line by line and parse the data into a list of Double values.

mydata = ArrayUtils.toPrimitive(data.toArray(new Double[data.size()]));

We need primitive data types to calculate the statistics; therefore, we transform the list into an array of primitive double values. ArrayUtils comes from the Apache Commons Lang library.

private Options getOptions() {

    Options options = new Options();

    options.addOption("f", "filename", true, 
        "file name to load data from");
    return options;
}

The getOptions() provides the application options.

private void printAppHelp() {

    Options options = getOptions();

    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("JavaStatsEx", options, true);
}

The printAppHelp() prints the help of the application. It uses HelpFormatter to do the job.

private void calculateAndPrintStats(double[] data) {

    System.out.format("Geometric mean: %f%n", StatUtils.geometricMean(data));
    System.out.format("Arithmetic mean: %f%n", StatUtils.mean(data));
    System.out.format("Max: %f%n", StatUtils.max(data));
    System.out.format("Min: %f%n", StatUtils.min(data));
    System.out.format("Sum: %f%n", StatUtils.sum(data));
    System.out.format("Variance: %f%n", StatUtils.variance(data));
}

With StatUtils(), we compute some statistics. The StatUtils() takes a Java array as a parameter.

$ mvn -q exec:java 
/home/janbodnar/tmp/data.csv
Geometric mean: 3.412562
Arithmetic mean: 4.168750
Max: 8.700000
Min: 1.000000
Sum: 66.700000
Variance: 6.158292

This is the output.

In this tutorial, we have created a simple Java console application, which computes basic statistics from a CSV file.

You might also be interested in the following related tutorials: Java Log4j tutorial and Java tutorial.