The Program

< Back to Main Page

// start SysClass.java

///////////////////////////////////////////////////////////////////////////////\
// Brueckner, Scott
// COP2805 E001 99001, Thu 7:00-9:45 pm, Seat 24
// Programming Project 1, Due Date 11-11-1999
//
// SysClass.java: Java application to demonstrate some features of Java's
//                System class. It also demonstrates some rudimentary keyboard
//                and disk file handling.
//
// Notes:
//
//   This program scratches the surface of Java's System class. It's main
//   function is to "ask" the system (via the System class) for a couple of its
//   "properties," and use these properties to assist in writing a list of ALL
//   system properties to a text file. You can then review the text file to see
//   what properties the System class reports.
//
//   This is not a particularly "robust" application, and will bomb-out to the
//   operating system on any exception. A "real" application should provide
//   exception handling.
//
//   This program was compiled and run in the following environments:
//
//     - Java 1.1 on a Linux (Unix) platform
//     - Java 1.2 ("Java 2") on a Windows 95 platform
//
//   Since the program needed to run under Java 1.1, I wasn't able to use
//   methods that were introduced in Java 1.2. Of particular interest is the
//   setProperty() method.
//
//   In Java 1.2, you can easily change existing system properties (and add new
//   properties) with the System.setProperty() method. Based on the API
//   documentation, it looks like there might be a way to do this under Java
//   1.1, but I didn't have time to experiment. It's worth noting that the
//   setProperty() method does _not_ permanently change system properties; the
//   changes are only in effect during the execution of the program.
//
//   This program will ask you for a file name. The list of system properties
//   will then be written to this file in the current directory. The program
//   will _not_ overwrite an existing file, but it _will_ bomb-out if you
//   specify an illegal file name.
//
//   I recommend that you keep the file name short (even just one or two
//   characters) or the screen output will "wrap."
///////////////////////////////////////////////////////////////////////////////\

import java.io.*;
import java.util.*;

