DEV Community

loading...
Cover image for Simple Java Command Line Argument Parser Implementation

Simple Java Command Line Argument Parser Implementation

oshanoshu profile image Oshan Upreti Originally published at oshanoshu.github.io ・3 min read

Here, we will create a Custom CommandLineParser class to parse the arguments passed via the command line in Java.

Let's first see the sample entry point for the Java program.

public class MyProgram{
    public static void main(String args[])
    {
        System.out.println("This is my program.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Ever wondered why do we need to pass an array of strings as arguments in main method of Java?

It's for the command line arguments. When you run your Java program from the command line:

java MyProgram Oshan 
Enter fullscreen mode Exit fullscreen mode

It takes "Oshan" as an argument. So, if you want your program to access this String, you can access it using the array of String passed in the main method.

// inside main method 
    //Prints "My name is Oshan"
    System.out.println("My name is ", args[0]);
Enter fullscreen mode Exit fullscreen mode

You can pass the initial configuration you want your Java program to follow via command-line arguments. For example:

## if you want to send file path
java MyProgram -filePath file1.txt 

## if you want to send multiple file paths
java MyProgram -filePath file1.txt file2.txt 

## or, if you just want to send flags 
java MyProgram -noprint 
Enter fullscreen mode Exit fullscreen mode

By default, Java takes each string as an argument and cannot differentiate between argument names, values, or flags. So, today, we'll write a simple program that will parse the arguments passed through the command line. This way we don't have to hard code the values of the arguments as args[1] or args[2] in our program. Instead, we will be able to see the argument list and choose values using argument names rather than an array of strings.

Here is the code:

import java.util.HashMap;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

public class CommandLineParser {
    List <String> args = new ArrayList<>();
    HashMap<String, List<String>> map = new HashMap<>();
    Set<String> flags = new HashSet<>();

    CommandLineParser(String arguments[])
    {
        this.args = Arrays.asList(arguments);
        map();
    }

    // Return argument names
    public Set<String> getArgumentNames()
    {
        Set<String> argumentNames = new HashSet<>();
        argumentNames.addAll(flags);
        argumentNames.addAll(map.keySet());
        return argumentNames;
    }

    // Check if flag is given
    public boolean getFlag(String flagName)
    {
        if(flags.contains(flagName))
            return true;
        return false;
    }

    // Return argument value for particular argument name
    public String[] getArgumentValue(String argumentName)
    {
        if(map.containsKey(argumentName))
            return map.get(argumentName).toArray(new String[0]);
        else
            return null;
    }

    // Map the flags and argument names with the values 
    public void map()
    {
        for(String arg: args)
        {
            if(arg.startsWith("-"))
            {
                if (args.indexOf(arg) == (args.size() - 1))
                {
                    flags.add(arg.replace("-", ""));
                }
                else if (args.get(args.indexOf(arg)+1).startsWith("-"))
                {
                    flags.add(arg.replace("-", ""));
                }
                else
                {
                    //List of values (can be multiple)
                    List<String> argumentValues = new ArrayList<>();
                    int i = 1;
                    while(args.indexOf(arg)+i != args.size() && !args.get(args.indexOf(arg)+i).startsWith("-"))
                    {
                        argumentValues.add(args.get(args.indexOf(arg)+i));
                        i++;
                    }
                    map.put(arg.replace("-", ""), argumentValues);
                }
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Now, you can add the above class to any program you want and easily parse the values.

Let's try with a simple program:

public class MyProgram
{
    public static void main (String args[])
    {
        CommandLineParser clp = new CommandLineParser(args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Make sure you include the CommandLineParser class in the classpath when you compile your program.

javac -classpath /pathToTheCommandLineParserClass MyProgram.java

java MyProgram.java -name Oshan -prints 3 -test
Enter fullscreen mode Exit fullscreen mode

Now, in our program you can easily get these values and use it.

// inside main method
    String name = clp.getArgumentValue("name");
    int prints = Integer.parseInt(clp.getArgumentValue("prints"));
    boolean isTest = clp.getFlag("test");

    if(isTest)
        System.out.println("This is only a test");

    for(int i = 0; i < prints; i++)
    {
        System.out.print(name+" ");
    }
Enter fullscreen mode Exit fullscreen mode

The output of the above program will be:

This is only a test
Oshan
Oshan
Oshan
Enter fullscreen mode Exit fullscreen mode

You can also use the method getArgumentNames to see the passed argument names.

I recently encountered a problem that made me write this custom CommandLineParser. Obviously, you can modify this to fit your requirements or go with the traditional approach. But, making such class removes the ambiguity when multiple arguments are passed via command line.

I hope you find this useful.

Thanks for reading.

Discussion (0)

pic
Editor guide