Session 4 Command-Line Arguments, Strings, and Files Options for User Input • Options for getting information from the user – Write event-driven code • Con: requires a significant amount of new code to set-up • Pro: the most versatile. – Use System.in • Con: less versatile then event-driven • Pro: requires less new code – Use the command line (String[ ] args) • Con: very limited in its use • Pro: the simplest to set up Using the command line • Remember what causes the “big bang” in our programs? public static void main (String [] args) { • main expects an array of strings as a parameter. • The fact of the matter is that this array has been a null array in each of our programs so far. Using the command line • However, we can give this array values by providing command line arguments when we start a program running. $ java MyProgram String1 String2 String3 args[0] args[1] args[2] Fixing this problem public class MyEcho2 { public static void main( String[] args ) { if (args.length == 2) { System.out.println("args[0] is ” + args[0]); System.out.println("args[1] is " + args[1]); } else { System.out.println( "Usage: java MyEcho2 " + "string1 string2"); } // end if } // end main } // end MyEcho2 $ java MyEcho2 Mark Usage: java MyEcho2 string1 string2 $ java MyEcho2 Mark Alan Fienup Usage: java MyEcho2 string1 string2 Your turn to write a simple program using the command line • Write a program to echo all command-line arguments to System.out $ java EchoAll This is a long line args[0] is This args[1] is is args[2] is a args[3] is long args[4] is line Simple Calculations at the Command Line $ java Calculate 6 + 4 10 $ java Calculate 8 - 5 3 First Attempt - What’s wrong? public class Calculate { public static void main( String[] args ) { int operand1 = args[0]; String operator = args[1]; int operand2 = args[2]; if ( operator.equals("+") ) { System.out.println( operand1 + operand2 ); } else if ( operator.equals("-") ) { System.out.println( operand1 - operand2 ); } else { System.out.println("Invalid operator: " + operator); } // end if } // end main } // end Calculate $ javac Calculate.java Calculate.java:3: incompatible types found : java.lang.String required: int int operand1 = args[0]; ^ Correct Calculate public class Calculate { public static void main( String[] args ) { int operand1 = Integer.parseInt( args[0] ); String operator = args[1]; int operand2 = Integer.parseInt( args[2] ); if ( operator.equals("+") ) { System.out.println( operand1 } else if ( operator.equals("-") System.out.println( operand1 } else { System.out.println( "Invalid } // end if } // end main } // end Calculate + operand2 ); ) { - operand2 ); operator: " + operator ); The wrapper classes • Primitive data types (int, double, boolean, etc.) are not actually objects. Because of this, you can’t use them easily in certain OO situations • Therefore, Java has “wrapper classes” such as Integer, Double, and Boolean. • These are true classes in the OO sense of the word since they contain data which store information (often the value in it’s corresponding primitive data type) and methods that can act on this data. But wait a minute! • How is it that we can use the parseInt() method from the Integer class without actually creating an instance of Integer class. Lifetime Modifiers What does static mean? Lifetime Modifiers What does static mean? • The item being declared is a feature of the class – what we usually call “class methods” or “class variables.” • The item being declared exists at load time, before any instance is created. Lifetime Modifiers • A “class method” is one that can be invoked without sending a message to an instance of the class. the main method of MemoPadApp int operand1 = Integer.parseInt(args[0]); double myRandom = Math.random(); Lifetime Modifiers • A “class variable” is one that every instance has access to and shares. In chapter 5, Budd creates windows in which bouncing balls live. Every instance of his BallWorld class shares the same height and width dimensions, implemented as static class variables: public static int frameWidth=200; public static int frameHeight=250; Lifetime Modifiers • We will use these rarely in the code we write. – The more you use static stuff, the less flexible and modifiable your code tends to be. • The Java class library uses these more frequently. Budd will use them occasionally. – Thus, you will still get to see plenty of examples before we are done! Homework #2 – Constructors and Command-line Arguments • Goals for this assignment: practice implementing constructors practice factoring common behavior into helper methods experience working with command-line arguments • You will continue to work with the MemoPad program for this assignment, including the database class that you implemented for Homework 1 Homework #2 • For this homework, you will modify the MemoPadApp class to accept some optional command-line arguments. java MemoPadApp Use the original DefaultMemoDatabase java MemoPadApp –d Use the original DefaultMemoDatabase java MemoPadApp -s Use your original student version of MyMemoDatabase from homework 1 java MemoPadApp -s 100 Use your MyMemoDatabase that is created by a new constructor that limits the database to the specified maximum size (in this example Homework #2 - Tasks 1. Add a new constructor to your MyMemoDatabase class that takes one argument: the maximum number of memos that can be stored. 2. Eliminate any code duplication in your MyMemoDatabase class's constructors. 3. Add a new constructor to the MemoPad class that takes one argument: the MemoDatabase that it uses to store the memos. 4. Change the original "default" constructor back to its original form, from before Homework 1: initialize the database variable to be a DefaultMemoDatabase. 5. Eliminate any code duplication in the MemoPad constructors. 6. Modify the main() method in the MemoPadApp driver to accept up to two optional arguments that control the kind of MemoDatabase to be used. Homework #2 - Sample Executions java MemoPadApp MemoPadApp uses the default constructor of MemoPad java MemoPadApp -d MemoPadApp creates a DefaultMemoDatabase and passes it to the new MemoPad constructor that takes a MemoDatabase parameter java MemoPadApp -s MemoPadApp creates an instance of your MyMemoDatabase (use default constructor) and passes it to the new MemoPad constructor Homework #2 - Sample Executions – java MemoPadApp -s 100 MemoPadApp creates an instance of your MyMemoDatabase using the new constructor that takes an int parameter, and then passes it to the new MemoPad constructor Homework #2 - Sample Executions • If the user gives any other command-line argument, print an error message and return without creating any objects. For example: $ java MemoPadApp -oops Usage: java MemoPadApp java MemoPadApp -d java MemoPadApp -s [size] Java Strings and Files Exercise Complete the “quick-and-dirty” class CharacterCounter containing only a main() method that displays the number of non-space characters on the command line after the command. For example: $ java CharacterCounter 0 $ java CharacterCounter a 1 $ java CharacterCounter a bc def ghij 10 CharacterCount template public class CharacterCounter { public static void main( String[] args ) { int characterCount = 0 ; } // end main } // end class CharacterCounter StringTokenizer • Useful tool for processing a String object • Allows you to sequentially walk down a String and extract “words”/tokens that are delimited by specified characters • What delimiter normally aids us in parsing a long string into words? StringTokenizer General usage of a StringTokenizer: – create one using a constructor that takes a string argument to process – send one of two messages: hasMoreTokens() and nextToken – use a stereotypical loop to process a sequence of strings A default StringTokenizer uses spaces as delimiters. StringTokenizer Example import java.util.StringTokenizer; public class EchoWordsInArgumentV1 { public static void main( String[] args ) { StringTokenizer words = new StringTokenizer(args[0]); while( words.hasMoreElements() ) { String word = words.nextToken(); System.out.println( word ); } // end while } // end main } // end class EchoWordsInArgumentV1 StringTokenizer Example $ java EchoWordsInArgumentV1 "StringTokenizer, please process me." StringTokenizer, please process me. • Notice the quotes (“”) in the command line so the whole string is read as args[0]. • The comma (“,”) and period (“.”)are part of the words and not delimiters by default. StringTokenizer Example 2 • Fortunately, we can construct a StringTokenizer that uses specified characters for delimiters. • The designer of the StringTokenizer was planning ahead for future usage!!! $ java EchoWordsInArgumentV2 "StringTokenizer, please process me." StringTokenizer please process me StringTokenizer Example 2 import java.util.StringTokenizer; public class EchoWordsInArgumentV2 { public static void main( String[] args ) { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r"; StringTokenizer words = new StringTokenizer( args[0], delimiters ); while( words.hasMoreElements() ) { String word = words.nextToken(); System.out.println( word ); } // end while } // end main } // end class EchoWordsInArgumentV2 Split – alternative to StringTokenizer public String[] split(String regex) Splits this string around matches of the given regular expression. This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array. The string "boo:and:foo", for example, yields the following results with these expressions: Regex Result : { "boo", "and", "foo" } o { "b", "", ":and:f" } Parameters: regex - the delimiting regular expression Returns: the array of strings computed by splitting this string around matches of the given regular expression Throws: PatternSyntaxException - if the regular expression's syntax is invalid Since: 1.4 UNIX/Linux pipe • “|” character on the command line • Allows the output of one program to be sent as input to another program, like the UNIX “sort” utility. $ java EchoWordsInArgumentV2 "StringTokenizer, please process me.” | sort StringTokenizer me please process • Is this sorted? How can we fix this? StringTokenizer Example 3 import java.util.StringTokenizer; public class EchoWordsInArgumentV3 { public static void main( String[] args ) { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r"; StringTokenizer words = new StringTokenizer( args[0], delimiters ); while( words.hasMoreElements() ) { String word = words.nextToken(); word = word.toLowerCase(); System.out.println( word ); } // end while } // end main } // end class EchoWordsInArgumentV3 StringTokenizer Example 3 $ java EchoWordsInArgumentV3 "StringTokenizer, please process me." | sort me please process stringtokenizer Java File I/O • Allows us to write and read “permanent” information to and from disk • How would file I/O help improve the capabilities of the MemoPadApp? Java File I/O Example: Echo.java • echoes all the words in one file to an output file, one per line. $ java Echo hamlet.txt hamlet.out $ less hamlet.out 1604 the tragedy of hamlet prince of denmark by william shakespeare ... Study Echo.java’s File I/O • have constructors that allow convenient and flexible processing • send input message: readLine() • send output messages: print() and println() • use a stereotypical loop to process a file of lines • use of the stereotypical StringTokenizer loop as inner loop import java.io.*; import java.util.StringTokenizer; public class Echo { public static void main( String[] args ) throws IOException { String delimiters = " .?!()[]{}|?/&\\,;:-\'\"\t\n\r"; BufferedReader inputFile = new BufferedReader(new FileReader(args[0]) ); PrintWriter outputFile = new PrintWriter( new FileWriter( args[1] ) ); String buffer = null; while( true ) { buffer = inputFile.readLine(); if ( buffer == null ) break; buffer = buffer.toLowerCase(); StringTokenizer tokens = new StringTokenizer( buffer, delimiters ); while( tokens.hasMoreElements() ) { String word = tokens.nextToken(); outputFile.println( word ); } // end while } // end while(true)... } // end main } // end class Echo