/////////////////////
public class SysClass
/////////////////////
{
  ///////////////////////////////////////////////////////
  public static void main(String args[]) throws Exception // Bombs on exception
  ///////////////////////////////////////////////////////
  {
    // The first few lines of code get the "line separator" from the system.
    // This is the character (or characters) used to terminate lines in
    // text files. Also, the line separator is added to the keyboard input
    // stream (System.in) when the user presses the ENTER key.
    //
    // The line separator is platform-specific. The standard line separators
    // for the major microcomputer platforms are:
    //
    //   DOS:  CarriageReturn/LineFeed ("\r\n")
    //   Unix: LineFeed                ("\n")
    //   Mac:  CarriageReturn          ("\r")

    String stLineSep;      // String containing the system line separator
    int    iLineSepLength; // Length of the line separator
    int    iLineSepEnd;    // Last character of the line separator

                                                           // Line separator:
    stLineSep      = System.getProperty("line.separator"); //   Get it
    iLineSepLength = stLineSep.length();                   //   Length
    iLineSepEnd    = stLineSep.charAt(iLineSepLength - 1); //   Last character

    // The next statement creates a File object corresponding to the current
    // directory (where we'll create the output file).
    //
    // The "file separator" is the system property containing the character (or
    // characters) that delimits file and directory names. Again, this is
    // platform-specific:
    //
    //   DOS:  \ (backslash)
    //   Unix: / (forward slash)
    //   Mac:  I don't know
    //
    // In the DOS and Unix environments, the current directory can be referenced
    // as a period (.) followed by the file separator:
    //
    //   DOS:  .\
    //   Unix: ./
    //
    // Using the "file.separator" property from the system makes the application
    // portable to different platforms. (At least between DOS and Unix. I don't
    // know for sure if this works on a Mac, although I expect it does).

    File filDir = new File("." + System.getProperty("file.separator"));

    int          iThisChar; // To read individual chars with System.in.read()
    boolean      bError;                                 // Entry error flag
    StringBuffer bufOutputFileName = new StringBuffer(); // Buffer for file name
    File         filOutput         = new File("");       // Output disk file

    System.out.println(
      "\nThis program writes a list of the current system properties");

    System.out.println("to a text file in the current directory.");

    do // while (bError)
    {
      bError = false;                 // Clear error flag
      bufOutputFileName.setLength(0); // Truncate file name buffer

      System.out.print("\nPlease enter a name for the text file: "); // Prompt

      // The next block reads the keyboard input one character at a time until
      // it encounters the last character of the system line separator. This
      // will presumably be the end of the keyboard buffer. It retains ALL
      // characters read, including the line separator, so we can see what
      // really came in from the keyboard.
      //
      // This logic won't work if the last character of the line separator
      // occurs more than once in the line separator, but as far as I know,
      // this doesn't happen (at least it doesn't on PCs, Unix boxes, or Macs).
      //
      // You probably wouldn't do it this way in practice. Using a
      // 'BufferedReader' is much easier, and it takes care of the details for
      // you, including removing the line separator.

      do
      {
        iThisChar = System.in.read();                 // Get the next char
        bufOutputFileName.append( (char) iThisChar ); // Add it to the buffer
        System.out.print("  " + iThisChar);           // Display ASCII value
      } while (iThisChar != iLineSepEnd);

      System.out.println(" <-- ASCII codes input");

      // Display length before removing the line separator
      System.out.println("  " +
                         "Length of input BEFORE removing line separator = " +
                         bufOutputFileName.length());

      // Remove the line separator
      bufOutputFileName.setLength(bufOutputFileName.length() - iLineSepLength);

      // Display length after removing the line separator
      System.out.println("  " +
                         "Length of input AFTER  removing line separator = " +
                         bufOutputFileName.length());

      // Display ASCII values of remaining characters
      for (int i = 0; i < bufOutputFileName.length(); i++)
        System.out.print("  " + (int) bufOutputFileName.charAt(i));

      System.out.println(" <-- ASCII codes retained");

      if (bufOutputFileName.length() == 0) // User didn't enter anything
      {
        System.out.println("\n  Please enter SOMETHING.");
        bError = true;
        continue;
      }

      // Create an new File object in the current directory. This doesn't
      // actually create the file, only a reference to it. If the user enters
      // an illegal file name (based on the underlying operating system), an
      // exception will be thrown when an attempt is made to create the file.

      filOutput = new File(filDir, bufOutputFileName.toString());

      // The next clause disallows the file name if the file already exists or
      // if there is a directory of the same name in the current directory. A
      // "real" application should probably allow the user to overwrite an
      // existing file. On the platforms tested, the exists() method was able
      // to see "hidden" files.
      //
      // In Java 1.2, you can use File.createNewFile() and check its return
      // value to see if the file was really created (createNewFile() returns
      // 'false' if the file already exists, and unlike C, it won't truncate
      // an existing file). The createNewFile() method wasn't introduced until
      // until Java 1.2; I couldn't use it since my test Linux platform is
      // running Java 1.1.

      if (filOutput.exists())
      {
        if (filOutput.isDirectory())
          System.out.println("\n  " + filOutput + " is a directory.");

        else
          System.out.println("\n  File already exists.");

        bError = true;
        continue;
      }

    } while (bError);

    // Attach a buffered output stream to the File object. This statement
    // creates the disk file with a length of zero bytes (since it doesn't
    // already exist). If we had used File.createNewFile() (in Java 1.2) above,
    // the file would already be created.
    //
    // If the user entered an illegal file name, a FileNotFoundException will
    // be thrown. A "real" application should handle this.

    BufferedWriter bufOutputStream = new BufferedWriter(
                                     new OutputStreamWriter(
                                     new FileOutputStream(filOutput)));

    // Get the system property list. If a Security Manager is operating, it may
    // not allow this (it will throw a SecurityException). Even if this is true,
    // it _may_ allow explicit access to individual properties with the
    // System.getProperty(String) method.

    Properties prSystemProperties = System.getProperties();

    String     stPropertyKey;   // Current system property key (name)
    String     stPropertyValue; // Current system property value

    // We'll pull out the individual properties with an enumerator. Iterators
    // are nicer, but the Properties.propertyNames() method returns an
    // Enumeration object.
    //
    // It would be nice to sort the list, but I wasn't that ambitious. Also,
    // notice that the 'for' header doesn't contain an increment.

    for (
          Enumeration e = prSystemProperties.propertyNames();
          e.hasMoreElements();
        )
    {

      stPropertyKey   = ( (String) e.nextElement() );      // Property name
      stPropertyValue = System.getProperty(stPropertyKey); // Get property value

      // Write the name of the property to the file. This will write in ASCII
      // (one byte characters). If you want Unicode output (two byte characters,
      // use writeChars() instead of write().

      bufOutputStream.write(stPropertyKey + " = ");

      // Write the value of the property to the file. We'll handle the line
      // separator differently. Since 'line.separator' contains the characters
      // that actually make up the line separator, if we write it "as is," it
      // will just produce a blank line. Instead, we'll write the ASCII value(s)
      // as int(s).

      if (stPropertyKey.equals("line.separator"))
        for (int i = 0; i < iLineSepLength; i++)
          bufOutputStream.write( (int) stPropertyValue.charAt(i) + " " );

      else
        bufOutputStream.write(stPropertyValue);

      // The next statement writes the line separator to the file, causing an
      // advance to the next line. This will create a text file in the proper
      // format for the current platform.
      //
      // If you wanted to create a text file for a specific (possibly different)
      // operating system, you could use one of the following statements
      // instead:
      //
      //   bufOutputStream.write("\r\n"); // DOS  (carriage return / line feed)
      //   bufOutputStream.write("\n");   // Unix (line feed)
      //   bufOutputStream.write("\r");   // Mac  (carriage return)
      //
      // Note that if you follow the common practice of just blindly using a
      // "\n" to terminate the lines, you're actually creating a UNIX text file.
      // Other operating systems may not display the file correctly.

      bufOutputStream.write(stLineSep);

    } // end for (Enumeration e)

    // Be sure to close the file. This is particularly important for buffered
    // output streams. My testing indicated that all bytes might not be written
    // unless the file is explicitly closed.

    bufOutputStream.close();
    System.out.println("\nSystem properties written to " + bufOutputFileName);
    return;

  } // end main()

} // end class SysClass

// end SysClass.java
< Back to Main Page | ^ Up to Top