Wednesday, November 30, 2016

Error Handling Challenge

In this exercise, you will learn how to handle exceptions and how to validate inputs.

The base code is:
/**
 * Class MyCopy does just that, it copies a file into another.
 * @author Zoltan Szabo
 * @version 1.0.0
 */
public class MyCopy{
    /**
     * Entry point to application.
     * If output file exists or input file does not exists, it sets errorlevel.
     * @param args[0] source file name
     * @param args[1] destination file name
     */
    public static void main(String args[]){
            File inFile=new File(args[0]);  //source file name
            File outFile=new File(args[1]); //destination file name

            Scanner input = new Scanner(inFile);
            PrintWriter output = new PrintWriter(outFile);
            while(input.hasNext()){                    //read input file until it reaches the end of file
                    output.println(input.nextLine());
                }
            output.close();
            input.close();
    }
}

Now let's try to compile it with BlueJ ( any other IDE will do that does not give you too much help. Try to find the problems logically using the Java API )

1. We get an error message - "cannot find symbol - class File"  This suggest the missing class, so we should think about importing the class.
Solution:
Go to Java API and search for File class
Copy the path
Add the import java.io.File; to your code
2. We get an error message - "cannot find symbol - class Scanner"  This suggest the missing class, so we should think about importing the class.
Solution:
Go to Java API and search for Scanner class
Copy the path
Add the import java.util.Scanner; to your code
3. We get an error message - "cannot find symbol - class PrintWriter"  This suggest the missing class, so we should think about importing the class.
Solution:
Go to Java API and search for PrintWriter class
Copy the path
Add the import java.io.PrintWriter; to your code
4. At this point, we seem like have all the classes imported, but we get another type of error:
"unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown"
Let's look at the Scanner class constructor to see why we get this error message.
We see that
public Scanner(File source)
        throws FileNotFoundException
and FileNotFoundException is thrown - if source is not found

So, you can add public static void main(String args[])throws java.io.FileNotFoundException to your main method header or just public static void main(String args[])throws FileNotFoundException and then also import java.io.FileNotFoundException; to have the class available.
You should also add the docstring tag @throws since you need to explain why you are throwing the exception.

@throws java.io.FileNotFoundException if source is not found

5. Now, if we run the application without entering a filename argument, we'll get an error:
"java.lang.ArrayIndexOutOfBoundsException:0" This error was not handled yet, so we need to see how we can handle it.  This time, we'll actually will catch the exception and handle it locally instead of throwing it to the JVM to handle.
So, add the try block embracing all statements in the main method and the catch block to the code:

catch(ArrayIndexOutOfBoundsException e){
  System.out.println("You need to type the input and output files for this utility to work properly. \"MyCopy [[drive:\\]path]input.txt [[drive:\\]path]output.txt\"");
   System.exit(2017);
        }

ArrayIndexOutOfBoundsException class is in java.lang so you will not have to import it, but as a learning process, you should add the import anyway and you should also lookup the class in Java API documentation.

6. Now, you should also look at the other classes in your program to see if more exception might be thrown by any one of those classes.
public PrintWriter(File file)
            throws FileNotFoundException
You can see that PrintWriter class also throws an exception, so you can also handle that locally by surrounding the PrintWriter related statements in a try block and catching the exception.

 catch(FileNotFoundException e){
    System.out.println("The destination file " + outFile + " might not have the appropriate rights.");
    System.exit(2016);
    }

If you look further into the methods like nextLine method in the Scanner class also throws exceptions, but instead of handling every exception individually,

public String nextLine()
    NoSuchElementException - if no line was found
    IllegalStateException - if this scanner is closed


you can see in the Java API the hierarchy that it might make sense to throw the Exception object at a method level to handle all other than FileNotFoundException will be thrown and handled by the common class and due to polymorphism, the exception will be handled.

