4. Files and Streams

 

 

Introduction

 

Now that we have laid the groundwork for developing servlets, let’s get back to the basics. This chapter carries on from where we left off in the first two chapters. It details a few more features of the Java Programming language.

 

Let’s understand the first program in this chapter, where we have two simple classes.

zzz.java

import java.applet.*;

public class zzz extends Applet {

public void init()

{

xxx a,b;

a =  new xxx();

System.out.println(a.i);

b =  new xxx();

System.out.println(b.i);

}

}

class xxx {

public int i = 6;

xxx()

{

i++;

System.out.println(“In Const xxx “ + i);

}

}

C:\javaprg>appletviewer a.html

 

In Const xxx 7

7

In Const xxx 7

7

 

You can have as many classes as you like in a file, but only one of them can be declared public. You will get an error if you make more than one class public. Add public to the xxx class as well and it will display an error as shown below.

 

C:\javaprg>javac zzz.java

 

zzz.java:14: Public class xxx must be defined in a file called “xxx.java”.

public class xxx

             ^

1 error

 

In this program, class zzz is declared as public but class xxx is not. a and b are two objects that look like xxx. Let us remind you that here you do not call the constructor; it is called by new at the time the object is created. The next line is, a=new xxx(). In the constructor, i, which has the value 6, will now become 7. The next line, System.out.println prints the value of i as 7. Hence you see the output as

In Const xxx 7

 

C:\javaprg>appletviewer a.html

 

In Const xxx 7

7

In Const xxx 7

7

 

 

 

The statement b=new xxx() creates one more variable named i. This is because new creates the variables again. a.i and b.i will both have the same value. A point to be noted here is that the functions don’t get created again. Functions can be shared but not variables.

 

The next example includes the word static which precedes the variable i.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

public void init()

{

xxx a,b;

a =  new xxx();

System.out.println(a.i);

b =  new xxx();

System.out.println(b.i);

}

}

class xxx

{

public static int i = 6;

xxx()

{

i++;

System.out.println(“In Const xxx “ + i);

}

}

 

C:\javaprg>appletviewer a.html

 

In Const xxx 7

7

In Const xxx 8

8

 

 

When you say static and run the program, you will notice that a.i displays 7 and b.i displays 8. This means that i in xxx gets created only once. In the previous example, where the word ‘static’ was not included, if you had created 100 instances of xxx there would have been 100 i’s. Remember, the code is not replicated each time you say new. It is only the variables that get recreated.

 

Functions are stored in one area of memory and variables in another. Each time you say new, it checks to see if the function exists in memory. If it exists, then the function isn’t added. In other words, functions are loaded into memory only once, but the variables within the class are created afresh each time.

 

An object is an instance of a class and when a class is instantiated, the variables are created afresh. i as a variable is now related to the object and not to the class. Whereas static variables have nothing to do with the object, they go with the class. You don’t have to say new to access the static variable. This is shown in the next program.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a;

public void init()

{

System.out.println(a.i);

}

}

class xxx

{

public static int i = 9;

}

 

C:\javaprg>appletviewer a.html

 

9

In this program, ‘a’ looks like xxx. We have not used new anywhere. We have a static variable i in the class xxx. System.out.println with a.i will print 9 on the screen. Here, if we make ‘a’ local, the compiler will return with an error saying that it has not been initialized.

 

public void init()

{

xxx a;

System.out.println(a.i);

}

 

The compiler error will be:

 

C:\javaprg>javac zzz.java

 

zzz.java:9: Variable a may not have been initialized.

System.out.println(a.i);

                   ^

1 error

 

‘a’ was made global so it does not have to be initialized. a.i displays 9, which means that there is one and only one i. We repeat, static variables can be accessed without creating the object.

 

Here’s another example to prove the same point

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a,b;

public void init()

{

System.out.println(a.i);

b.i = 20;

System.out.println(a.i);

}

}

class xxx

{

public static int i = 9;

}

 

C:\javaprg>appletviewer a.html

 

9

20

 

At first a.i will print 9. Then b.i is initialized to 20. b.i and a.i are the same because i is a static variable and is shared. So when you say a.i again, the value of i is 20. As you can see, you don’t have to create an object to use static variables.

 

The next program introduces the concept of a static function that returns void.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a;

public void init()

{

a.abc();

}

}

class xxx

{

public static void abc()

{

System.out.println(“hi”);

}

}

 

Here a.abc calls the function abc in the class xxx. Once the function is called  ‘hi’ is printed on the screen.

c:\javaprg>appletviewer a.html

 

hi

 

The need for static functions will be discussed a little later in this chapter.

 

In the following program, the static variable ‘i’ is declared to be private.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a,b;

public void init()

{

System.out.println(a.i);

b.i = 20;

System.out.println(a.i);

}

}

class xxx

{

private static int i=10;

}

 

C:\javaprg>javac zzz.java

zzz.java:7: Variable i in class xxx not accessible from class zzz.

System.out.println(a.i);

                    ^

zzz.java:8: Variable i in class xxx not accessible from class zzz.

b.i = 20;

 ^

zzz.java:9: Variable i in class xxx not accessible from class zzz.

System.out.println(a.i);

                    ^

3 errors

The default is private, which means that only the class members can access the variable. “Outsiders are not allowed!” i.e. anyone outside the class is not allowed to access it. Try to trespass and you will definitely see the watchdog, the error.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

xxx a;

public void init()

{

a=new xxx();

}

}

class xxx

{

private static int i=10;

xxx()

{

i++;

System.out.println(“In Const “+i);

}

}

 

C:\javaprg>appletviewer a.html

 

In Const 11

 

Here xxx increments the value of i by saying i++ and display its value. Only the constructors and functions in xxx have access to i. The variables ‘a’ and ‘b’, though created in zzz and in the very same file, are not allowed to access i.

 

zzz.java

import java.applet.*;

public class zzz extends Applet

{

}

class xxx

{

public void abc()

{

}

}

class yyy extends xxx

{

public void abc()

{

}

}

 

In the above program, apart from zzz there are two more classes, xxx and yyy. Class xxx has a function called abc. Class yyy extends xxx and also has a function named abc. This will not result in any compilation errors.

 

The next program introduces a small change. Here the word ‘final’ precedes void abc().

zzz.java

import java.applet.*;

public class zzz extends Applet

{

}

class xxx

{

public final void abc()

{

}

}

class yyy extends xxx

{

public void abc()

{

}

}

C:\javaprg>javac zzz.java

 

zzz.java:13: The method void abc() declared in class yyy cannot override the final method of the same signature declared in class xxx.  Final methods cannot be overridden.

public void abc()

            ^

1 error

 

Final methods cannot be changed or overrriden. Since abc has been made final, the class yyy cannot have another function abc. The abc in xxx is final, thus you can’t change it.

 

It is not without purpose that such a concept has been introduced in Java. Let’s understand the rationale behind it.

 

Let us assume that you have your own class with a final function. Others will derive from it, but if they want to override the same function, they will not be allowed to do so. They will get the error shown above. Without the use of final there is no guarantee that the function will not be overridden. Thus to prevent the overriding of a function, it must be made final.

 

Now, in xxx, we are creating a function named abc.

zzz.java

import java.applet.*;

public class zzz extends Applet

{

}

class xxx

{

public  void abc() throws IOException

{

}

}

 

 

 

C:\javaprg>javac zzz.java

 

zzz.java:7: Class IOException not found in throws.

public  void abc() throws IOException

                          ^

1 error

 

The function abc throws an exception, or to be more specific, it throws IOException. The full name is java.io.IOException, hence we need to import java.io.*

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (Exception e){System.out.println(e.getMessage());}

}

}

class xxx

{

public  void abc() throws IOException

{

throw new IOException(“hi”);

}

}

 

C:\javaprg>appletviewer a.html

 

hi

 

A function takes parameters and along with it, it can also throw exceptions. This tells us more about the function.

 

This program has x that looks like xxx and is created on the same line by saying new xxx(). This does not give us any problems at all. The next line has x.abc(), where we call this function. abc returns a void and throws an IOException. Within the curly braces, the command ‘throw’ is used to actually throw the exception. Here, it throws the predefined exception, which is IOException. Before the exception is thrown, it must be created. It is created with the help of ‘new’. We are calling the constructor, which takes one parameter, in this class. A couple of lines later we will show you how to create your own exceptions.

 

