Java Pre assign args before passing from command line - java

I am developing a very simple Java application, through which to take files from a folder, obtain information from them and save them in the database.
The app is launched from the command line, and I need to pass the following parameters: file_path, db_name, db_user, db_host, db_user_psw.
When I run the check to see if all the parameters have been passed, in case a parameter is missing, I get an index out of bound exception, correctly according to java.
My need is to bypass this exception and display a string indicating an error message.
For example, if all parameters except db_user_psw are entered, instead of getting index of bound exception I would like the message "You must enter the password to access the db!".
My idea is to pre-assign the args to null, and once the script is run check if they are null or not.
Is it possible to do this in java? I accept any advice or suggestion
My code:
if(args[0] == null ){ System.out.println("Insert a valid Path!"); System.exit(0); }
if(args[1] == null ){ System.out.println("Insert the DB IP!"); System.exit(0);}
if(args[2] == null ){ System.out.println("Insert a DB name!"); System.exit(0);}
if(args[3] == null ){ System.out.println("Insert a DB Username!"); System.exit(0);}
if(args[4] == null ){ System.out.println("Insert User DB Password!"); System.exit(0);}

When I run the check to see if all the parameters have been passed, in case a parameter is missing, I get an index out of bound exception, correctly according to java. My need is to bypass this exception and display a string indicating an error message.
Check the length of args instead:
if(args.length == 0){ System.out.println("Insert a valid Path!"); System.exit(0); }
if(args.length == 1){ System.out.println("Insert the DB IP!"); System.exit(0);}
// ...
(You should exit with a non-zero code, in order to indicate an error)
I think you should really consider using named flags, so your command line isn't just a "meaningless" sequence of arguments that can easily be put in the wrong order. So rather than
java YourMainClass whatever blah etc
you provide something like:
java YourMainClass --file_path=whatever --db_name=blah etc
For your specific question of "Is it possible to do this in java?": You can, by copying the args array:
if (args.length < 5) args = Arrays.copyOf(args, 5);
// or
args = Arrays.copyOf(args, Math.max(5, args.length));
If args has fewer than 5 elements, this will create an array with 5 elements, padding the "missing" elements with null.
But this is an odd and unnecessary thing to do: checking the length is easier.

