How to Use Command Line Arguments to Dictate Flow of Program? - java

I have scoured all of Google it seems and I cannot find anything regarding how to use command line arguments to tell the Java program which subsequent method to perform. I am trying to create a Java program with several different aspects of a student grading application.
The main program is a GUI form where the user can input grades for each student in a specific class. Along with this, I need a control program that accepts 3 command arguments. The first is a number to indicate the type of file to load (1. XML 2. JSON 3. TXT). The second is a letter to indicate the file material (C indicates Course data, S indicates Student data). The last argument is the name of the specific data file to upload, which will then be extracted and uploaded to a database to be used by the GUI program.
I have the rest of the program already coded except for the command arguments because I have absolutely no idea what I am doing. The command argument code is supposed to look something like this:
public class Load
{
//Define global variables
static String inputDataChoice;
static String inputTableChoice;
static String inputFileName;
public static void main(String[] arg)
{
if (userChose == arg[0], arg[3], arg[5])
{
//If user chose 1 (XML), S (Student), and xmltest.xml
//Go to ParseXMLStudentFile();
}
if (userChose == arg[1], arg[4], arg[6])
{
//If user chose 2 (JSON), C (Course), and jsontest.json
//Go to ParseJSONCourseFile();
}
if (userChose == arg[2], arg[3], arg[7])
{
//If user chose 3 (TXT), S (Student), and test.txt
//Go to ParseTXTStudentFile();
}
}
}
I know that the above code is bogus, but that is the general idea. How do I accept command arguments from the user and then use that input to decide which method is executed? Would this program use the console window to accept user input? Please help!

arg contains the parameters passed to the command line, i.e. if you call the prog with prog.jar XML S xmltest.xml:
String fileType = arg[0]; // == XML
String material = arg[1]; // == S
String fileName = arg[2]; // == xmltest.xml
if (fileType.equals("XML") && material.equals("S")) {
parseXMLStudentFile(fileName);
} else { // ...
}

Related

Exception handling when dealing with user input for a beginner

I have to do a little program based in a shop, I have to add new clients to the shop customer collection, new items to the shop stock, edit them etc, so I use user input(scanner) to create this new objects. I have all the methods I need for this already without exceptions.
I would like some simple java exception handling for when the user introduces a string were he is supposed to enter a integer or viceversa.
For example if I'm executing a method to create a item for the shop and when I ask the user to introduce the stock(integer) the user types hello instead of a number the program crashes, I would like to handle the exception, show a error message, don't create the object and relaunch the item creation method from the beggining(or relaunch the submenu it was right before)
should I use try and catch? the method in try, when it fails catch throws message of error and relaunches the item creation menu? How should i do this? I've been searching and found a interesting method for integers here:
Exception Handling for no user input in Java
The problem is I don't know how I could handle possible exceptions for when introducing the ID for the user(which would be a string composed of 8 numbers and a letter like for example: 13234354A, so how could I show a error if a user introduces "sjadsjasdj" as a ID instead of something sort of realistic ) or some other things like handling exceptions for a few enum or boolean variables I use when creating this objects.
I've been looking in this site and searching google but I haven't found what I need or are more complex than what I understand with my little knowledge, also English is not my native language so my searches may be a little off.
Thanks for your time!
When you are reading the input just read in the the entire ID 123A for example and verify that each character is valid using for example Character.isDigit() and Character.isLetter(). With a 4 letter case
import java.util.Scanner;
public class Test {
public static void main(String[]args) {
boolean flag = false;
Scanner kb = new Scanner(System.in);
while(!flag) {
String id = kb.next();//To get the next word
flag = true;//by default its assumed to be valid input
if(id.length() == 4) {
for(int i = 0; i < 3; i++) {
if(!Character.isDigit(id.charAt(i))) {
flag = false;
}
}
if(!Character.isLetter(id.charAt(3))) {
flag = false;
}
}
else {
flag = false;
}
System.out.println("ID is "+ (flag == true?"Valid":"Invalid"));
}
}
}
Output
1234
ID is Invalid
123A
ID is Valid
You could throw your own error at the end if you want or just loop back to the beginning to take a new input.

