001: package com.protomatter.util;
002:
003: /**
004: * {{{ The Protomatter Software License, Version 1.0
005: * derived from The Apache Software License, Version 1.1
006: *
007: * Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
008: *
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution,
022: * if any, must include the following acknowledgment:
023: * "This product includes software developed for the
024: * Protomatter Software Project
025: * (http://protomatter.sourceforge.net/)."
026: * Alternately, this acknowledgment may appear in the software itself,
027: * if and wherever such third-party acknowledgments normally appear.
028: *
029: * 4. The names "Protomatter" and "Protomatter Software Project" must
030: * not be used to endorse or promote products derived from this
031: * software without prior written permission. For written
032: * permission, please contact support@protomatter.com.
033: *
034: * 5. Products derived from this software may not be called "Protomatter",
035: * nor may "Protomatter" appear in their name, without prior written
036: * permission of the Protomatter Software Project
037: * (support@protomatter.com).
038: *
039: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
040: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
041: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
042: * DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
043: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
044: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
045: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
046: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
047: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
048: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
049: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
050: * SUCH DAMAGE. }}}
051: */
052:
053: import java.io.*;
054: import java.text.*;
055:
056: /**
057: * A binary data printer. This is basically a pretty-printer for
058: * binary data.
059: */
060: public class ByteDisplay {
061: // things are faster if we cache these strings
062: private static String ZERO = "0";
063: private static String DOT = ".";
064: private static String SPACE = " ";
065: private static String TWO_SPACE = " ";
066: private static String THREE_SPACE = " ";
067: private static String CR = "\n";
068: private static String HEADER = "offset hex data ascii data\n";
069:
070: /**
071: * Display the given byte.
072: */
073: public static String displayBytes(int b) {
074: byte[] thebyte = new byte[1];
075: thebyte[0] = (byte) b;
076: return displayBytes(thebyte);
077: }
078:
079: /**
080: * Display the given byte array.
081: */
082: public static String displayBytes(byte[] b) {
083: return displayBytes(b, 0, b.length);
084: }
085:
086: /**
087: * Display the given byte array, starting at the given offset
088: * and ending after the given length.
089: */
090: public static String displayBytes(byte[] b, int off, int len) {
091: StringBuffer buf = new StringBuffer(2048);
092: int end = off + len;
093: buf.append(HEADER);
094: int i, j, c;
095:
096: for (i = off; i < end; i += 16) {
097: if (i < 100000)
098: buf.append(SPACE);
099: if (i < 10000)
100: buf.append(SPACE);
101: if (i < 1000)
102: buf.append(SPACE);
103: if (i < 100)
104: buf.append(SPACE);
105: if (i < 10)
106: buf.append(SPACE);
107: buf.append(String.valueOf(i));
108: buf.append(THREE_SPACE);
109:
110: // hex display
111: for (j = i; j < end && j < i + 16; j++) {
112: c = b[j] & 0xff;
113: if (c < 16)
114: buf.append(ZERO);
115: buf.append(Integer.toHexString(c));
116: buf.append(SPACE);
117: }
118: if (j == end) // pad for end
119: {
120: while (j++ < i + 16)
121: buf.append(THREE_SPACE);
122: }
123:
124: // ascii display
125: buf.append(TWO_SPACE);
126: for (j = i; j < end && j < i + 16; j++) {
127: c = b[j] & 0xff;
128: if (c < 32 || c > 127)
129: buf.append(DOT);
130: else
131: buf.append((char) c);
132: }
133: buf.append(CR);
134: }
135: return buf.toString();
136: }
137:
138: /**
139: * Display a file's contents. Takes the first command-line
140: * argument as the name of the file to display.
141: */
142: public static void main(String args[]) {
143: if (args.length != 1 && args.length != 2) {
144: System.out.println("Usage: ByteDisplay filename [size]");
145: System.exit(0);
146: }
147: try {
148: ByteArrayOutputStream bytes = new ByteArrayOutputStream();
149: FileInputStream in = new FileInputStream(new File(args[0]));
150: int size = Integer.MAX_VALUE;
151: if (args.length == 2)
152: size = Integer.parseInt(args[1]);
153:
154: byte[] buffer = new byte[16];
155: int read = 0;
156: int total = 0;
157: while (((read = in.read(buffer)) != -1) && (total < size)) {
158: bytes.write(buffer, 0, read);
159: total += read;
160: }
161: System.out.println("Read " + bytes.size() + " bytes from "
162: + args[0]);
163: System.out.println(displayBytes(bytes.toByteArray()));
164: } catch (Exception x) {
165: x.printStackTrace();
166: }
167: }
168: }
|