Every exception thrown must be caught, so catch catches Exception, which is the base class for all exceptions. System.out.println prints the return value of e.getMessage. e looks like Exception and the getMessage function in e displays “hi”. “hi” is displayed because this is what was given in the constructor. You can have as many catches as you want for the different exceptions you want to catch.

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (IOException e){System.out.println(“In IOException “+e.getMessage());}

catch (Exception e){System.out.println(“In Exception “ + e.getMessage());}

 

finally

{

System.out.println(“All over”);

}

}

}

class xxx

{

public  void abc() throws IOException

{

throw new IOException(“hi”);

}

}

 

C:\javaprg>appletviewer a.html

 

In IOException hi

All over

 

Here’s one more example where we catch IOException and then Exception e. Since abc throws an IOException, the IOException will be called and not the second one. Once the first catch is executed, the execution of the other catches stops.

 

Reversing the catch order will generate an error.

 

C:\javaprg>javac zzz.java

 

zzz.java:13: catch not reached.

catch (IOException e){System.out.println(“In IOException “+e.getMessage());}

^

1 error

 

In the try and catch, we have introduced a new word ‘finally’. The code in the curly braces, which has been given after the word ‘finally’ is called when everything is over. Hence you see ‘All over’. ‘finally’ gets called irrespective of the throws. To check this, comment out the throw and you will still see ‘All over’.

 

‘finally’ is used to execute code at the end of ‘try’ and ‘catch’ pair. It can be used to close a file that was opened in the program. The file will be closed irrespective of whether the exception takes place or not.

 

Ready for something interesting? We are now going to show you how to create your own exception.

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (Exception e){System.out.println(e.getMessage());}

}

}

class xxx

{

public  void abc() throws ppp

{

throw new ppp(“hi”);

}

}

class ppp extends Exception

{

ppp(String p)

{

System.out.println(“In const “ + p);

}

}

C:\javaprg>appletviewer a.html

 

In const hi

null

 

Here we are calling our exception ppp which extends Exception, the base class of all exceptions. Then we create a constructor, which accepts one parameter ‘p’. This value is displayed using System.out.println. There you go! Exception created.

 

When we say x.abc, at first abc in xxx gets called and it immediately throws an exception. This will call the constructor in ppp. The p in the constructor has the value ‘hi’, hence we see ‘In const hi’. But e.getMessage does not return any value, so we see null. Since we do not have the getMessage function, the one in Exception is called and it returns a null.

 

In our next program, we have added the getMessage function in ppp and the statement returned is “Sonal”.

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (Exception e){System.out.println(e.getMessage());}

}

}

class xxx

{

public  void abc() throws ppp

{

throw new ppp(“hi”);

}

}

class ppp extends Exception

{

ppp(String p)

{

System.out.println(“In const “ + p);

}

public String getMessage()

{

return “Sonal”;

}

}

 

C:\javaprg>appletviewer a.html

 

In const hi

Sonal

 

To print the value returned by e.getMessage, our getMessage will be called and thus you see ‘Sonal’.

 

This is not the correct way to go about doing things, so we now set it in the right way.

 

When we create an object, our constructor is given ‘hi’ as a parameter. This constructor should call the original constructor and give it the same string. Then, the getMessage function in our code should receive the value returned by the original function, which will be the value to be returned back.

 

The next program implements these two things.

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (Exception e){System.out.println(e.getMessage());}

}

}

class xxx

{

public void abc() throws ppp

{

throw new ppp(“hi”);

}

}

class ppp extends Exception

{

ppp(String p)

{

super(p);

System.out.println(“In const “ + p);

}

public String getMessage()

{

String s;

s = super.getMessage();

return s;

}

}

 

C:\javaprg>appletviewer a.html

 

In const hi

hi

 

In ppp, we have super(p) which must be written on the very first line. It is used to call code in the original. By original we mean the class that we have derived from. In our case, the constructor in Exception will be called with one parameter p. This constructor stores the string. In getMessage, we again have super.getMessage. super.getMessage will call getMessage from the base class, which is Exception. The getMessage returns a string, which is stored in the variable s and then we simply return s. Now the program will work in the required manner.

 

Our next example is slightly larger.

 

zzz.java

import java.applet.*;

import java.io.*;

public class zzz extends Applet

