2. 在程序中解析命令行参数¶
2.1. 编程中的参数¶
你可能理解函数参数的概念。但程序本身是如何拥有参数的呢?这来自每个 Java 程序都有的 Main 函数。把它看成程序的 "启动"(launch)函数。通常这个 "main" 函数名为 Main,并以一个字符串数组 作为其参数,就像这样:
public static void main(String[] args)
所以当你从终端启动命令时,它会传入一个数组,包含所有附加信息(通常还会去掉空白字符)。 所以如果我运行
那么 args 就是一个数组,包含:
{"-l", "file.txt"}
注意,这一点对 Java 成立,但对 C 或 C++ 来说略有不同。在 C 中,你得到的第一个参数总是命令名, 所以在 C 中你的数组会是:
{"ls", "-l", "file.txt"}
不过 Java 会去掉命令名,只提供参数。
我为你在项目中准备了一个 main 函数骨架。它的搭建很简单,并且用到了 switch 分支。你可以 下载它。让我们看看它是如何工作的。
public class MainParameters {
public static void main(String[] args) {
int count = 0; // Set our counter
if (args.length < 1) {
// No parameters is this a problem?
}
while(count < args.length) { // While we have not reached the end of our arguments keep going.
switch(args[count]) {
case "-h": // Display help info
System.out.println("This is the help message. Proper command syntax:");
System.out.println("cmdline -v: Displays version information");
System.out.println("cmdline -h: Displays this help message");
System.out.println("cmdline -f [file]: Sets file to file provided");
count++;
break;
case "-v": // Display version information
System.out.println("Cmdline parse sample version 1.0.0");
count++;
break;
case "-f": // This is an example to show you how to handle when you have a parameter that takes info
String fileName = args[count+1]; // We are getting the filename so set it to the string after -f
System.out.println("Input file is " + fileName); // Print out info
count = count + 2; // Increment counter to next item (skipping filename).
// Note this provides no bounds checking so if you pass the parameter without file info it may bomb if at the end
// You may also surround it in a try/catch for safety.
break;
default: // If none of your cases match then this is an unrecognized parameter and we will exit.
System.out.println("Unrecognized parameter " + args[count] + "\nExiting.");
System.exit(-1);
break;
}
}
}
}
我们的 main 函数以一个字符串数组(名为 args)作为参数。 如果这个数组为空,由于我们没有任何参数,可以(也可以不)选择退出。 接着它会进入一个 while 循环,遍历所有参数。 这个循环的语法很有用,因为它不会把参数锁定在某个固定顺序中。 你可以按任意方式调用它们。 switch 语句让你能轻松地为每个参数编写处理逻辑,并利用 default 分支为无法识别的参数 添加一个 case。 在这个例子中,我选择在打印出无法识别的字符串后退出。 以后你也许想把它改成别的处理方式。 你可以进一步了解 switch 语句。 还有一点很重要:如果你使用了 "-f" 却没有提供文件名,这个函数可能会抛出异常,或以意想不到的 方式运行。 例如,如果你用 {"-f", "-v"} 调用程序,它会把文件名设为 -v。 或者如果你用 {"-f"} 调用程序,会因试图访问数组范围之外而得到一个异常。 你可以使用 try-catch 块来防止这种情况。 一旦设置好你的参数,就可以调用相应的方法来启动程序。
