// 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