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

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

Java 控制台示例

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

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

src/resources/data.csv

  1. 2.3, 3.5, 5, 6.7, 3.2, 1.2, 6.7, 7.8
  2. 4.5, 2.1, 6.6, 8.7, 3.2, 1.0, 1.2, 3

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

  1. pom.xml
  2. src
  3. ├───main
  4. ├───java
  5. └───com
  6. └───zetcode
  7. JavaStatsEx.java
  8. MyStatsApp.java
  9. └───resources
  10. data.txt
  11. └───test
  12. └───java

这是项目结构。

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <groupId>com.zetcode</groupId>
  8. <artifactId>javastatsex</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <properties>
  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12. <maven.compiler.source>12</maven.compiler.source>
  13. <maven.compiler.target>12</maven.compiler.target>
  14. </properties>
  15. <dependencies>
  16. <dependency>
  17. <groupId>commons-cli</groupId>
  18. <artifactId>commons-cli</artifactId>
  19. <version>1.4</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>com.opencsv</groupId>
  23. <artifactId>opencsv</artifactId>
  24. <version>4.6</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.apache.commons</groupId>
  28. <artifactId>commons-math3</artifactId>
  29. <version>3.6.1</version>
  30. </dependency>
  31. </dependencies>
  32. </project>

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

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

com/zetcode/JavaStatsEx.java

  1. package com.zetcode;
  2. /**
  3. * Starter class for MyStats application.
  4. *
  5. * @author janbodnar
  6. */
  7. public class JavaStatsEx {
  8. /**
  9. * Application entry point.
  10. *
  11. * @param args application command line arguments
  12. */
  13. public static void main(String[] args) {
  14. var app = new MyStatsApp();
  15. app.run(args);
  16. }
  17. }

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

com/zetcode/MyStatsApp.java

  1. package com.zetcode;
  2. import com.opencsv.CSVReaderBuilder;
  3. import org.apache.commons.cli.CommandLine;
  4. import org.apache.commons.cli.CommandLineParser;
  5. import org.apache.commons.cli.DefaultParser;
  6. import org.apache.commons.cli.HelpFormatter;
  7. import org.apache.commons.cli.Options;
  8. import org.apache.commons.cli.ParseException;
  9. import org.apache.commons.lang3.ArrayUtils;
  10. import org.apache.commons.math3.stat.StatUtils;
  11. import java.io.IOException;
  12. import java.nio.file.Files;
  13. import java.nio.file.Paths;
  14. import java.util.ArrayList;
  15. /**
  16. * MyStatsApp is a simple console application which computes
  17. * basic statistics of a series of data values. The application takes
  18. * a file of data as its single argument.
  19. *
  20. * @author janbodnar
  21. */
  22. public class MyStatsApp {
  23. /**
  24. * Runs the application
  25. *
  26. * @param args an array of String arguments to be parsed
  27. */
  28. public void run(String[] args) {
  29. CommandLine line = parseArguments(args);
  30. if (line.hasOption("filename")) {
  31. System.out.println(line.getOptionValue("filename"));
  32. String fileName = line.getOptionValue("filename");
  33. double[] data = readData(fileName);
  34. calculateAndPrintStats(data);
  35. } else {
  36. printAppHelp();
  37. }
  38. }
  39. /**
  40. * Parses application arguments
  41. *
  42. * @param args application arguments
  43. * @return <code>CommandLine</code> which represents a list of application
  44. * arguments.
  45. */
  46. private CommandLine parseArguments(String[] args) {
  47. Options options = getOptions();
  48. CommandLine line = null;
  49. CommandLineParser parser = new DefaultParser();
  50. try {
  51. line = parser.parse(options, args);
  52. } catch (ParseException ex) {
  53. System.err.println("Failed to parse command line arguments");
  54. System.err.println(ex.toString());
  55. printAppHelp();
  56. System.exit(1);
  57. }
  58. return line;
  59. }
  60. /**
  61. * Reads application data from a file
  62. *
  63. * @param fileName file of application data
  64. * @return array of double values
  65. */
  66. private double[] readData(String fileName) {
  67. var data = new ArrayList<Double>();
  68. double[] mydata = null;
  69. try (var reader = Files.newBufferedReader(Paths.get(fileName));
  70. var csvReader = new CSVReaderBuilder(reader).build()) {
  71. String[] nextLine;
  72. while ((nextLine = csvReader.readNext()) != null) {
  73. for (String e : nextLine) {
  74. data.add(Double.parseDouble(e));
  75. }
  76. }
  77. mydata = ArrayUtils.toPrimitive(data.toArray(new Double[0]));
  78. } catch (IOException ex) {
  79. System.err.println("Failed to read file");
  80. System.err.println(ex.toString());
  81. System.exit(1);
  82. }
  83. return mydata;
  84. }
  85. /**
  86. * Generates application command line options
  87. *
  88. * @return application <code>Options</code>
  89. */
  90. private Options getOptions() {
  91. var options = new Options();
  92. options.addOption("f", "filename", true, "file name to load data from");
  93. return options;
  94. }
  95. /**
  96. * Prints application help
  97. */
  98. private void printAppHelp() {
  99. Options options = getOptions();
  100. var formatter = new HelpFormatter();
  101. formatter.printHelp("JavaStatsEx", options, true);
  102. }
  103. /**
  104. * Calculates and prints data statistics
  105. *
  106. * @param data input data
  107. */
  108. private void calculateAndPrintStats(double[] data) {
  109. System.out.format("Geometric mean: %f%n", StatUtils.geometricMean(data));
  110. System.out.format("Arithmetic mean: %f%n", StatUtils.mean(data));
  111. System.out.format("Max: %f%n", StatUtils.max(data));
  112. System.out.format("Min: %f%n", StatUtils.min(data));
  113. System.out.format("Sum: %f%n", StatUtils.sum(data));
  114. System.out.format("Variance: %f%n", StatUtils.variance(data));
  115. }
  116. }

