HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Data
You just can't get away from it. No matter what you do, a certain amount of data is always generated. One of the more profound quotes of the day can be attributed to Peter Large of Information Anxiety, where he once said:

"More Information has been produced in the last 30 years than in the previous 5,000. About 1,000 books are published internationally every day, and the total of all printed knowledge doubles every eight years."

A sobering thought. Data is to the developer what heat is to the physicist. They share the same dilemma; for every operation a small amount of heat or energy is produced; sometimes welcomed, sometimes not. Fortunately, the majority of data generated is purely cosmetic and does not require permanent storage. However, a certain amount of data does require archiving.

The main issue isn't the fact that this large quantity of data is being generated; quite the contrary. But how we organize this information in such a way that we can find what we want, when we want, is the much bigger issue. Get this right and the volume of data being handled becomes academic. The famous Sioux chieftain, Sitting Bull, remarked, back in 1876:

"'The white man knows how to make everything, but he does not know how to distribute it."

A man obviously much ahead of his time; a remark so fitting in today's mass data producing world. So, what has all this got to do with us, and more importantly, what has it to do with Java?

We are all responsible for organizing our data in a more structured manner. If it makes sense to us, then the chances that it makes sense to the next person are very high. Therefore due care and attention must be taken to all data being produced, by whatever means.

This article kicks off a mini-series of articles focusing purely on data storage and exploring some of those options open to you as a Java developer. To start with, we will look at storing simple pieces of information using simple text files. Next month, we will take a close look at the Object Serialization that was introduced in the 1.1 release of the JDK and the following month look at storing large amounts of data using a fully compliant JDBC database. finally, we will round off this mini-series by looking at how you can use Symantec's implementation of dbAnywhere to store data. So, let's begin.

Small Volumes
Data comes in many shapes and sizes, and sometimes, paradoxically, the smaller the data, the more hassle it is to handle. How many of us have broken the golden rule of never hard coding values into programs because we knew it was too much work just to save one stupid value, and by the time the program was developed, we were left with many so called 'stupid values' all hard coded and awkward to change.

Well, fear no longer. Let me introduce you to a class that will make the saving and retrieval of such 'stupid values' so easy that hard coded values will be a thing of the past.

Before we go into the implementation details of the class, let's do a quick overview of what features we would like to see from such a class. First, it has to be generic and be able to handle any number of parameters. Second, it must be able to read a pure ASCII file - that way, we will manually edit the values if necessary. Finally, it must allow the saving of data as well as reading.

A solution that has been in use on the Microsoft Windows platform for many years is the concept of an INI, or information file. This is where data is stored, on a line-by-line basis, as key/value pair. For example:

UserLogin=ceri
Password=moran

So let's take this system and use it as the basis for our new data handling class. The only difference between our implementation and the one employed in Windows is that ours will not support the notion of categories - in other words, we won't have any [ ] sections.

INI class
This class will be constructed in such a way that a calling process will be able to request a particular parameter, using the same name as appears in the main INI file. We can then identify at least one parameter, the filename of the INI file. Using this parameter we will be able to locate the file and begin reading it.

There are two approaches that may be taken at this point. The first one, and most obvious, is to open and parse the file every time a particular parameter is called for. The advantage of this system lies in the fact that no memory is used in storing all the parameters. However, if a lot of parameters exist that are continually being read, then a significant amount of time is lost opening and reopening the file each time.

A better solution is to bring all the parameters into memory in such a way that it allows for easy retrieval. The most obvious data structure for this task is the java.util.Hashtable. This structure allows us to store data, based on a unique key, which in this case is the name of the parameter (see Listing 1).

From the user's point of view there are only two public functions: one for reading parameters and the other to set parameters. The class is created by passing in the full path of the INI file, which throws an exception if something goes wrong.

As soon as the class is created, the INI file is opened and parsed, which can be seen in Listing 2. This is a simple matter of creating a new Hashtable instance and then reading the file, line-by-line. Assuming the line isn't empty, or a comment field (denoted by a hash (#) symbol), it is parsed into a key and data pair (see Listing 2).

Once retrieved, the value is inserted into the Hashtable. If for some reason the value already exists, then the subsequent insert is ignored. Notice the inner try/catch block. This is to catch any parsing problems that may be associated with a particular line. If this wasn't here, then as soon as a rogue line is met, the first try/catch block would catch the problem and reading of the file would stop. This would flag an exception at the creation of the class and the whole file would be deemed useless.

Once created, reading parameters is a simple matter of calling the appropriate methods from the Hashtable. Listing 3 illustrates the rather simple get( ) method.

If the Hashtable does indeed contain that particular parameter, then it is retrieved; otherwise, null is returned.

The majority of INI files are used purely for reading values, but there are times when writing a value back out to the INI is desirable. This is the reason for the set( ) method of the INI class. However, whereas the read method didn't incur any additional file access time, the writing method must. When a value is set, it must be written straight out to file, in case of a system crash or some other undetermined state that may prevent the class from closing naturally.

Listing 4 shows the setting of a new value. Note that if the parameter already exists, then it is first removed and then re-inserted as the new value. Having set the correct parameter in the Hashtable, it must be written out to the file, which can be seen in Listing 5.