{

public void init()

{

try

{

xxx x = new xxx();

x.abc();

}

catch (Exception e){System.out.println(e.getMessage());}

finally

{

System.out.println(“All over”);

}

}

}

class xxx

{

public  void abc() throws ppp

{

throw new ppp(“hi”);

}

}

class ppp extends Error

{

ppp(String p)

{

super(p);

System.out.println(“In const “ + p);

}

public String getMessage()

{

String s;

s = super.getMessage();

System.out.println(“In getmessage “+s );

return s;

}

}

 

C:\javaprg>appletviewer a.html

 

In const hi

All over

In getmessage hi

In getmessage hi

In getmessage hi

ppp: hi

        at xxx.abc(zzz.java:23)

        at zzz.init(zzz.java:10)

        at sun.applet.AppletPanel.run(AppletPanel.java:333)

        at java.lang.Thread.run(Thread.java:479)

 

Class zzz has a variable x as an object that looks like xxx. The statement, x.abc, calls the function abc which throws an exception called ppp. The constructor gets called, hence ‘In const hi’ is displayed. This is the first line of output. Then ‘finally’ gets called because of which ‘All over’ is displayed. The catch code will be the next to be called and because we have System.out.println, it will constantly print e.getMessage, which contains ‘hi’. Once all this is over, it will tell you that there was an error int xxx.abc at zzz.init.

The reason why all this happens is that we are not deriving ppp from Exception but instead we are deriving from Error. The error messages are to be read in the reverse order: The error is in xxx.abc, which has been called from zzz.init and AppletPanel.run calls init and so on.

 

Building Applications

 

So far you have been building Applets, now let’s build Applications.

 

Applets and applications are very similar in appearance, with one key difference: A Java application is an independent piece of software; an applet is not. The applet is loaded and run by a browser or viewer. In fact, the HotJava browser is just a Java application.

 

qqq.java

public class qqq

{

}

 

Start by saying public class qqq { }. Here, no import statements are used. When you run the program by saying javac, you get a file named qqq.class and no errors. To see the application work, instead of appletviewer, run another program called java.

 

C:\javaprg>java qqq

 

Exception in thread “main” java.lang.NoSuchMethodError: main

 

This program gives an error saying that you don’t have a function called main.

 

At times, you may get a different error that looks like the statement given below

 

Exception in thread “main” java.lang.NoClassDefFoundError: qqq

Then you must set the classpath to the current directory. In order to do so give the command

 

>set CLASSPATH=.;%CLASSPATH%

 

So far we have been using Java as a programming language. We have written  code that executes in a browser. Whenever code runs in a browser, it is called an applet. This time we want our code to run as a standalone application. To do so, we require a program called Java, also known as the Java Virtual Machine. We will go in depth into the differences between an applet and an application just a little later. As of now, it is important to understand that a Java applet can’t read and write to a file on disk, whereas a Java application can do anything that any executable can do.

 

In the next program, we have added a function named main.

 

qqq.java

public class qqq

{

public static void main(String a[])

{

System.out.println(“Hi “);

}

}

 

Earlier, in this chapter, we discussed static variables and static functions where we explained that we don’t have to create an object to access them. main here is a function and it takes an array of strings named a. You may choose to name the array as you please. main has been declared public, otherwise, it won’t be visible. main has also been made static so that it is available to Java without creating the object that looks like qqq. Static functions are always available irrespective of you using new or not. main returns void because it is not returning anything here. The order is important, you cannot mess with it. First you must say public or private, then static and then give the return value. Compile it and then say java qqq. It will display ‘hi’.

C:\javaprg>java qqq

 

hi

 

Now let’s print out a[0] and a[1].

 

qqq.java

public class qqq

{

public static void main(String a[])

{

System.out.println(a[0]);

System.out.println(a[1]);

}

}

 

Run the compiler and then say java qqq. It will give an error saying, ArrayIndexOutOfBoundsException.

 

C:\javaprg>java qqq

 

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 0

        at qqq.main(qqq.java:5)

 

Say java qqq one at the command prompt, this will first show one on the screen and then give the same error.  

 

C:\javaprg>java qqq one

 

one

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 1

        at qqq.main(qqq.java:6)

 

To eliminate the error, say java qqq one two.

 

