Issue #009 September, 1996 Contents: Comparing C/C++ and Java Part 9 - Operators Introduction to Applet Programming Part 5 - Text Input Performance - Fast I/O For Text Lines COMPARING C/C++ AND JAVA PART 9 - OPERATORS If you know C or C++, many of the operators found in Java will be familiar. But there are also some differences worth noting. 1. Java has no unsigned data types, and so the operator >>> has been added to support unsigned right shifting. That is, a right shift using >> will propagate the sign, whereas a shift using >>> will zero fill the high bits. >>>= also has been added. The operator "instanceof" can be used to determine whether an object is an instance of a given class, as in: if (s instanceof String) // do something 2. Java does not have any of the following C/C++ operators: , -> .* ->* :: 3. In Java "*" and "&" have no meaning for doing pointer arithmetic or addressing, because Java has no user-visible pointers. 4. Java has no operator overloading, for example overloading [] to provide a "smart" vector type of some sort. 5. In Java "+" can be used for String concatenation. 6. Finally, as a quick summary of Java operators, here is a table of operators and their precedences, highest to lowest. This table is taken from Arnold & Gosling's "The Java Programming Language", page 300: postfix [] . (params) expr++ expr-- unary ++expr --expr +expr -expr ~ ! creation/cast new (type)expr multiplicative * / % additive + - shift << >> >>> relational < > >= <= instanceof equality == != bitwise AND & bitwise exclusive OR ^ bitwise inclusive OR | logical AND && logical OR || conditional ?: assignment = += -= *= /= %= >>= <<= >>>= &= ^= |= INTRODUCTION TO APPLET PROGRAMMING PART 5 - TEXT INPUT In the last issue we talked about button input, where the user clicks on a button. In this issue we'll continue our discussion of input and discuss text input a bit, starting with low-level character input. To illustrate what such input looks like, here is a simple applet: import java.applet.*; import java.awt.*; public class text1 extends Applet { int x = 40; int y = 40; public boolean keyUp(Event e, int key) { if ((e.modifiers & Event.CTRL_MASK) != 0) { char buf[] = new char[2]; buf[0] = '^'; key += 0x40; buf[1] = (char)key; getGraphics().drawChars(buf, 0, 2, x, y); x += getFontMetrics(getFont()).charWidth('^'); x += getFontMetrics(getFont()).charWidth(key); x += 2; } else { char buf[] = new char[1]; buf[0] = (char)key; getGraphics().drawChars(buf, 0, 1, x, y); x += getFontMetrics(getFont()).charWidth(key); x++; } return true; } } and the HTML that drives it: Interface to Text Applet keyUp() is a method called in response to a keyboard event. Once inside keyUp(), we go through some machinations to determine what sort of a key was pressed, for example whether a control key was hit. The code in this example is incomplete but illustrative of the technique. Once we have a key, we want to echo it in the applet window. We use drawChars() for this. Then we need to update the X position in the window for drawing the next character, and to do that, we use the FontMetrics class with the current font, to determine the width of a character that's just been drawn. In other words, this applet simply echoes its input to the window, and throws in a "^" in front of control characters. There are higher-level methods for entering text, which we will look at in future issues. PERFORMANCE - FAST I/O FOR TEXT LINES In issue #002 we traced through the steps involved in doing Java character output. The Java I/O system offers flexibility in structuring various sorts of I/O, with the possibility of adding filtering layers and so on. But this flexibility has a performance cost, caused in part by the layers themselves and in part by the method call overhead. As we've said previously, Java is a young language and it's not totally clear how various pieces will shake out. But it's worth considering how some common types of I/O might be speeded up. As an example, consider text lines. These are lines of characters ending in \n while being manipulated in a program, and ending in \r\n or \n when residing in a disk file. \r\n is used with Microsoft system software on PCs, while \n is used on UNIX systems. Suppose that we wish to read and write sets of text lines sequentially, for example, reading all the lines in a file, one after another, or writing to a file in a similar way. One way to do this is illustrated in the following example. We set up our own file output buffer, and move characters from a passed-in String object directly to the buffer. We use the low-level FileOutputStream class to actually do the I/O; it has a write() method that takes a vector of bytes and outputs them to a file or to standard output. We determine whether \r\n or just \n is needed on output, by looking at the system properties list. JDK 1.0 running on Windows NT has an anomaly or feature in the way that standard output is treated with respect to line delimiters, and so if output is to standard out it's treated differently. This particular example, with the driver program below, runs about 5X faster than the equivalent using System.out.print(). The code for doing input of text lines is analogous. import java.io.*; class StdioOutput { private static final int BUFSIZ = 4096; private FileOutputStream fos; private byte buf[] = new byte[BUFSIZ]; private int left; private int pos; private static boolean need_cr = false; // figure out whether we have \r or \r\n static { String s = System.getProperty("line.separator"); need_cr = (s.length() >= 1 && s.charAt(0) == '\r'); } // open a file public StdioOutput(String fn) throws IOException { fos = new FileOutputStream(fn); left = BUFSIZ; pos = 0; } // open standard output public StdioOutput() throws IOException { fos = new FileOutputStream(FileDescriptor.out); left = BUFSIZ; pos = 0; need_cr = false; } // close a file public synchronized void close() throws IOException { flush(); fos.close(); fos = null; } // flush output public synchronized void flush() throws IOException { if (pos > 0) fos.write(buf, 0, pos); left = BUFSIZ; pos = 0; } // output a character public synchronized void putc(int c) throws IOException { // flush output buffer if needed if (left <= 0) flush(); // handle simple case if (c != '\n' || !need_cr) { left--; buf[pos++] = (byte)c; } // handle \r\n else { left--; buf[pos++] = '\r'; if (left <= 0) flush(); left--; buf[pos++] = '\n'; } } // output a line public synchronized void putline(String s) throws IOException { int len = (s == null ? 0 : s.length()); // empty string if (len < 1) return; // whole string will fit in buffer if (len + 1 <= left) { if (len >= 2) { s.getBytes(0, len - 1, buf, pos); pos += len - 1; left -= len - 1; } putc(s.charAt(len - 1)); } // whole string won't fit, do a character at a time else { for (int i = 0; i < len; i++) putc(s.charAt(i)); } } } public class testio2 { public static void main(String args[]) { StdioOutput fout = null; String s; try { fout = new StdioOutput(); } catch (Throwable e) { System.err.println("* file opening error *"); } try { int N = 10000; for (int i = 1; i <= N; i++) // System.out.print("xxxxxxxxxxxxxxx\n"); fout.putline("xxxxxxxxxxxxxxx\n"); } catch (Throwable e) { System.err.println("*** file I/O error ***"); } try { fout.close(); } catch (Throwable e) { System.err.println("* file closing error *"); } } } ACKNOWLEDGEMENTS Thanks to Thierry Ciot, Irv Kanode, Mike Paluka, and Alan Saldanha for help with proofreading. SUBSCRIPTION INFORMATION / BACK ISSUES To subscribe to the newsletter, send mail to majordomo@world.std.com with this line as its message body: subscribe java_letter Back issues are available via FTP from: rmii.com /pub2/glenm/javalett or on the Web at: http://www.rmii.com/~glenm There is also a C++ newsletter. To subscribe to it, say: subscribe c_plus_plus using the same majordomo@world.std.com address. ------------------------- Copyright (c) 1996 Glen McCluskey. All Rights Reserved. This newsletter may be further distributed provided that it is copied in its entirety, including the newsletter number at the top and the copyright and contact information at the bottom. Glen McCluskey & Associates Professional Computer Consulting Internet: glenm@glenmccl.com Phone: (800) 722-1613 or (970) 490-2462 Fax: (970) 490-2463 FTP: rmii.com /pub2/glenm/javalett (for back issues) Web: http://www.rmii.com/~glenm