7. You can still have another exception thrown if you do not give the proper input arguments to the application at run time due to the args[0] and args[1] usage.  It can throw and ArrayIndexOutOfBoundsException and that exception should not let the program continue to run.  Thus, add another try/catch block to handle that case as well.

        catch(ArrayIndexOutOfBoundsException e){
            System.out.println("Type the input and output files. \"MyCopy [[drive:\\]path]input.txt [[drive:\\]path]output.txt\"");
            System.exit(2017);
        }

8. Now, you just have to add the input and output validation where we can terminate the application and return an exit code to the OS to show status of program exit.

So, the final program should look like this:

import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
//you don't really need it since it is in java.lang, but nice to have it to remind you 
import java.lang.ArrayIndexOutOfBoundsException;
/**
 * Class MyCopy does just that, it copies a file into another.
 * @author Zoltan Szabo
 * @version 1.0.0
 */
public class MyCopy
{
    /**
     * Entry point to application.
     * If output file exists or input file does not exists, it sets errorlevel.
     * @param args[0] source file name
     * @param args[1] destination file name

     * @throws Exception to handle all exceptions not specifically handled locally
     */
    public static void main(String args[])throws Exception {
        try{
            File inFile=new File(args[0]);  //source file name
            File outFile=new File(args[1]); //destination file name

            if (!inFile.exists()){           //Checks if the file name exists
                System.out.println("Source file " + inFile + " does not exists.");
                System.exit(2014);            // Exit the program.
            }

            Scanner input = new Scanner(inFile);

            if (outFile.exists()){           //Checks if the file name already exists
                System.out.println("The destination file " + outFile + " already exists.");
                System.exit(2015);            // Exit the program.
            }

            try{
                PrintWriter output = new PrintWriter(outFile);
                while(input.hasNext()){                    //read input file until it reaches the end of file
                    //System.out.println(input.nextLine());
                    output.println(input.nextLine());
                }
                output.close();
            }
            catch(FileNotFoundException e){
                System.out.println("The destination file " + outFile + " might not have the appropriate rights.");
                System.exit(2016);
            }

            input.close();
        }
        catch(ArrayIndexOutOfBoundsException e){
            System.out.println("Type the input and output files. \"MyCopy [[drive:\\]path]input.txt [[drive:\\]path]output.txt\"");
            System.exit(2017);
        }

    }
}

Exception handling simple example with custom exception

Simple example to practice throwing, catching, and creating custom exceptions.  Look at the API documentation for each class and familiarize yourself with the exceptions the class or method can throw in order to pan for exception handling.  In this example, look up FileReader(String ) constructor and take not of the exception and BufferedReader's readLine() method. 

In order to understand exception handling, you need to understand polymorphic object references. In this case, the relevant inheritance tree is as follows:
java.lang.Object

     java.lang.Throwable
         java.lang.Exception
              java.io.IOException
                   java.io.FileNotFoundException 

The program UML is as follows:

Source code that you should copy/paste and experiment with

import java.io.IOException; // For File class and FileNotFoundException
import java.io.File;
import java.util.Scanner; // For the Scanner class 

/**
 * This program demonstrates how a FileNotFoundException, IOException, and custom exception 
 * exception can be handled.
 */
public class OpenFile {
   public static void main(String[] args)   {
     FilePrinter my=new FilePrinter();
     try{
           my.displayFile("c:\\temp\\input.txt");
    }
    catch(IOException e){
            System.out.println("Got you - can't read anymore");   //change source file security rights to deny read.
           }
   }
}

import java.io.*;   
   
public class FilePrinter{   
     private FileReader reader;   
     private BufferedReader inputFile;   
     private String input;   
   
     public void displayFile(String name)throws IOException{   
       //  try{
                 callMe(name);   
       // }
      //  catch(FileNotFoundException e){
      //      System.out.println("File not found");   
      //  }
     }   
         /**
          * This is just a test
          * @param name as a string of the file name including path to the file if any
          * @throws IOException if file was not found
          * @throws FileNotFoundException if file was not able to open
          */

