Java tutorial
/* * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation", "Tapestry" * must not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * or "Tapestry", nor may "Apache" or "Tapestry" appear in their * name, without prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE TAPESTRY CONTRIBUTOR COMMUNITY * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; /** * A kind of super-formatter. It is sent a stream of binary data and * formats it in a human-readable dump format which is forwarded to * its output stream. * * <p>Currently, output is in hex though options to change that may * be introduced. * * @author Howard Lewis Ship * @version $Id: BinaryDumpOutputStream.java,v 1.1 2003/03/05 22:59:31 hlship Exp $ * **/ public class BinaryDumpOutputStream extends OutputStream { private PrintWriter out; private boolean locked = false; private boolean showOffset = true; private int bytesPerLine = 16; private int spacingInterval = 4; private char substituteChar = '.'; private String offsetSeperator = ": "; private int offset = 0; private int lineCount = 0; private int bytesSinceSpace = 0; private char[] ascii = null; private boolean showAscii = true; private String asciiBegin = " |"; private String asciiEnd = "|"; private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * Creates a <code>PrintWriter</code> for <code>System.out</code>. * **/ public BinaryDumpOutputStream() { this(new PrintWriter(System.out, true)); } public BinaryDumpOutputStream(PrintWriter out) { this.out = out; } public BinaryDumpOutputStream(Writer out) { this.out = new PrintWriter(out); } public void close() throws IOException { if (out != null) { if (lineCount > 0) finishFinalLine(); out.close(); } out = null; } private void finishFinalLine() { // Since we only finish the final line after at least one byte has // been written to it, we don't need to worry about // the offset. while (lineCount < bytesPerLine) { // After every <n> bytes, emit a space. if (spacingInterval > 0 && bytesSinceSpace == spacingInterval) { out.print(' '); bytesSinceSpace = 0; } // Two spaces to substitute for the two hex digits. out.print(" "); if (showAscii) ascii[lineCount] = ' '; lineCount++; bytesSinceSpace++; } if (showAscii) { out.print(asciiBegin); out.print(ascii); out.print(asciiEnd); } out.println(); } /** * Forwards the <code>flush()</code> to the <code>PrintWriter</code>. * **/ public void flush() throws IOException { out.flush(); } public String getAsciiBegin() { return asciiBegin; } public String getAsciiEnd() { return asciiEnd; } public int getBytesPerLine() { return bytesPerLine; } public String getOffsetSeperator() { return offsetSeperator; } public boolean getShowAscii() { return showAscii; } public char getSubstituteChar() { return substituteChar; } public void setAsciiBegin(String value) { if (locked) throw new IllegalStateException(); asciiBegin = value; } public void setAsciiEnd(String value) { if (locked) throw new IllegalStateException(); asciiEnd = value; } public void setBytesPerLine(int value) { if (locked) throw new IllegalStateException(); bytesPerLine = value; ascii = null; } public void setOffsetSeperator(String value) { if (locked) throw new IllegalStateException(); offsetSeperator = value; } public void setShowAscii(boolean value) { if (locked) throw new IllegalStateException(); showAscii = value; } /** * Sets the character used in the ASCII dump that substitutes for characters * outside the range of 32..126. * **/ public void setSubstituteChar(char value) { if (locked) throw new IllegalStateException(); substituteChar = value; } public void write(int b) throws IOException { char letter; if (showAscii && ascii == null) ascii = new char[bytesPerLine]; // Prevent further customization after output starts being written. locked = true; if (lineCount == bytesPerLine) { if (showAscii) { out.print(asciiBegin); out.print(ascii); out.print(asciiEnd); } out.println(); bytesSinceSpace = 0; lineCount = 0; offset += bytesPerLine; } if (lineCount == 0 && showOffset) { writeHex(offset, 4); out.print(offsetSeperator); } // After every <n> bytes, emit a space. if (spacingInterval > 0 && bytesSinceSpace == spacingInterval) { out.print(' '); bytesSinceSpace = 0; } writeHex(b, 2); if (showAscii) { if (b < 32 | b > 127) letter = substituteChar; else letter = (char) b; ascii[lineCount] = letter; } lineCount++; bytesSinceSpace++; } private void writeHex(int value, int digits) { int i; int nybble; for (i = 0; i < digits; i++) { nybble = (value >> 4 * (digits - i - 1)) & 0x0f; out.print(HEX[nybble]); } } }