|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
These tips and cautions will help you write better programs and save you from agonizing over why the compiler produces error messages.
locals command to view the contents of a classfile's local variables can fail if javac compiled the equivalent source file with
the -g debugging option unspecified.
-g debugging option to javac from within JCreator?
Last month, I asked you to answer some questions and enhance the Editor program. Here are my answers (which appear in red).
Character class?
Java requires a Character class for the following reasons:
char variable in these objects proves impossible, that variable's value must wrap inside a Character object, which subsequently stores in a data structure object.Character objects; for example, a method that converts an arbitrary character argument representing a lowercase letter to another character
representing the uppercase equivalent.String objects?
Java regards string literals as String objects to serve as a convenience for developers. Substituting string literals for String object reference variables reduces the amount of code you must write.
Editor application with the following capabilities:DELFCH to DELCH and modify that command to take a single integer argument identifying the zero-based index of the character to delete in
the current line. Example: delch 2 deletes the current line's third character. Provide appropriate error checking to warn users when they specify an invalid
index (or curline contains -1, indicating no lines of text). If no more characters are in the current line, delete it and update curline as appropriate.
DEL command that deletes the current line. Use error checking to deal with the situation when curline contains -1. Update curline as appropriate.
REPL command that replaces all occurrences of a specific character in the current line with another character. Two character arguments
should follow REPL: the first argument identifies the character to replace, and the second argument identifies its replacement character. Example:
repl # * replaces all occurrences of # with *. Use appropriate error checking in case no current line exists (i.e., curline contains -1).
SETCL command that takes a single zero-based integer argument and sets curline to that value. Use appropriate error checking in case the value is out of range or curline contains -1.
LOAD and SAVE commands that let you load the contents of arbitrary text files and save the current text to a specific text file. What sort
of error checking will you need?
The following Editor source code contains the enhancements:
Read more about Tools & Methods in JavaWorld's Tools & Methods section.
// Editor.java
// ==============================================
// CAUTION:
//
// Although this program contains a LOAD command that loads a text file, not
// just any text file loads. Only text files previously saved with the SAVE
// command load. This is due to the internal UTF structure of Editor's text
// files, which differs from newline-terminated text file structure. I talk
// about UTF and files in a future Java 101 article.
// ==============================================
import java.io.*;
import java.util.StringTokenizer;
class Editor
{
public static int MAXLINES = 100;
static int curline = -1; // Current line index.
static int lastline = -1; // Last appended line index.
// The following array holds all lines of text. (Maximum is MAXLINES.)
static StringBuffer [] lines = new StringBuffer [MAXLINES];
static
{
// We assume 80-character lines. But who knows? Because StringBuffers
// dynamically expand, you could end up with some very long lines.
for (int i = 0; i < lines.length; i++)
lines [i] = new StringBuffer (80);
}
public static void main (String [] args)
{
do
{
// Prompt user to enter a command.
System.out.print ("C: ");
// Obtain the command and make sure there is no leading/trailing
// white space.
String cmd = readString ().trim ();
// Ignore blank lines.
if (cmd.length () == 0)
continue;
// =========================================
// The following commands take no arguments.
// =========================================
// Add a line of text?
if (cmd.equalsIgnoreCase ("ADD"))
{
if (lastline == MAXLINES - 1)
{
System.out.println ("FULL");
continue;
}
String line = readString ();
lines [++lastline].append (line);
curline = lastline;
continue;
}
// Display current line number?
if (cmd.equalsIgnoreCase ("CL"))
{
System.out.println ((curline == -1)
? "EMPTY" : "CL = " + curline);
continue;
}
// Delete current line?
if (cmd.equalsIgnoreCase ("DEL"))
{
if (curline == -1)
{
System.out.println ("EMPTY");
continue;
}
for (int i = curline + 1; i <= lastline; i++)
lines [i - 1] = lines [i];
lines [lastline--] = new StringBuffer (80);
if (curline > lastline)
curline = lastline;
continue;
}
// Dump all lines to standard output?
if (cmd.equalsIgnoreCase ("DUMP"))
{
for (int i = 0; i <= lastline; i++)
System.out.println (i + ": " + lines [i]);
continue;
}
// Display help information on available commands?
if (cmd.equalsIgnoreCase ("HELP"))
{
System.out.println ("Available commands:\n");
System.out.println ("ADD");
System.out.println ("CL");
System.out.println ("DEL");
System.out.println ("DELCH index");
System.out.println ("DUMP");
System.out.println ("HELP");
System.out.println ("LOAD filename");
System.out.println ("REPL oldchar newchar");
System.out.println ("SAVE filename");
System.out.println ("SETCL index");
continue;
}
// Terminate editor?
if (cmd.equalsIgnoreCase ("QUIT"))
break;
// =====================================================
// Because the following commands take at least one argument,
// we need a StringTokenizer to parse out command name and
// each argument.
// =====================================================
StringTokenizer st = new StringTokenizer (cmd);
// Extract command name.
String cmdname = st.nextToken ().toUpperCase ();
// Delete a character on the current line?
if (cmdname.equalsIgnoreCase ("DELCH"))
{
if (curline == -1)
{
System.out.println ("EMPTY");
continue;
}
if (!st.hasMoreTokens ())
{
System.out.println ("DELCH: index argument expected");
continue;
}
int index = 0;
try
{
index = toInteger (st.nextToken ());
}
catch (IllegalArgumentException e)
{
System.out.println ("DELCH: nonnumeric index argument");
continue;
}
if (index >= lines [curline].length ())
{
System.out.println ("DELCH: index out of range");
continue;
}
lines [curline].deleteCharAt (index);
// When current line contains no more characters, delete that
// line and choose a new line to be current.
if (lines [curline].length () == 0)
{
for (int i = curline + 1; i <= lastline; i++)
lines [i - 1] = lines [i];
lines [lastline--] = new StringBuffer (80);
if (curline > lastline)
curline = lastline;
}
continue;
}
// Load text file into editor?
if (cmdname.equalsIgnoreCase ("LOAD"))
{
if (!st.hasMoreTokens ())
{
System.out.println ("LOAD: filename argument expected");
continue;
}
String filename = st.nextToken ();
DataInputStream dis = null;
try
{
FileInputStream fis = new FileInputStream (filename);
dis = new DataInputStream (fis);
int i = 0;
try
{
do
{
String line = dis.readUTF ();
lines [i].replace (0, lines [i].length (), line);
i++;
}
while (i < MAXLINES);
}
catch (EOFException e)
{
}
if (i == 0)
{
curline = -1;
lastline = -1;
}
else
{
curline = i - 1;
lastline = i - 1;
}
}
catch (IOException e)
{
System.out.println ("unable to load from file");
}
finally
{
try
{
if (dis != null)
dis.close ();
}
catch (IOException e)
{
}
}
continue;
}
// Replace on the current line all occurrences of a specific
// character with another character?
if (cmdname.equalsIgnoreCase ("REPL"))
{
if (curline == -1)
{
System.out.println ("EMPTY");
continue;
}
if (!st.hasMoreTokens ())
{
System.out.println ("REPL: first char argument expected");
continue;
}
char c1 = st.nextToken ().charAt (0);
if (!st.hasMoreTokens ())
{
System.out.println ("REPL: second char argument expected");
continue;
}
char c2 = st.nextToken ().charAt (0);
for (int i = 0; i < lines [curline].length (); i++)
if (lines [curline].charAt (i) == c1)
lines [curline].setCharAt (i, c2);
continue;
}
// Save lines to text file?
if (cmdname.equalsIgnoreCase ("SAVE"))
{
if (curline == -1)
{
System.out.println ("EMPTY");
continue;
}
if (!st.hasMoreTokens ())
{
System.out.println ("SAVE: filename argument expected");
continue;
}
String filename = st.nextToken ();
DataOutputStream dos = null;
try
{
FileOutputStream fos = new FileOutputStream (filename);
dos = new DataOutputStream (fos);
for (int i = 0; i <= lastline; i++)
dos.writeUTF (lines [i].toString ());
}
catch (IOException e)
{
System.out.println ("unable to save to file");
}
finally
{
try
{
if (dos != null)
dos.close ();
}
catch (IOException e)
{
}
}
continue;
}
// Set current line to a specific index?
if (cmdname.equalsIgnoreCase ("SETCL"))
{
if (curline == -1)
{
System.out.println ("EMPTY");
continue;
}
if (!st.hasMoreTokens ())
{
System.out.println ("SETCL: index argument expected");
continue;
}
int index = 0;
try
{
index = toInteger (st.nextToken ());
}
catch (IllegalArgumentException e)
{
System.out.println ("SETCL: nonnumeric index argument");
continue;
}
if (index > lastline)
{
System.out.println ("SETCL: index out of range");
continue;
}
curline = index;
continue;
}
System.out.println ("unrecognized command");
}
while (true);
}
// Read a string of characters from the keyboard. String might end with a
// carriage return character -- depending on platform.
static String readString ()
{
StringBuffer sb = new StringBuffer (80);
try
{
do
{
int ch = System.in.read ();
if (ch == '\n')
break;
sb.append ((char) ch);
}
while (true);
}
catch (IOException e)
{
}
return sb.toString ();
}
// Convert a string of digits to an integer value. Throw a new
// IllegalArgumentException object if the string contains a nondigit.
static int toInteger (String value)
{
int temp = 0;
for (int i = 0; i < value.length (); i++)
{
char c = value.charAt (i);
if (c < '0' || c > '9')
throw new IllegalArgumentException ("Not a digit: " + c);
temp *= 10;
temp += (c - '0');
}
return temp;
}
}