I am not entirely sure on this, since I am a beginner myself but did you consider to wrap it into a try - catch block?
try {
// Your logic to execute
}
catch(Exception e) {
System.out.println("Insert User DB Password! " + e);
// or something else
}```

Related

Exception handling not triggered/unexpected behaviour in program

I have a java program that takes command line arguments and then converts the decimal value to its hexadecimal counterpart. I am trying to make use of an exception handling code block (try/catch) which is not being triggered. The try/catch block is intended to be triggered when no command line arguments are passed to the program.
Have ran program through Jenkins/SonarQube to identify code smells and remedy issues. Have utilised process of trial and error, to experiment with different possibilities to see if I can resolve the design flaw.
https://pastebin.com/frBq46zs
//import java.util.Scanner;
public class Dec2Hex
{
public static int Arg1;
public static void main(String args[])
{
Scanner scan = new Scanner(System.in);
System.out.println("Enter any number: ");
//Arg1= scan.nextInt();
//scan.close();
if (args.length < 0)
{
try
{
Arg1 = Integer.parseInt(args[0]);
}
catch (NumberFormatException e)
{
System.err.println("Argument" + args[0] + " must be an integer.");
System.exit(1);
}
}
Utilising if (args.length > 0) with no command line value results in the exception not being triggered. I thought that this was to be expected, because the exception block would never be triggered because the conditional statement has not been satisfied.
However, the converse was not as expected. I thought that if (args.length==0) then this would mean "no arguments have been passed, attempt to parse the value entered, at the command line. If still despite that, no value can be parsed, THEN trigger the catch statement generating the error message and output it to the user."
Whenever I use args.length==0 or args.length<0 with no command line arguments submitted, all I get is a:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
Message which specifically refers to the following line of code:
Arg1 = Integer.parseInt(args[0]);
In your code Arg1 = Integer.parseInt(args[0]); before method call Integer.parseInt method arguments will be resolved. So it will try to get first element from argument list (as Java array is 0 based it will get first element with index 0).
As you are not passing any command line argument, code is breaking during argument resolution. Because the array length is 0, args[0] is giving ArrayIndexOutOfBoundsException. Which is an expected scenario. So you should case this exception as well.
try
{
Arg1 = Integer.parseInt(args[0]);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.err.println("No Argument Provided.");
System.exit(1);
}
catch (NumberFormatException e)
{
System.err.println("Argument" + args[0] + " must be an integer.");
System.exit(1);
}
And you don't need that if condition of checking for argument length, if you want to execute the exception code for 0 length. If you want to execute existing exception block pass argument that is not a number and remove the if condition.
In summary, code will reach to NumberFormatException block when you pass some argument and that is not a number. And that exception will be thrown by Integer.parseInt. And current exception is being thrown by args[0] because array length is 0 and you are trying to retrieve the first array element from empty array and it's throwing ArrayIndexOutOfBoundsException.
Although it's not desirable to reach to exception code, while you can handle that even before that.

java.lang.NumberFormatException: For input string: "" when using "2" or "5"

I read in a menu choice and typing in any number but 2 & 5 work.
String choice = promptUser(choicePrompt);
try {
outputInfo(String.format("choice=...%s...",choice));
int c = Integer.parseInt(choice);
/* process it */
}catch (NumberFormatException e) {
outputInfo(String.format("choice=%s",choice));
outputInfo(e.toString());
}
public static void outputInfo(String msg)
{
System.out.printf("\t%s\n",msg);
}
Good output:
Enter Option: 1
choice=...1...
Bad Output:
Enter Option: 2
choice=...2...
choice=2
java.lang.NumberFormatException: For input string: ""
Update:
I've hard-coded "2" and it still fails!:
String choice = promptUser(choicePrompt);
try {
choice="2";
outputInfo(String.format("choice=...%s...",choice));
int c = Integer.parseInt(choice);
/* process it */
}catch (NumberFormatException e) {
outputInfo(String.format("choice=%s",choice));
outputInfo(e.toString());
}
Hard-coding "5" also fails but "1" works!!!
Any ideas gratefully received.
Simon
If I assume your promptUser() method to be something like:
static String promptUser() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
return reader.readLine();
}
catch(Exception ex) {
return null;
}
}
(without the parameter) then the program behaves as expected - certainly there's nothing in that code that treats 2 or 5 differently. If you're getting an empty string then are you sure your prompt user method is working correctly?
Either way, the code you've posted here is essentially correct. I would imagine there's something else wrong in your more fully complete program that doesn't manifest itself when you've reduced it down here; perhaps you're running into a case where a local variable is hiding a field for example and you're not using the value you think you are (but at this point, I'm just guessing.)
updated
Seems the promptUser method is returning an empty String "". check if choice is empty before calling
ParseInt method
Also you can add trim() to eliminate spaces before and after the input
if(choice!=null && !"".equals(choice))
int c = Integer.parseInt(choice.trim());
printStackTrace() is your friend.
Turns out the number format exception was further down (in the 'process it' code) and was not being caught down there.
It was data driven so didn't happen on other machines.
Thanks to every one for your support.
Simon

Reading and comparing strings in a text file, variables not initialized

I'm getting the error
the local variables name and password may not have been initialized,
for the if-statement. These errors go away if I change the second string in parentheses to something in quotes, or if I set the variables to 0, but then I would also need to change them to int and I need them to be String.
I'm trying to compare the username and password from a text file to a newly input username and password. The program should also quit after 3 bad attempts so I probably put the System.out.println("Goodbye!"); in the wrong place too.
public static void main(String[] args) {
int numberOfAttempts = 1;
String fileName = "logins.txt";
Scanner inputStream = null;
String name, password, line, secondname;
String secondpassword;
do
{
System.out.println("Please enter your username: ");
Scanner keyboard = new Scanner(System.in);
secondname = keyboard.nextLine();
System.out.println("Please enter your password: ");
secondpassword = keyboard.nextLine();
try
{
inputStream = new Scanner(new File(fileName));
}
catch(FileNotFoundException e)
{
System.out.println("Error opening the file " +
fileName);
System.exit(0);
}
while (inputStream.hasNextLine())
{
line = inputStream.nextLine();
}
if ((name.equalsIgnoreCase(secondname))&&
(password.equalsIgnoreCase(secondpassword)))
{System.out.println("Welcome!");
numberOfAttempts = 4;
}
else
System.out.println("Invalid. Please try again.");
numberOfAttempts++;
}
while ( numberOfAttempts <4);
System.out.println("Goodbye!");
inputStream.close();
}
}
You never initialize name and password, so of course you'll get this error.
You initialize secondname and secondpassword, but your condition checks name and password which are not initialized.
In JAVA methods, any local variable must be initialized first it can be used. In your case you are trying to compare the name & password in your code are never initialized or assigned a value.. It will be a good idea to initialize your strings either as NULL or empty string such as "" or any desired value.
You have a bunch of problems.
The errors are caused by the fact that you never assign any values to the variables "name" and "password", but you then check to see if those variables match the secondname and secondpassword variables you do read. Because name and password never get any values at all, the comparison can't possibly be what you intend, so the compiler flags it as an error.
You can make the error go away by assigning name and password to some values when you declare them, but your program still isn't going to work correctly, because no matter what value you assign, it probably won't be the thing that the user of your program would want to be comparing against.
Presumably your intent is to read the value of name and password from the input file you've opened and read in, but in fact you aren't doing anything with the values in that file except immediately throwing them away. Look at the loop
while(inputStream.hasNextLine()) {
line = inputStream.nextLine();
}
This loop will read in every line from the file, but as soon as you read one line, you throw away whatever you read into the line variable because you have to reuse that variable to read the next line, which you'll also throw away immediately. At the end of the loop, you'll have saved the last line from the file into line, but the rest of the program doesn't use the line variable either.
You need to put some logic inside that loop to read whatever you wanted to read from the file, store it in the name and password variables, and then you'll have some hope that when you do the equalsIgnoreCase stuff that you'll actually be comparing variables that have some meaning to your program.

why testing args.length?

I'm a Java beginner and I'm confused about testing args.length at the begining of many codes, and why it's never gets higher than 0 in any of my codes?
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.IOException;
public class LowPortScanner {
public static void main(String[] args) {
String host = "localhost";
if (args.length > 0) {
host = args[0];
}
for (int i = 1; i < 1024; i++) {
try {
Socket s = new Socket(host, i);
System.out.println("There is a server on port " + i + " of "
+ host);
}
catch (UnknownHostException ex) {
System.err.println(ex);
break;
}
catch (IOException ex) {}
} // end for
} // end main
} // end PortScanner
You have to inputs to main mathod from Command prompt.
like below
java LowPortScanner TEST1 TEST2
Because if it is not tested then an exception would be thrown because host = args[0]; would illegal.
However, this doesn't look like it's going to help much, an empty or null host looks like it would cause further problems.
If the length of args is always 0, then be sure you're actually passing in parameter arguments.
If there are no command arguments the args[0] will fail. This is why it must be protected.
It depends on how you invoke the Java class file. In command prompt or bash shell:
java LowPortScanner Argument1
typing the above line in the command prompt/bash will cause the argument count to increase to 1. (because Argument1 is one argument, after the class file LowPortScanner)
java LowPortScanner Argument1 Argument2
the above line will make argument count to increase to 2.
hence args.length will be 2 in the second case and 1 in the first case.
If you are calling your program from CMD or bash you can asign ARGuments it like
java LowPortScanner google.com
Then "google.com" is your args[0]. When your program supports commandline attributes it is recommended to test if the given arguments are corret.
The variable String[] args hold all the parameter pass to the program thorough command line if you are not passing any argument then the length of args become 0. Now it's better to check it's length before accessing it other wise there is chance to get ArrayIndexOutOfBoundsException if it's size is 0
args in public static void main(String[] args is the String array of arguments passed from command line.
java LowPortScanner argument1 argument2
if you try the above command args.length will return 2.
As far as question of checking the length it is done for java programs which can take command line arguments and if arguments are not passed then they prompt for input.
if(args.length >0 ){
//proceed using passed arguments
}else{
//proceed with some default value
}
You are running your program using java LowPortScanner hence no arguments are passed and args.length is always zero.
Moreover if you don't pass any argument and use host=args[0] you will get ArrayIndexOutOfBoundsException.

How to check for an integer or a string and if not ask again [Java]

There are a bunch of threads throughout the internet on this but I can't make heads or tails of any of them.
As an assignment for an intro to Java course we have been tasked with making a handful of different programs, we were then given them back and told to make them idiot proof.
So for example, we have to use a program to determine what day of the week a random day of any random year will be, (i.e Jan 1 2013 being a Tuesday)
I prompt for three things, Day, Year and Month, I want to make it so that if Day is contains a letter it sends back Invalid and prompts again.
Right now I have it set so that if day is an integer less than one or greater than 31 it asks again, so I don't have a problem with the range, just the NFE.
I have heard that I should use a
Try
{
//...
}
catch{NumberFormatExcept nFE}
but I have no idea how to use that to re-prompt for what I an looking for
Here is a snippet of my code so far
System.out.print("Enter the day of the month (1-31): ");
int d = UserInput.nextInt();
do
{
if(d < 1 || d > 31)
{
System.out.print("That day is invalid, please enter a day between 1 and 31");
d = UserInput.nextInt();
}
}while(d < 1 || d > 31);
I tried making d a string and using Integer.parseInt(); but that would just parse a into 1, I want to so something like if d.hasNextInt(); continue, but if it hasNextString() reprompt.
AKA
String d;
d = UserInput.nextLine();
int dVar = Integer.parseInt(d);
I can't just throw an exception because the objective is to not crash but just prompt again.
Consider creating a method for reading in a valid integer. Pass this method the valid integer range. The method would attempt to read the value once and validate. If the method fails, return null, if it passes return the Integer. Call this method in a do-while loop until you get a non-null Integer.
First off, you really shouldn't use exceptions for input validations. Exceptions are for exceptional conditions; things you don't expect to happen. Josh Bloch outlines this specifically in his excellent book Effective Java
As for your code, I would suggest using the hasNextInt() method combined with getting the input as an int and checking for the range you require as you've actually stated in your question.
int d = 0;
while (d < 1 || d > 31)
{
System.out.print("Enter the day of the month (1-31): ");
if (userInput.hasNextInt())
{
int d = userInput.nextInt();
}
else
{
String s = userInput.next();
}
if(d < 1 || d > 31)
{
System.out.print("That day is invalid - ");
}
}
It looks like you are using Scanner to get input. (By the way, in Java, it is conventional for variables to start with lower-case letters).
If that's the case, if you attempt to scan an int when there isn't one in the input, an InputMismatchException will be thrown. You avoid this by testing whether this will happen before you try to read the int.
So, think about a loop structure like this:
int d = 0;
while (true) {
if (/* The input isn't an integer */) {
/* Tell the user. */
continue;
}
d = input.nextInt();
if (/* The input is out of range */) {
/* Tell the user. */
continue;
}
...
/* When you've completed all of your tests and everything is okay, break. */
break;
}
By the way, many months don't have 31 days.
Are you familiar with the behavior of a try-catch statement?
try
{
//do something that may throw an exception you can handle
}
catch(Exception ex)
{
//If we enter this block, an exception was thrown from the try block's code
//If you cannot fully handle the exception, you can rethrow it
throw ex;
}
finally
{
//This code ALWAYS executes, unless the program is aborted from outside its scope
}
You can use this inside some other loop, allowing you to define behavior based on whether an exception was thrown. This code is in C#; it is syntactically very close to Java but I'm a little light on Java's libraries so substitute proper class names/method calls as necessary:
int day = 0;
while(true) //we will manually break out of the loop once the user enters a valid value
{
try
{
//Ask user for input
string input = Console.ReadLine();
day = Int32.Parse(input); //this will throw an exception if input is not numeric
//You can throw your own exception within a try block too
if (day < 1 || day > 31) throw new Exception("Date not within proper bounds");
break; //if the parse worked and the value passed the validation, end the loop.
}
catch(Exception ex) //You can catch something more specific
{
//The parse failed; tell the user that they screwed up, and how
Console.WriteLine("Invalid entry: " + ex.Message);
//skip the rest of the loop's code and start a new iteration of the loop
continue;
}
}
The behavior of this construct is that while the user keeps entering values that cannot be turned into a number between 1 and 31, exceptions will be thrown, caught, and used to perpetuate the loop. As soon as the user enters something you can work with, execution flow will move past this loop to whatever is next.

Categories