     public void callMe(String name)throws IOException,FileNotFoundException{   
         try{
          callMeAgain(name);   
        }
        catch(MyError e){
            System.out.println(e.toString());
            System.out.println(e.getMessage());
        }
         catch(FileNotFoundException e){
            System.out.println("File name does not exists.");
           // e.printStackTrace();
           }

         }   
          /**
          * This is just a test
          * @param name as a string of the file name including path to the file if any
          * @throws IOException if file was not found
          * @throws FileNotFoundException if file was not able to open
          * @throws MyError if a particular file name was attempted to open
          */

    public void callMeAgain(String name)throws IOException,FileNotFoundException,MyError{   
          if(name.equals("c:\\temp\\two.jpg"))
              throw new MyError();
          if(name.equals("c:\\temp\\two2.jpg"))
              throw new MyError("This is just a custom message!!!");
          try{
                reader = new FileReader(name);                //throws FileNotFoundException
                inputFile = new BufferedReader(reader);       

                input = inputFile.readLine();                    //throws IOException
                while (input != null) {   
                        System.out.println(input);   
                        input = inputFile.readLine();   
                       }   
                inputFile.close();   
               }
        catch(IOException e){
               System.out.println("read not allowed");   
               }
     }   
}   


public class MyError extends Exception
{
public MyError(){
    super("My error - zoltan");
}
public MyError(String msg){
    super(msg);
}
}

Tuesday, November 29, 2016

Java UTF-8

In order to understand UTF-8, you need to write not just English characters, but also characters that use the UNICODE characters like Chinese.

"UTF-8 is a character encoding capable of encoding all possible characters, or code points, defined by Unicode and originally designed by Ken Thompson and Rob Pike. The encoding is variable-length and uses 8-bit code units." ~ Ref: https://en.wikipedia.org/wiki/UTF-8

Use translate.google.com to generate simple strings in different languages to test.  
 
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
/**
 * This program opens a binary file and writes a series of strings
 * using UTF-8 encoding.
 */

public class WriteUTF
{
   public static void main(String[] args) throws IOException
   {
      String names[] = { "Warren", "Becky", "Holly", "Chloe","缅甸城","炫耀的生","你好"};
      FileOutputStream fstream = new FileOutputStream("c:\\temp\\UTFnames.dat");
      DataOutputStream outputFile = new DataOutputStream(fstream);
     
      System.out.println("Writing the names to the file...");
     
      for (int i = 0; i < names.length; i++)
         outputFile.writeUTF(names[i]);
     
      System.out.println("Done.");
      outputFile.close();    
   }
}


Due to the variable length storage of UTF-8, Java writes UTF-8 strings by recording the string length first following by the string characters.

  
Unicode encoded files written in notepad start with a Unicode signature and every character is stored as a 2 byte sequence of characters.
 
UTF-8 encoded files saved in notepad also stat with a signature, but the file structure is very different from the Java implementation of UTF-8 encoding.
 

Validate string with Regular Expression


Validating a string of characters is much easier with regular expressions than with a boolean expression where you would check if a character at a given position is within a range of legal characters.  You can us the Character class's isDigit, isLetter, isLetterOrDigit, or other methods in conjunction with the String charAt( ) method, but why would you do that when you have regular expression to match pattern much simpler. The Pattern class provides an easy to use way to match many complicated patterns of strings.

import java.util.regex.Pattern;
import java.util.regex.Matcher;

   /**
   Application to demonstrate of string validation based on regular expression
   @author Zoltan Szabo
   @version 1.0.0
   */
   public class MyClass{
   public static void main(String args[]){
  
    System.out.println(validate("234-L"));  //true
    System.out.println(validate("234-X"));  //false
    System.out.println(validate("234.L"));  //false
    System.out.println(validate("234-B"));  //true
    System.out.println(validate("234-b"));  //false
  
   }
   /**
   Validate string that is XXX-L format where X is a number 0-9 and L is a letter A-M and the length of the valid string is exactly 5 characters.
   @param s string to validate
   @return true or false based on the string validity
   */
   private static boolean validate(String s){
    boolean answer=true;
    if(s.length()!=5){
       answer=false;
    }
    else{
        Pattern p = Pattern.compile("[0-9]{3}-[A-M]");
        Matcher m = p.matcher(s);
        answer = m.matches();
    }
   return answer;
   }
  }

Saturday, November 19, 2016

Object Oriented Programming for Modularity - ROT-13

Many students starting out in Java try to solve a problem using a single class and thinking only about the application not its components and "building blocks".

In this example, writing an application to encrypt a string is simple to do in a single application, but the ROT-13 algorithm is not just useful in this application, but it should be used in many other applications as well. While the application interface and driving code are application specific, the ROT-13 algorithm is not and should be separated into a modular structure.




import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

/** This simple application will help you understand polymorphism
 * @version 1.0.0
 * @author Zoltan Szabo
 */
public class Rot13Demo{
      public static void main(String[] args) {
            try{
                  File inFile=new File("c:\\temp\\infile.txt");
                  File outFile=new File("c:\\temp\\outfile6.txt");
                  Scanner input=new Scanner(inFile);
                  PrintWriter output=new PrintWriter(outFile);
                  while(input.hasNext()){
                        String temp=input.nextLine();
                        for(int i=0;i<temp.length();i++){
                              char ch=temp.charAt(i);
                              if(Character.isLowerCase(ch)){
                                    if(ch<='m')
                                          output.print((char)(ch+13));
                                    else
                                          output.print((char)(ch-13));
                              }
                              else if(Character.isUpperCase(ch)){
                                    if(ch<='M')
                                          output.print((char)(ch+13));
                                    else
                                          output.print((char)(ch-13));
                              }
                              else
                                    output.print(ch);
                        }
                        output.println();
                  }
                  input.close();
                  output.close();
            }

            catch(IOException e){
                  System.out.println("Error: Check your input and output files and locations.");
            }
      }
}

If you are more adventurous, you can simplify the decision making and the "heart" of the algorithm with ternary operator, like this:


output.print((Character.isLowerCase(ch))?(ch<='m')?(char)(ch+13):(char)(ch-13):(Character.isUpperCase(ch))?(ch<='M')?(char)(ch+13):(char)(ch-13):ch);

Look at the simplicity of this driver class where the programmer can focus on the interface and how to handle the input and output files, while the algorithm can be used in any other applications.   


import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

/** This simple application will help you understand object oriented programming and an introduction to encryption
* @version 1.0.0
* @author Zoltan Szabo
*/
public class Rot13Demo{
   public static void main(String[] args)  throws IOException {
       File inFile=new File(args[0]);
       File outFile=new File(args[1]);
       Scanner input=new Scanner(inFile);
       PrintWriter output=new PrintWriter(outFile);
    while(input.hasNext()){
        String temp=input.nextLine();
        output.println(Rot13.encode(temp));
    }
    input.close();
    output.close();
   }
}

Since there are no attributes, the static method is a better choice for this method than a method belonging to an instantiated object.

/** This simple class helps you understand the static methods as a helper class for a collection of encryption algorithms.
* @version 1.0.0
* @author Zoltan Szabo
*/

public class Rot13{
/** This simple method will encode the temp string using ROT-13
* @param temp string to be encoded that can be a string encoded using ROT-13 to decode since ROT-13 is circular encryption algorithm
* @return The 13 character shifted string result
*/
   public static String encode(String temp) {
    StringBuilder encoded=new StringBuilder();
        for(int i=0;i<temp.length();i++){
            char ch=temp.charAt(i);
            if(Character.isLowerCase(ch)){
                if(ch<='m')
                    encoded.append((char)(ch+13));
                else
                    encoded.append((char)(ch-13));
            }
            else if(Character.isUpperCase(ch)){
                if(ch<='M')
                    encoded.append((char)(ch+13));
                else
                    encoded.append((char)(ch-13));
            }
            else
                  encoded.append(ch);
    }
    return encoded.toString();
   }
}

So, think about the generic and blocks in your code that should be independent from a specific application and design your code with objects in mind for mobility and modularity.