Getting input from users command and using .equals

Im trying to read the users input from the command box of my program and based on what the user enters into this command box the program should output appropriate messages. For example when the user enters quit the program is supposed to stop and I have implemented this correctly. SO what I am trying to achieve is when the users doesnt enter the words :"QUIT", "ROLL","property", "Buy" , "help" "done ,"balance" the program should displau an error message.
I need the command to work simultaneously so that if any 7 commands entered an appropriate message is returned
Here is my code so far:Thanks ,
private void echo () {
String command ;
String command2;
ui.display();
ui.displayString("ECHO MODE");
do {
command = ui.getCommand();
ui.displayString(command);
} while (!command.equals("quit"));
{
ui.displayString("The game is over.");
}
do{
command = ui.getCommand();
ui.displayString(command);
}while (!command.equals("help")||(!command.equals("buy"))||(!command.equals("roll"))||(!command.equals("done"))||(!command.equals("property"))||(!command.equals("balance")));
{
ui.displayString("Please enter a valid command");
}
return;
Your last do/while's condition looks almost good, but it should be using && instead of || : you want to display the error message when the command input isn't the first expected one, and not the second expected one, etc.
A prettier syntax would be to use a List of accepted commands and check whether it contains the received command :
List<String> acceptedCommands = new ArrayList<>();
acceptedCommands.add("help");
acceptedCommands.add("quit");
// [...]
do { command = ui.getCommand(); }
while (!acceptedCommands.contains(command));
Note that the do/while construct is rarely used (altough it can sometime be more appropriate than a standard while) and that you seem to misuse it ; you've used twice that same pattern :
do { actions }
while (condition)
{ more actions }
This is probably not doing what you want, since the last block isn't part of the do/while but just an anonymous code block, with its own scope but not much else.
After discussion I think you want something along those lines :
private void echo() {
String command = null;
while (!"quit".equals(command)) {
command = ui.getCommand();
if (!acceptedCommands.contains(command)) {
ui.displayString("Please enter a valid command");
} else if (!"quit".equals(command)) {
// handle other commands
}
}
ui.displayString("The game is over.");
// no need for "return;", it's implicit
}

Calling a Translate Program using a Dictionary program that will be called back to program

I am a complete noob in coding and I was wondering if I can get some help
I have this project see and basically what I need to do is:
Create 2 executable programs. A Translate Program, and a Dictionary Program. The programs can be written in any language.
The Translate program will pass the Dictionary program an English word. The Dictionary program will translate and return a foreign word. The Translate program will print out the English word and it’s translation into a file.
The Dictionary program will look up the English word and return its translation in foreign language. The Dictionary program will have the ability to translate a selected number of English words into another language. The language the Dictionary program will translate English words to will be determined by the student. The Dictionary program will have the ability to translate at least 15 English words into a foreign language. "
Right now I am having trouble having the Dictionary program call the Translate program.
My instructor told us to use the statement
Process proc = Runtime.getRuntime().exec("java -jar Translate.jar");
InputStream in = proc.getInputStream();
InputStream err= proc.getErrorStream();
Currently the problem is that my program doesn't seem to have access to the jar file.
I am using Eclipse and Windows 7
The steps I did to create the Translate jar file was to
right-click the Translate project
export
Selected Runnable Jar File
Chose Dictionary - Dictionary as the Launch configuration
Typed in Dictionary\Translate.jar as the Export Destination
Clicked finish and then proceeded to try and use Process runtime
Right now I only have pseudo-codes for both programs but I am focusing on figuring out how to call the translate program.
Dictionary.java
public class Dictionary {
public static void main(String [] args){
/******************
* Dictionary Program
* Will translate and return a foreign word back
* to the Translate program that this Program is calling.
* It will look up the English word. The Dictionary will use
* Elvish as the foreign language that is being translated.
* Should be able to translate 15 english words.
*/
/**********************************************************
/* External Module code calls Translate and gets output
*from module
/*********************************************************/
/* try
{
// Run a java app in a separate system process
Process proc = Runtime.getRuntime().exec("java -jar Translate.jar");
// Then retreive the process output
InputStream in = proc.getInputStream();
InputStream err= proc.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String EngWord = reader.readLine(); //EngWord is the variable sent from the Translate program
while ( (EngWord = reader.readLine()) != null)
do //Pseudo-code of (If, Else Statements provided below)
/**********************************************************************
* Pseudo-code
**********************************************************************/
String EngWord = "Should be a variable that the Translate Program is passing that is the english word";
String foreignWord = "A variable created by this Diction program that will be sent back to the Translate program";
if (EngWord == "dog") {
foreignWord = "elvish equivalent";
} else if (EngWord == "cat") {
foreignWord = "cat in elvish";
} else if (EngWord == "tree"){
foreignWord = "tree in elven";
} else {
EngWord = "nothing? something that can end the loop well";
// I guess this is where the loop must terminate
}
//Must find a way to return the foreignWord back to Translate
/*
} catch (Throwable e){
e.printStackTrace();
}
*/
}
}
Translate.java
public class Translate {
/**************************
* Translate program will pass the Dictionary program
* an English word. When the Dictionary program translate and returns an Elvish word
* This program will print out the English word and its translation into a file
*
*/
public static void main(String [] args) {
//Must find a way to pass the english word to Dictionary
String EngWord = "This is the variable being sent to the Dictionary program...use as parameter?";
//Must use some type of Writer class in order to write the output of both the EngWord and foreignWord
//into an Output file
String foreignWord = "THis is the variable being sent back from the Dictionary program";
//perhaps use runtime before this so Translate can retreive foreignWord from Dictionary?
//Some type of algorithm that will write both the foreignWord and Engword onto an output file.
//Prints (Writes) out to "output.txt"
}
}
If I am not allowed to receive such amount of help can someone perhaps tell me what other websites I may be allowed to post this request?

Handle one or multiple words in Java Socket .readLine()

I am building an application where I have a server and a client that talk to each other -over telnet. (via socket). The server program is monitoring a tank of some gass, and sends temperature level and preassure level via socket to the accepted clients.
I have managed to get the client and server to talk to each other when I write stuff --in telnet--, but...
I need some help to handle the data that I send.
I have made a loginscript to determine if the user is a valid user or not.
So I can write two words like "myname" "space" "mypassword" and I get a green light and returns a valid user.
But when I only write one word, and hit enter, it gives me:
Exeption in thread... java.lang.Array.IndexOutOfBoundsExeption EXEPT for when I write exit or logout!
(All users are hardcoded in the script for ease of use for testing. (The login script works fine by it self, and returns valid user = false when I write something wrong.)
Here is my code. Some pseudo code is added since I am not 100% sure of what to do...;)
String telNetCommand = dataIn.readLine();
System.out.println(telNetCommand);
String dataInArray[] = telNetCommand.split(" ");
user.isValid(dataInArray[0], dataInArray[1]);
if (dataInArray[1] == "\n") {
//Ignore login request and continue telnet-logging?
}
The client application has a button for each command, like:
"Send me every n'th data", or "Send me a batch of data every n'th second. If command equals exit, or logout - > break operation....
// --------------// USER INPUT FROM CLIENT APP //--------------------------//
// --------------// CONTINUE ? //----------------------------//
if (command.equals("CONTINUE")) {
continueSession();
else { //..Kill session
}
}
// --------------// SKIP <N> //----------------------------//
if (command.equals("SKIP_N")) {
skipEveryNthData();
}
// --------------// BATCH <N> //---------------------------//
if (command.equals("BATCH_N")) {
batchEveryNthData();
}
// --------------// LOGG OUT #1 //-------------------------//
if (command.equals("logout") || command.equals("exit")) {
break;
}
Maybe I am getting a bit confused now, but I think that I need to put all data into an array, and check
if
dataInArray[0] == "CONTINUE"
dataInArray[0] == "SKIP_N", or
dataInArray[0] == "BATCH_N"
(then send some data back)...
and...
if dataInArray[1] == "enter" ("\n") execute the single word commands ...??
if dataInArray[0] == "LOG_IN" or "PASSWORD" check if valid user is true..
Thanks for any help, and/or tips! :)
In this part of your code:
String dataInArray[] = telNetCommand.split(" ");
user.isValid(dataInArray[0], dataInArray[1]);
You assume that the telNetCommand string contains a space. If it does not, dataInArray will only contain one element and dataInArray[1] will throw an IndexOutOfBoundsExeption.
You should check the size of the array:
if (dataInArray.length < 2) {
//no space in the command - do what you need to do
//for example an error message
}
The IndexOutOfBoundsExeption more than likely being caused by:
user.isValid(dataInArray[0], dataInArray[1]);
Make sure that the incoming String telNetCommand contains at least one space so that you have at 2 Strings in the array. You could do this checking the size of the array:
if (dataInArray.length < 2) {
throw new IllegalArgumentException(telNetCommand + " only contains " + dataInArray.length + " elements");
}
Also, on a different note, make sure to use String.equals when checking String content:
if ("\n".equals(dataInArray[1])) {
Thanks guys. I don't get any errors now... And here is what I ended up doing.
I had to set it == 2 in order not to get any errors.
while (true) {
String telnetCommand = dataIn.readLine();
System.out.println(telnetCommand);
String dataInArray[] = telnetCommand.split(" ");
if (dataInArray.length == 2) {
user.isValid(dataInArray[0], dataInArray[1]);
}
if (dataInArray.length < 2) {
if (telnetCommand.equals("CONTINUE")) {
continueThisSession();
System.out.println("Running method continueThisSession");
}
if (telnetCommand.equals("SKIP_N")) {
skipEveryNthData();
System.out.println("Running method skipEveryNthData");
}
if (telnetCommand.equals("BATCH_N")) {
batchEveryNthData();
System.out.println("Running method batchEveryNthData");
}
if (telnetCommand.equals("logout") || telnetCommand.equals("exit")) {
break;
}
}
}
Peace :)