C:\javaprg>java qqq one two

 

one

two

 

Simply saying java qqq does not create an array of strings because no parameters have been given after qqq. java qqq one will create only one element in the array because only one argument is specified. Hence printing the second member will give an error because the array is limited to only one member. The last command that you tried, java qqq one two, creates two elements and since you are displaying two members you see no errors. Elements in the array are created with respect to the parameters specified. What we are trying to say here is that if you go beyond the bounds of the array, an exception will be generated.

 

The next program is a generic one, which displays all the command line arguments without showing any errors.

 

qqq.java

public class qqq

{

public static void main(String a[])

{

int i;

for ( i = 0 ; i < a.length ; i++)

System.out.println(a[i]);

}

}

 

C:\javaprg>java qqq one

one

 

C:\javaprg>java qqq one two three

one

two

three

 

In Java, an array class has a member called length. If you say java qqq one, a.length will be 1 because there is only one member. java qqq one two three will make a.length 3 as there are three members. Since the condition is i< a.length, the value of i will start from 0 and keep changing till it is less than 3 i.e. 2. System.out.println will therefore print a[0] ,a[1], a[2]. This is how, depending on the parameters passed, all the members of the array can be displayed.

 

Now, let’s try writting data to the disk.

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

}

catch (Exception e){e.getMessage();}

}

}

 

In this program, fos is an object that looks like FileOutputStream. We know how much shortcuts are appreciated, so to avoid writing the full name the import statement has been used. To create a new instance FileOutputStream requires one parameter, the name of the file. Our subdirectory is c:\javaprg and the file name we want to use is z.ser. Similarly, make sure you give the complete path to the constructor. fos is now an object that looks like FileOutputStream. The name FileOutputStream itself suggests that the file will be in output mode, i.e. we can write to the file. Stop here, compile the file and run it. You will find that z.ser is created in the subdirectory but it’s size is 0 bytes.

 

Now to write to this file.

To do that, another object is needed that looks like ObjectOutputStream. This class takes the FileOutputStream variable as a parameter and so we pass fos to it. It is closed on the next line.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

 

Compile this program and run it. A directory listing in the javaprg subdirectory will display the file size as 4 bytes.

 

The bytes are shown in dec, char and hex below.

 

172 ¬ ac

237 í ed

0  0

5 - 5

 

Now we will actually write to this file.You may wish to write strings and many more things to the file. oos is used to write to fos, fos stands for z.ser. In the program below, we are simply writing AB.

 

 

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(“AB”);

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

 

Check the size of the file. It is a very small file and the size is 9 bytes. You can also see 2, which is the length of the string and then AB.

 

172 ¬ ac

237 í ed

0  0

5 - 5

116 t 74

0  0

2  2

65 A 41

66 B 42

 

In the program below, we are writing two strings to the file. One string is AB and the other is CDE. The output is shown below.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(“AB”);

oos.writeObject(“CDE”);

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

 

You will notice that the string always starts with 116, followed by 0. After that, we have the length of the string and then the string itself.

 

172 ¬ ac

237 í ed

0  0

5 - 5

116 t 74

0  0

2  2

65 A 41

66 B 42

116 t 74

0  0

3  3

67 C 43

68 D 44

69 E 45

 

You can’t be satisfied with just this, can you? So let’s write an entire object to a file in one stroke.

 

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

xxx x;

x = new xxx();

try

{

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(x);

oos.close();

}

catch (Exception e){e.getMessage();}

}

}

class xxx implements Serializable

{

public int i=6;

String s = “hi”;

}

 

In the above program, x is an object that looks like xxx. It has two members - int i and String s. writeObject with x will write the entire object to the file.

 

Class xxx implements Serializable. This is an interface but it does not have any functions. So,it is assumed that it only has variables. ObjectOutputStream is used to take the entire object and write it to disk in one stroke.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

xxx x;

FileInputStream fos = new FileInputStream(“c:\\javaprg\\z.ser”);

ObjectInputStream oos = new ObjectInputStream(fos);

x = ( xxx ) oos.readObject();

System.out.println(x.i);

System.out.println(x.s);

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

class xxx implements Serializable

{

public int i=60;

String s = “Byes”;

}

 

 