这是MyStatsApp

  1. CommandLine line = parseArguments(args);

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

  1. if (line.hasOption("filename")) {
  2. System.out.println(line.getOptionValue("filename"));
  3. String fileName = line.getOptionValue("filename");
  4. double[] data = readData(fileName);
  5. calculateAndPrintStats(data);
  6. } else {
  7. printAppHelp();
  8. }

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

  1. Options options = getOptions();

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

  1. try {
  2. line = parser.parse(options, args);
  3. } catch (ParseException ex) {
  4. System.err.println("Failed to parse command line arguments");
  5. System.err.println(ex.toString());
  6. printAppHelp();
  7. System.exit(1);
  8. }
  9. return line;

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

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

CSVReader用于读取 CSV 数据。

  1. String[] nextLine;
  2. while ((nextLine = csvReader.readNext()) != null) {
  3. for (String e : nextLine) {
  4. data.add(Double.parseDouble(e));
  5. }
  6. }

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

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

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

  1. private Options getOptions() {
  2. var options = new Options();
  3. options.addOption("f", "filename", true, "file name to load data from");
  4. return options;
  5. }

getOptions()提供应用选项。

  1. private void printAppHelp() {
  2. Options options = getOptions();
  3. var formatter = new HelpFormatter();
  4. formatter.printHelp("JavaStatsEx", options, true);
  5. }

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

  1. private void calculateAndPrintStats(double[] data) {
  2. System.out.format("Geometric mean: %f%n", StatUtils.geometricMean(data));
  3. System.out.format("Arithmetic mean: %f%n", StatUtils.mean(data));
  4. System.out.format("Max: %f%n", StatUtils.max(data));
  5. System.out.format("Min: %f%n", StatUtils.min(data));
  6. System.out.format("Sum: %f%n", StatUtils.sum(data));
  7. System.out.format("Variance: %f%n", StatUtils.variance(data));
  8. }

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

  1. src/main/resources/data.txt
  2. Geometric mean: 3.412562
  3. Arithmetic mean: 4.168750
  4. Max: 8.700000
  5. Min: 1.000000
  6. Sum: 66.700000
  7. Variance: 6.158292

这是输出。

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

列出所有 Java 教程