Split a string containing command-line parameters into a String[] in Java

Similar to this thread for C#, I need to split a string containing the command line arguments to my program so I can allow users to easily run multiple commands. For example, I might have the following string:
-p /path -d "here's my description" --verbose other args
Given the above, Java would normally pass the following in to main:
Array[0] = -p
Array[1] = /path
Array[2] = -d
Array[3] = here's my description
Array[4] = --verbose
Array[5] = other
Array[6] = args
I don't need to worry about any shell expansion, but it must be smart enough to handle single and double quotes and any escapes that may be present within the string. Does anybody know of a way to parse the string as the shell would under these conditions?
NOTE: I do NOT need to do command line parsing, I'm already using joptsimple to do that. Rather, I want to make my program easily scriptable. For example, I want the user to be able to place within a single file a set of commands that each of which would be valid on the command line. For example, they might type the following into a file:
--addUser admin --password Admin --roles administrator,editor,reviewer,auditor
--addUser editor --password Editor --roles editor
--addUser reviewer --password Reviewer --roles reviewer
--addUser auditor --password Auditor --roles auditor
Then the user would run my admin tool as follows:
adminTool --script /path/to/above/file
main() will then find the --script option and iterate over the different lines in the file, splitting each line into an array that I would then fire back at a joptsimple instance which would then be passed into my application driver.
joptsimple comes with a Parser that has a parse method, but it only supports a String array. Similarly, the GetOpt constructors also require a String[] -- hence the need for a parser.
Here is a pretty easy alternative for splitting a text line from a file into an argument vector so that you can feed it into your options parser:
This is the solution:
public static void main(String[] args) {
String myArgs[] = Commandline.translateCommandline("-a hello -b world -c \"Hello world\"");
for (String arg:myArgs)
System.out.println(arg);
}
The magic class Commandline is part of ant. So you either have to put ant on the classpath or just take the Commandline class as the used method is static.
If you need to support only UNIX-like OSes, there is an even better solution. Unlike Commandline from ant, ArgumentTokenizer from DrJava is more sh-like: it supports escapes!
Seriously, even something insane like sh -c 'echo "\"un'\''kno\"wn\$\$\$'\'' with \$\"\$\$. \"zzz\""' gets properly tokenized into [bash, -c, echo "\"un'kno\"wn\$\$\$' with \$\"\$\$. \"zzz\""] (By the way, when run, this command outputs "un'kno"wn$$$' with $"$$. "zzz").
You should use a fully featured modern object oriented Command Line Argument Parser I suggest my favorite Java Simple Argument Parser. And how to use JSAP, this is using Groovy as an example, but it is the same for straight Java. There is also args4j which is in some ways more modern than JSAP because it uses annotations, stay away from the apache.commons.cli stuff, it is old and busted and very procedural and un-Java-eques in its API. But I still fall back on JSAP because it is so easy to build your own custom argument handlers.
There are lots of default Parsers for URLs, Numbers, InetAddress, Color, Date, File, Class, and it is super easy to add your own.
For example here is a handler to map args to Enums:
import com.martiansoftware.jsap.ParseException;
import com.martiansoftware.jsap.PropertyStringParser;
/*
This is a StringParser implementation that maps a String to an Enum instance using Enum.valueOf()
*/
public class EnumStringParser extends PropertyStringParser
{
public Object parse(final String s) throws ParseException
{
try
{
final Class klass = Class.forName(super.getProperty("klass"));
return Enum.valueOf(klass, s.toUpperCase());
}
catch (ClassNotFoundException e)
{
throw new ParseException(super.getProperty("klass") + " could not be found on the classpath");
}
}
}
and I am not a fan of configuration programming via XML, but JSAP has a really nice way to declare options and settings outside your code, so your code isn't littered with hundreds of lines of setup that clutters and obscures the real functional code, see my link on how to use JSAP for an example, less code than any of the other libraries I have tried.
This is a direction solution to your problem as clarified in your update, the lines in your "script" file are still command lines. Read them in from the file line by line and call JSAP.parse(String);.
I use this technique to provide "command line" functionality to web apps all the time. One particular use was in a Massively Multiplayer Online Game with a Director/Flash front end that we enabled executing "commands" from the chat like and used JSAP on the back end to parse them and execute code based on what it parsed. Very much like what you are wanting to do, except you read the "commands" from a file instead of a socket. I would ditch joptsimple and just use JSAP, you will really get spoiled by its powerful extensibility.
/**
* [code borrowed from ant.jar]
* Crack a command line.
* #param toProcess the command line to process.
* #return the command line broken into strings.
* An empty or null toProcess parameter results in a zero sized array.
*/
public static String[] translateCommandline(String toProcess) {
if (toProcess == null || toProcess.length() == 0) {
//no command? no string
return new String[0];
}
// parse with a simple finite state machine
final int normal = 0;
final int inQuote = 1;
final int inDoubleQuote = 2;
int state = normal;
final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
final ArrayList<String> result = new ArrayList<String>();
final StringBuilder current = new StringBuilder();
boolean lastTokenHasBeenQuoted = false;
while (tok.hasMoreTokens()) {
String nextTok = tok.nextToken();
switch (state) {
case inQuote:
if ("\'".equals(nextTok)) {
lastTokenHasBeenQuoted = true;
state = normal;
} else {
current.append(nextTok);
}
break;
case inDoubleQuote:
if ("\"".equals(nextTok)) {
lastTokenHasBeenQuoted = true;
state = normal;
} else {
current.append(nextTok);
}
break;
default:
if ("\'".equals(nextTok)) {
state = inQuote;
} else if ("\"".equals(nextTok)) {
state = inDoubleQuote;
} else if (" ".equals(nextTok)) {
if (lastTokenHasBeenQuoted || current.length() != 0) {
result.add(current.toString());
current.setLength(0);
}
} else {
current.append(nextTok);
}
lastTokenHasBeenQuoted = false;
break;
}
}
if (lastTokenHasBeenQuoted || current.length() != 0) {
result.add(current.toString());
}
if (state == inQuote || state == inDoubleQuote) {
throw new RuntimeException("unbalanced quotes in " + toProcess);
}
return result.toArray(new String[result.size()]);
}
Expanding on Andreas_D's answer, instead of copying, use CommandLineUtils.translateCommandline(String toProcess) from the excellent Plexus Common Utilities library.
I use the Java Getopt port to do it.

Categories

Resources