Instead of FileOutputStream and ObjectOutputStream, the above program uses FileInputStream and ObjectInputStream. In the previous example, we had writeObject and here we have readObject. We have to cast it to xxx. Now when you print x.i and x.n, the value will be that of the earlier program, it doesn’t take the new values.

 

C:\javaprg>java qqq

6

hi

 

Let’s see how arrays can be saved to the disk.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

String a[];

a = new String[2];

a[0] = “hi”;

a[1] =  “Nono”;

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(a);

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

 

The concept of arrays has already been explained. Here ‘a’, an array of strings, is created. a[0] is initialized to ‘hi’ and a[1] to ‘Nono’. Using writeObject, the entire array is written to disk. ‘a’ has the length of the array so it knows how much to write.

 

Thinking of taking a break? Great idea! But please do so after trying out the next program. The next program will read from the same file into an array. So you need to try this right now.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

String a[];

FileInputStream fos = new FileInputStream(“c:\\javaprg\\z.ser”);

ObjectInputStream oos = new ObjectInputStream(fos);

a = (String [] ) oos.readObject();

System.out.println(a[0]);

System.out.println(a[1]);

System.out.println(a.length);

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

 

C:\javaprg>java qqq

 

hi

Nono

2

 

First run the earlier program where you wrote the array to the disk and then the current one. In this program, readobject will read from the file. Whatever is read in is assigned to a. Since we have cast the output to an array of strings, ‘a’ now contains the data as Strings. Therefore, it displays ‘hi’ and ‘Nono’ and the length is displayed as 2. 

 

Multi-Dimensional Arrays

 

Let’s understand multidimensional arrays. In Java, there is no such thing as a multidimensional array. Arrays are limited to one dimension. But what if you need more complex data structures such as two or three dimensions? For this you can fake multidimensional structures by building arrays within arrays.

 

qqq.java

public class qqq

{

public static void  main(String argv[])

{

String a[][] = {{ “a1”,”a2",”a3"} , { “b1”,”b2",”b3"} };

int i;

for ( i = 0 ; i<a.length ; i++)

{

System.out.println(a[i][0]);

}

}

}

 

C:\javaprg>java qqq

 

a1

b1

 

In order to create multidimensional arrays use two square brackets. In this program, the multidimensional array is of strings, so it is declared as string a [ ] [ ]. At the same time, the array is also being initialized using curly braces. Since there are two sets of curly brackets, we can say that we have an array a[2],[3]. Each one of them is an array and each one has 3 members.

 

The for loop starts by initializing i to 0. a.length will give you 2 because the array only has two members, each one of them in turn is an array, so their length should be three. When we say println a[i][0], it is a[0][0]. This will print the first member of the first array, that is, a1. When i becomes 1 we are printing a[1][0] and this will print b1.

 

The next program enables you to print all the members in the array.

 

qqq.java

public class qqq

{

public static void  main(String argv[])

{

String a[][] = {{ “a1”,”a2",”a3"} , { “b1”,”b2",”b3"} };

int i,j;

for ( i = 0 ; i<a.length ; i++)

{

System.out.println(a[i][0]);

for ( j = 0 ; j < a[i].length ; j++)

{

System.out.println(a[i][j]);

}

}

}

}

 

C:\javaprg>java qqq

 

a1

a1

a2

a3

b1

b1

b2

b3

 

The objective here is to print all the members in the array. i in the for loop is initialized to 0; the condition is i<a.length. a.length will give 2. So the println will print the value in a[0][0], which is a1. Then we have another for loop within the earlier for. j in the loop gets initialized to 0; the condition is j < a[i].length. The length here will be 3 because the first array has 3 members. Remember, a[0] and a[1] are both arrays. So j will be 0,1,2 and thus will print all members of the array.

 

The same is applicable to ints also. The following program demonstrates this.

 

qqq.java

public class qqq

{

public static void  main(String argv[])

{

int [][] m;

m = new int[3][];

int i;int k = 1;

for ( i = 0 ; i < m.length ; i++)

{

m[i] = new int[2];

m[i][0] = k++;

m[i][1] = k++;

}

for ( i = 0; i < m.length ; i++)

{

System.out.println(m[i][0]);

System.out.println(m[i][1]);

System.out.println(“—”);

}

}

}

 

