Java 控制台应用教程显示了如何创建 Java 控制台应用。 该应用计算一些统计信息。
Java 控制台示例
以下示例创建一个 Java 控制台应用,该应用从 CSV 文件读取数据并计算一些基本统计信息。
该示例使用 Apache Commons 库来解析命令行参数,进行数学运算和转换数据。 OpenCSV 库用于读取 CSV 数据。
src/resources/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
这是数据文件。 文件名将是我们程序的控制台参数。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ JavaStatsEx.java
│ │ MyStatsApp.java
│ └───resources
│ data.txt
└───test
└───java
这是项目结构。
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>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
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
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
。
CommandLine line = parseArguments(args);
parseArguments()
方法解析命令行参数。 它返回CommandLine
,它代表针对Options
描述符解析的参数列表。
if (line.hasOption("filename")) {
System.out.println(line.getOptionValue("filename"));
String fileName = line.getOptionValue("filename");
double[] data = readData(fileName);
calculateAndPrintStats(data);
} else {
printAppHelp();
}
该应用具有强制性的文件名选项,该选项指向要读取的文件并从中计算统计信息。 如果不存在,我们将提供应用帮助消息。
Options options = getOptions();
getOptions()
方法返回应用的选项。
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
对象中返回已解析的参数。
try (var reader = Files.newBufferedReader(Paths.get(fileName));
var csvReader = new CSVReaderBuilder(reader).build()) {
CSVReader
用于读取 CSV 数据。
String[] nextLine;
while ((nextLine = csvReader.readNext()) != null) {
for (String e : nextLine) {
data.add(Double.parseDouble(e));
}
}
在此 while 循环中,我们逐行读取 CSV 文件,并将数据解析为Double
值列表。
mydata = ArrayUtils.toPrimitive(data.toArray(new Double[0]));
我们需要原始数据类型来计算统计信息。 因此,我们将列表转换为原始双精度值数组。 ArrayUtils
来自 Apache Commons Lang 库。
private Options getOptions() {
var options = new Options();
options.addOption("f", "filename", true, "file name to load data from");
return options;
}
getOptions()
提供应用选项。
private void printAppHelp() {
Options options = getOptions();
var formatter = new HelpFormatter();
formatter.printHelp("JavaStatsEx", options, true);
}
printAppHelp()
打印应用的帮助。 它使用HelpFormatter
来完成工作。
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 数组作为参数。
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 文件计算基本统计信息。