Writing the data out to file is a trivial matter of running through the Hashtable, and formatting the data in a <key>=<value> format.

Summary
This article began the mini-series on data and shows how you, the developer, can best treat it using Java. We looked at the easiest way of storing and reading data using the INI file format found in the Microsoft Windows platform. A fully working class was developed that can be used to read and write values to such a file, with extreme ease.

The next article in this series will look at the next level up, which is Object Serialization as introduced in the 1.1 of the JDK.

About the Author
Alan Williamson is on the Board of Directors at N-ARY Limited, a UK-based Java software company, specializing in Java/JDBC/Servlets. He has recently completed his second book, focusing purely on Java Servlets, with his first book looking at using Java/JDBC/Servlets to provide a very efficient database solution. Alan can be reached at [email protected] (http://www.n-ary.com) and he welcomes all.

	

Listing 1: Storing data based on parameter.
 
  public class ini extends java.lang.Object { 
       
     private String  FileName = null; 
     private Hashtable   data = null; 
       
     public ini( String _filename ) throws Exception; 
   
     public String get( String _parameter ); 
     public void   set( String _parameter, String _value ); 
  
     private boolean reloadData( BufferedReader InFile ); 
     private boolean writeData( PrintWriter OutFile); 
  } 

Listing 2: Opening & parsing the INI file.
 
  private boolean reloadData(BufferedReader InFile){ 
      String LineIn=""; 
      String key, value; 
      int c1; 
      data = new Hashtable(); 
   
      try{ 
          while ( (LineIn=InFile.readLine()) != null ){ 
               
              if ( LineIn.length() == 0 || LineIn.charAt(0) == '#') 
                  continue; 
               
              try{ 
                  c1  = LineIn.indexOf("="); 
                  key = LineIn.substring(0,c1).toLowerCase(); 
                  value = LineIn.substring(c1+1,LineIn.length() ); 
                  data.put(key,value); 
              }catch(Exception E){} 
          } 
   
          return true; 
      }catch(Exception E){} 
      return false; 
   } 
  

Listing 3: Get ( ) method.
 
  public String get( String _parameter ){ 
       
      if ( data.containsKey( _parameter ) ) 
          return (String)data.get(_parameter); 
      else 
          return null; 
  } 

Listing 4: Setting a new value.
 
  public void set( String _parameter, String _value ){ 
       
      if ( data.containsKey( _parameter ) ){ 
          data.remove( _parameter ); 
      } 
       
      data.put(_parameter,_value); 
      try{ 
          writeData( new PrintWriter(new BufferedWriter(new FileWriter(FileName))) ); 
      }catch(Exception E){} 
  } 

Listing 5: Writing the parameter to the file.
 
  private boolean writeData(PrintWriter _Out){ 
      Enumeration E = data.keys(); 
      String key; 
      while (E.hasMoreElements()){ 
          key = (String)E.nextElement(); 
          _Out.println( key + "=" + (String)data.get(key) ); 
      } 
      _Out.flush(); 
      return true; 
  } 

Listing 6: Complete listing.
 
 import java.util.*; 
 import java.io.*;  
   
 public class ini extends Object { 
        
      private String  FileName = null; 
      private Hashtable   data = null; 
       
      public ini( String _filename ) throws Exception 
      { 
          FileName = _filename; 
          BufferedReader InFile = new BufferedReader(new FileReader(_filename)); 
   
          if ( reloadData( InFile ) == false ) 
              throw new Exception("File created an error:" + FileName ); 
      } 
   
      public String get( String _parameter ){ 
           
          if ( data.containsKey( _parameter ) ) 
              return (String)data.get(_parameter); 
          else 
              return null; 
      } 
   
      public void set( String _parameter, String _value ){ 
           
          if ( data.containsKey( _parameter ) ){ 
              data.remove( _parameter ); 
          } 
           
          data.put(_parameter,_value); 
          try{ 
             writeData( new PrintWriter(new BufferedWriter(new FileWriter(FileName))) ); 
          }catch(Exception E){} 
      } 
   
      private boolean writeData(PrintWriter _Out) 
      { 
          Enumeration E = data.keys(); 
          String key; 
          while (E.hasMoreElements()){ 
              key = (String)E.nextElement(); 
              _Out.println( key + "=" + (String)data.get(key) ); 
          } 
          _Out.flush(); 
          return true; 
      } 
   
      private boolean reloadData(BufferedReader InFile) 
      { 
          String LineIn=""; 
          String key, value; 
          int c1; 
          data    = new Hashtable(); 
   
          try{ 
              while ( (LineIn=InFile.readLine()) != null ){ 
                   
                  if ( LineIn.length() == 0 || LineIn.charAt(0) == '#') 
                     continue; 
   
                  c1  = LineIn.indexOf("="); 
                  key = LineIn.substring(0,c1).toLowerCase(); 
                  value = LineIn.substring(c1+1,LineIn.length() ); 
                  data.put(key,value); 
              } 
   
              return true; 
          }catch(Exception E){} 
          return false; 
     } 
  }
 
    
 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.