C:\javaprg>java qqq

 

1

2

3

4

5

6

 

Here, the variable has been created in a slightly different manner. You can create it either by saying int m[ ] [ ] or int [ ][ ]m. The square brackets can be put before or after the variable, it’s just a question of syntax. They both mean the same thing. m=new int[3][ ] will create 3 arrays but how many members each of them will hold is not known. It has been left blank for the moment. Then we have a for statement where m.length will be 3 because there are 3 arrays, so the for will go on three times. 

 

In the for, we say m[i] = new int[2]. This is how we initialize these arrays. Since i is 0, the 0th member of the array will hold two values. m[i][0] is actually m[0][0], which we are initializing to the value of k. k as of now is 0 which is the value given to m[0][0]. k++ will increment the value by 1, so k becomes 1. This is given to m[0][1]. When the bracket is reached, i will be incremented by 1, so it becomes 1. m[1] is now an array which will have 2 elements. And m[i][0] is now m[1][0] which refers to the second array and the 0 th element in the array. Since k has not been initialized again, k will retain its original value and will keep incrementing.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

String a[][] = {

{ “a1”,”a2",”a3" },{ “b1”,”b2",”b3" }};

//a = new String[3][2];

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(a);

oos.close();

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

 

In this program, the multidimensional array has 2 arrays each with 3 members. It could have been created as shown in the comment and we could have initialized every member later. It really doesn’t make any difference. With writeObject, the entire object will be written to disk. 

 

 

The next program reads from the file and prints it in the form of an array.

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

String a[][];int i,j;

FileInputStream fos = new FileInputStream(“c:\\javaprg\\z.ser”);

ObjectInputStream oos = new ObjectInputStream(fos);

a = (String [][] ) oos.readObject();

System.out.println(a.length);

for ( i = 0 ; i < a.length ; i++)

{

for ( j = 0 ; j < a[i].length ; j++)

System.out.println(a[i][j]);

}

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

 

C:\javaprg>java qqq

 

2

a1

a2

a3

b1

b2

b3

 

Here, we want to read all the strings, so we read the object into a. The for statement initializes i to 0 and it keeps incrementing i till it is less than the length, which is 2. This for will go on twice, the second for is the one that prints a1, a2, a3 in the first round and b1, b2, b3 in the second round.

See how easy it is to write and read an array of strings. Let’s see if we can work with chars as comfortably.

 

The difference between an array of chars and an array of strings is that a char holds a single entity whereas a string holds multiple entities.

 

The following program has a multidimensional array with 2 arrays each 3 members large. The values given are ‘a’ ‘b’ ‘c’ ‘d’ ‘e’ ‘f’.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

char  a[][] = {

{ ‘a’,’b’,’c’ },{ ‘d’,’e’,’f’ }};

FileOutputStream fos = new FileOutputStream(“c:\\javaprg\\z.ser”);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(a);

oos.close();

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

 

As previously, we are writing the object in one stroke to the file and in a similar way we are reading it from the file.

 

qqq.java

import java.io.*;

public class qqq

{

public static void  main(String argv[])

{

try

{

char a[][];

FileInputStream fos = new FileInputStream(“c:\\javaprg\\z.ser”);

ObjectInputStream oos = new ObjectInputStream(fos);

a = (char [][] ) oos.readObject();

System.out.println(a[0]);

System.out.println(a[0][0]);

System.out.println(a[1]);

}

catch (Exception e){System.out.println(“bye”);e.getMessage();}

}

}

 

C:\javaprg>java qqq

 

abc

a

def

 

a[0] within the println prints all the characters in one stroke. To print individual characters we have to be specific, like a[0][0] is ‘a’ and so on. a[0] will print the entire string ‘abc’ and a[1] will print out the entire string ‘def’.

 

Thus the crux is that using ObjectInputStream and ObjectOutputStream you can read and write arrays to the disk.

 

Conclusion

 

In this chapter, you learnt about static variables and static functions and gained some insight into the concept of constructors.We also showed you how you can create your own exceptions.

 

Apart from the applets that you have been creating, you are now able to create applications.  Using ObjectInputStream and ObjectOutputStream you can read and write arrays to the disk. After readig this hapter, we hope you are now well versed with the concept of multidimensional arrays in connection with objects and classes.