Command Line Parameters: A Java Approach

August 29, 2013 - Programming

Parameters and Arguments passed on the command line are something that we simply cannot seem to get rid of. Even with today’s UI-Centric Operating System and interaction Model, Application still expose a number of features through the use of Command-Line parameters and arguments.

There are a number of relatively complex libraries for dealing with Command Line parameters in any number of languages, most of which aim for the typical Command-line stuff; switches, switches with arguments, etcetera. Many of these are relatively complex; I created a COM Component in VB6 to parse Command Line Parameters and I believe I even created a C# Port to a self-contained file for some of my C# applications.

There is of course a simpler way of creating, parsing, and evaluating the arguments you are provided on the commandline, though many shrink from the idea- it involves simply changing up how you interpret arguments. Rather than switches, you instead simply interpret all your arguments as a set of key/value pairs.

Most Programming language environments will perform the task of actually splitting your command line at spaces. You have to workaround this since it might interfere with your own parsing. Some languages provide a way to directly access the CommandLine your application ran with, as a single string. Others, like Java, require you to simply paste together the arguments you are provided and hope for the best. (Java also has an anomoly when you are trying to pass arguments through a “java -jar” or “javaw -jar” call, too, but I’ll get to that in a moment).

The method I’ve found ideal is to simply have a method that accepts a string and then returns a HashMap consisting of key/value pairs, as present in the commandline. Both keys and values can be quoted to allow for spaces in their names, too. Here is a Java implementation of that Method:

The logic is exceedingly similar to some of the logic that was involved in my BASeParser XP Expression Evaluator. The ubiquitous “inquote” boolean makes a cameo in this Java implementation. the basic idea is that when it finds a quote, it toggles “inquote”; and it will only recognize separators (spaces) and equals signs (used to separate keys from values) when inquote is false. If it finds a space, it will take what it has for a key and the value it’s building and add those to the HashMap it is building. If it finds an equals sign, it will take what it’s currently got in ValueRunner and throw it into the Key. the purpose being to allow the key and name to be enclosed in quotes if they contain spaces, so they don’t get split apart.

An example usage would require the original command line to be rebuilt:

This works by simply rebuilding the arguments Java has so helpfully split for us.

HOWEVER: this does have some caveats. The first seems to be that Java removes the quotations around any quotes entries, and it obviously get’s confused by our non-standard arguments. So we need a custom Join method for this task:

OK so maybe the Join I had was a lot simpler and just a standard Join() that didn’t take spaces and add quotes to each one if they were found. I only realized the caveat involving quotes (which explains the massive mystery that took me 3 hours to solve this morning, which I ended up chalking up to a known netbeans bug, which no doubt did not help clarify the problems I was having. Ideally I would be able to get the pure unfiltered and untainted Command Line; (sort of like .NET’s Environment.CommandLine Property) But there doesn’t appear to be a good way to do that in Java, as near as I can tell, which is a shame.

And that’s that: Now you have a method to parse a command line like this:

Which will give us these pairs:

Key Value
Username billy
password Hunter42
main weapon slarpy Gun

Tada! And now you can add helper methods, or encapsulate this functionality into a class and give it those helper methods, for all sorts of different features that manipulate or return given parameters or sets of command parameters. I personally have a “popParameter()” method that takes the hashmap, a key name, and a default value, and will retrieve the existing value of the given key if found and remove it or if not found return the default value.

Have something to say about this post? Comment!