# Java 控制台应用

原文：http://zetcode.com/java/console/

Java 控制台应用教程显示了如何创建 Java 控制台应用。 该应用计算一些统计信息。

## Java 控制台示例

以下示例创建一个 Java 控制台应用，该应用从 CSV 文件读取数据并计算一些基本统计信息。

该示例使用 Apache Commons 库来解析命令行参数，进行数学运算和转换数据。 OpenCSV 库用于读取 CSV 数据。

`src/resources/data.csv`

```java
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

```

这是数据文件。 文件名将是我们程序的控制台参数。

```java
pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │               JavaStatsEx.java
│   │               MyStatsApp.java
│   └───resources
│           data.txt
└───test
    └───java

```

这是项目结构。

`pom.xml`

```java
<?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>javastatsex</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>12</maven.compiler.source>
        <maven.compiler.target>12</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.6</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.6.1</version>
        </dependency>

    </dependencies>

</project>

```

在`pom.xml`文件中，我们定义了应用的依赖项。 `commons-cli`工件用于解析命令行参数，`opencsv`用于读取 CSV 数据，`commons-math`用于统计计算，`commons-lang3`用于将列表转换为数组。

`exec-maven-plugin`从 Maven 执行 Java 程序。 在`arguments`标签中，我们为应用提供了选项和文件名。

`com/zetcode/JavaStatsEx.java`

```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) {

        var app = new MyStatsApp();
        app.run(args);
    }
}

```

`JavaStatsEx`是应用入口点。 它创建`MyStatsApp`的实例，并将其传递给应用参数。

`com/zetcode/MyStatsApp.java`

```java
package com.zetcode;

import com.opencsv.CSVReaderBuilder;
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;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;

/**
 * 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 application arguments
     * @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("Failed to parse command line arguments");
            System.err.println(ex.toString());
            printAppHelp();

            System.exit(1);
        }

        return line;
    }

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

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

        try (var reader = Files.newBufferedReader(Paths.get(fileName));
             var 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[0]));

        } catch (IOException ex) {

            System.err.println("Failed to read file");
            System.err.println(ex.toString());
            System.exit(1);
        }

        return mydata;
    }

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

        var 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();

        var 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));
    }
}

```

这是`MyStatsApp`。

```java
CommandLine line = parseArguments(args);

```

`parseArguments()`方法解析命令行参数。 它返回`CommandLine`，它代表针对`Options`描述符解析的参数列表。

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

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

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

} else {
    printAppHelp();
}

```

该应用具有强制性的文件名选项，该选项指向要读取的文件并从中计算统计信息。 如果不存在，我们将提供应用帮助消息。

```java
Options options = getOptions();

```

`getOptions()`方法返回应用的选项。

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

} catch (ParseException ex) {

    System.err.println("Failed to parse command line arguments");
    System.err.println(ex.toString());
    printAppHelp();

    System.exit(1);
}

return line;

```

`CommandLineParser`解析命令行参数。 如果存在`ParseException`，则应用退出。 解析器在`CommandLine`对象中返回已解析的参数。

```java
try (var reader = Files.newBufferedReader(Paths.get(fileName));
    var csvReader = new CSVReaderBuilder(reader).build()) {

```

`CSVReader`用于读取 CSV 数据。

```java
String[] nextLine;

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

    for (String e : nextLine) {

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

```

在此`while`循环中，我们逐行读取 CSV 文件，并将数据解析为`Double`值列表。

```java
mydata = ArrayUtils.toPrimitive(data.toArray(new Double[0]));

```

我们需要原始数据类型来计算统计信息。 因此，我们将列表转换为原始双精度值数组。 `ArrayUtils`来自 Apache Commons Lang 库。

```java
private Options getOptions() {

    var options = new Options();

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

```

`getOptions()`提供应用选项。

```java
private void printAppHelp() {

    Options options = getOptions();

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

```

`printAppHelp()`打印应用的帮助。 它使用`HelpFormatter`来完成工作。

```java
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));
}

```

使用`StatUtils()`，我们可以计算一些统计数据。 `StatUtils()`采用 Java 数组作为参数。

```java
src/main/resources/data.txt
Geometric mean: 3.412562
Arithmetic mean: 4.168750
Max: 8.700000
Min: 1.000000
Sum: 66.700000
Variance: 6.158292

```

这是输出。

在本教程中，我们创建了一个简单的 Java 控制台应用，该应用从 CSV 文件计算基本统计信息。

列出[所有 Java 教程](/all/#java)。