Download (direct link):
Listing 2.3 BmpWriter3.java (continued)
24 Item 2
060 imgPixels = new int[imgWidth * imgHeight];
061 // pixels are stored in rows
064 PixelGrabber pg = new 2
067 } catch (Exception e)
069 throw new IOException("Exception. Reason: "
+ e. toString());
072 // now open the file
073 FileOutputStream fos = new FileOutputStream(sFilename);
074 FileChannel fc = fos.getChannel();
076 // write the "header"
077 boolean padded=false;
078 // first calculate the scanline size
079 iScanLineSize = 3 * width;
080 if (iScanLineSize % 2 != 0)
083 padded = true;
086 // now, calculate the file size
087 fileSize = 14 + 40 + (iScanLineSize * imgHeight);
088 sizeOfBitmap = iScanLineSize * imgHeight;
090 // create a ByteBuffer
091 ByteBuffer bbuf = ByteBuffer.allocate(fileSize);
095 // now put out file header
// . .. some output to buffer code omitted for brevity ...
Listing 2.3 (continued)
NIO Performance and Pitfalls 25
114: // put the pixels
115: for (int i= (imgHeight - 1); i > II 0 i 1 1
117: byte pad = 0;
118: for (int j=0; j < imgWidth; j++)
120: int pixel = imgPixels[(i * width) + j];
121: byte alpha = (byte) ((pixel >> 24) & f f x 0
122: byte red = (byte) ((pixel >> 16) & f f x 0
123: byte green = (byte) ((pixel >> 8) & f f x 0
124: byte blue = (byte) ((pixel ) & f f x 0
126: // put them bgr
131: if (padded)
140: public static void main(String args)
// method omitted for brevity - available on Web site.
Listing 2.3 (continued)
The key lines of Listing 2.3 are as follows:
¦¦ At lines 64 and 65, we grab the image pixels (as integers) using the Pixel-Grabber class.
¦¦ At lines 73 and 74, we first create the FileOutputStream for the BMP output file and then get the FileChannel using the getChannel() method. This demonstrates the integration between the existing IO packages (FileOutputStream) and the new IO packages (FileChannel).
26 Item 2
¦¦ At line 91, we create a ByteBuffer via the static allocate() method. It is important to note that there is also an allocateDirect() method, which allows you to create DirectBuffers. A DirectBuffer is a buffer allocated by the operating system to reduce the number of copies between the virtual machine and the operating system. How DirectBuffers are implemented differs for each operating system. Additionally, a direct buffer may be more expensive to create because of the interaction with the operating system, so they should be used for long-standing buffers.
¦¦ There are three values associated with all buffers: position, limit, and capacity. The position is the current location to read from or write to. The limit is the amount of data in the array. The capacity is the size of the underlying array.
¦¦ At line 92, we use the order() method to set the endian order to LITTLE_ENDIAN.
¦¦ At lines 96 and 97, we use putInt() and putShort() to write integers and shorts, respectively, in Little Endian order, to the byte buffer.
¦¦ At line 135, we flip the buffer from reading to writing using the flip() method. The flip() method sets the limit to the current position and the position back to 0.
¦¦ At line 136, we write the byte buffer to the underlying file.
Now we can finish our discussion of NIO by examining how the package implements non-blocking IO.
Non-Blocking Server IO
Before NIO, Java servers would create a thread to handle each incoming client connection. You would see a code snippet like this:
Socket s = serverSocket.accept();
Thread handler = new Thread(new SocketHandler(s)); handler.start();
More experienced programmers would reuse threads via a thread pool instead of instantiating a new thread each time. So, the first key new feature of NIO is the ability to manage multiple connections by way of a multiplexer class called a Selector. Multiplexing is a networking term associated with protocols like the User Datagram Protocol (UDP) that multiplexes communication packets to multiple processes. Figure 2.1 demonstrates multiplexing.
NIO Performance and Pitfalls 27
Figure 2.1 UDP multiplexing example.
So, after hearing about Selectable channels and deciding that they are a good thing, we set out to use them. We examine the JDK documentation and study the example programs like NBTimeServer.java. The "non-blocking time server" demonstrates nonblocking IO by creating a simple server to send the current time to connecting clients. For our demonstration program, we will write a server that is the start of a collaborative photo space. In that space we need to share images and annotations. Here we only scratch the surface of the application by creating a server to receive the images and annotations from clients. Listing 2.4 has the initial attempt at a non-blocking server: