This class allows a number to be easily formatted as a hexadecimal number. The representation uses 0-f. : Hexadecimal « Data Type « Java






This class allows a number to be easily formatted as a hexadecimal number. The representation uses 0-f.

       
/*
 * Copyright (C) 1999  Jesse E. Peterson
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 *
 */

//package com.jpeterson.util;

import java.text.CharacterIterator;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.StringCharacterIterator;

/**
 * This class allows a number to be easily formatted as a hexadecimal number.
 * The representation uses 0-f.
 * 
 * @author Jesse Peterson <jesse@jpeterson.com>
 * 
 * @version 1.0
 */
public class HexFormat extends Format {
  /**
   * should upper case letters be used
   */
  private boolean upperCase;

  private String hexDigits = "0123456789abcdefABCDEF";

  /**
   * Create a new HexFormat object. By default the lower case letters 'a'-'f'
   * are used.
   * 
   * @since 1.0
   */
  public HexFormat() {
    upperCase = false;
  }

  /**
   * Format an object in a hexadecimal representation. The object
   * <CODE>number</CODE> must be an integer Number; Byte, Short, Integer, or
   * Long. If the parameter <CODE>number</CODE> is not one of these, this
   * method will throw a <CODE>IllegalArgumentException</CODE>.
   * 
   * @param number
   *            the number to format
   * @param toAppendTo
   *            where the text is to be appended
   * @param pos
   *            not used
   * @return the formatted hex number
   * 
   * @since 1.0
   */
  public StringBuffer format(Object number, StringBuffer toAppendTo,
      FieldPosition pos) {
    if (number instanceof Byte) {
      format(((Number) number).byteValue(), toAppendTo, pos);
    } else if (number instanceof Short) {
      format(((Number) number).shortValue(), toAppendTo, pos);
    } else if (number instanceof Integer) {
      format(((Number) number).intValue(), toAppendTo, pos);
    } else if (number instanceof Long) {
      format(((Number) number).longValue(), toAppendTo, pos);
    } else {
      throw new IllegalArgumentException(
          "Cannot format given Object as a Byte, Short, Integer, or Long");
    }

    return (toAppendTo);
  }

  /**
   * Format a byte, returning an 8 bit hex number. (2 digits, with leading
   * zeros)
   * 
   * @param number
   *            the byte to format
   * @return the formatted hex number
   * 
   * @since 1.0
   */
  public final String format(byte number) {
    return (format(number, new StringBuffer(), new FieldPosition(0))
        .toString());
  }

  /**
   * Format a byte, returning an 8 bit hex number. (2 digits, with leading
   * zeros)
   * 
   * @param number
   *            the number to format
   * @param toAppendTo
   *            where the text is to be appended
   * @param pos
   *            not used
   * @return the formatted binary number
   */
  public StringBuffer format(byte number, StringBuffer toAppendTo,
      FieldPosition pos) {
    int hiNibble, loNibble;
    String hiDigit, loDigit;

    hiNibble = (number >>> 4) & 0x0f;
    loNibble = number & 0x0f;
    hiDigit = Integer.toHexString(hiNibble);
    loDigit = Integer.toHexString(loNibble);
    if (upperCase) {
      hiDigit = hiDigit.toUpperCase();
      loDigit = loDigit.toUpperCase();
    } else {
      hiDigit = hiDigit.toLowerCase();
      loDigit = loDigit.toLowerCase();
    }
    toAppendTo.append(hiDigit).append(loDigit);

    return (toAppendTo);
  }

  /**
   * Format an array of bytes, returning 8 bits per byte. (2 digits with
   * leading zeros, per byte) The byte at index zero is the most significant
   * byte, making it possible to enter a stream of bytes received from a
   * serial connection very easily.
   * 
   * @param number
   *            the bytes to format
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public final String format(byte[] number) {
    return (format(number, new StringBuffer(), new FieldPosition(0))
        .toString());
  }

  /**
   * Format an array of bytes, returning 8 bits per bytes. (2 digits with
   * leading zeros, per byte) The byte at index zero is the most significant
   * byte, making it possible to enter a stream of bytes received from a
   * serial connection very easily.
   * 
   * @param number
   *            the number to format
   * @param toAppendTo
   *            where the text is to be appended
   * @param pos
   *            not used
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public StringBuffer format(byte[] number, StringBuffer toAppendTo,
      FieldPosition pos) {
    for (int i = 0; i < number.length; i++) {
      format(number[i], toAppendTo, pos);
    }

    return (toAppendTo);
  }

  /**
   * Format a short value, returning a 16 bit hexadecimal number. (4 digits
   * with leading zeros)
   * 
   * @param number
   *            the short to format
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public String format(short number) {
    return (format(number, new StringBuffer(), new FieldPosition(0))
        .toString());
  }

  /**
   * Format a short value, returning a 16 bit hexadecimal number. (4 digits
   * with leading zeros)
   * 
   * @param number
   *            the number to format
   * @param toAppendTo
   *            where the text is to be appended
   * @param pos
   *            not used
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public StringBuffer format(short number, StringBuffer toAppendTo,
      FieldPosition pos) {
    byte[] array = new byte[2];

    array[0] = (byte) ((number >>> 8) & 0xff);
    array[1] = (byte) (number & 0xff);

    return (format(array, toAppendTo, pos));
  }

  /**
   * Format an int value, returning a 32 bit hexadecimal number. (8 digits
   * with leading zeros)
   * 
   * @param number
   *            the int to format
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public String format(int number) {
    return (format(number, new StringBuffer(), new FieldPosition(0))
        .toString());
  }

  /**
   * Format an int value, returning a 32 bit hexadecimal number. (8 digits
   * with leading zeros)
   * 
   * @param number
   *            the number to format
   * @param toAppendTo
   *            where the text is to be appended
   * @param pos
   *            not used
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public StringBuffer format(int number, StringBuffer toAppendTo,
      FieldPosition pos) {
    byte[] array = new byte[4];

    array[0] = (byte) ((number >>> 24) & 0xff);
    array[1] = (byte) ((number >>> 16) & 0xff);
    array[2] = (byte) ((number >>> 8) & 0xff);
    array[3] = (byte) (number & 0xff);

    return (format(array, toAppendTo, pos));
  }

  /**
   * Format a long value, returning a 64 bit hexadecimal number. (16 digits
   * with leading zeros)
   * 
   * @param number
   *            the long to format
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public String format(long number) {
    return (format(number, new StringBuffer(), new FieldPosition(0))
        .toString());
  }

  /**
   * Format a long value, returning a 64 bit hexadecimal number. (16 digits
   * with leading zeros)
   * 
   * @param number
   *            the number to format
   * @param toAppendTo
   *            where the text is to be appended
   * @param pos
   *            not used
   * @return the formatted binary number
   * 
   * @since 1.0
   */
  public StringBuffer format(long number, StringBuffer toAppendTo,
      FieldPosition pos) {
    byte[] array = new byte[8];

    array[0] = (byte) ((number >>> 56) & 0xff);
    array[1] = (byte) ((number >>> 48) & 0xff);
    array[2] = (byte) ((number >>> 40) & 0xff);
    array[3] = (byte) ((number >>> 32) & 0xff);
    array[4] = (byte) ((number >>> 24) & 0xff);
    array[5] = (byte) ((number >>> 16) & 0xff);
    array[6] = (byte) ((number >>> 8) & 0xff);
    array[7] = (byte) (number & 0xff);

    return (format(array, toAppendTo, pos));
  }

  /**
   * Parse a hex number into a Number object. Hexadecimal numbers may be
   * indicated with a leading character designation of '0x'. If up to 1 byte
   * is parsed, returns a Byte. If more than 1 and up to 2 bytes are parsed,
   * return a Short. If more than 2 and up to 4 bytes are parsed, return an
   * Integer. If more than 4 and up to 8 bytes are parsed, return a Long.
   * 
   * @param source
   *            a binary number
   * @return return an integer form of Number object if parse is successful
   * @exception ParseException
   *                thrown if source is cannot be converted to a Byte, Short,
   *                Int, or Long.
   * 
   * @since 1.0
   */
  public Number parse(String source) throws ParseException {
    int startIndex = 0;
    Number result;

    ParsePosition parsePosition = new ParsePosition(startIndex);
    result = parse(source, parsePosition);

    if (result == null) {
      throw new ParseException("Unable to parse " + source
          + " using HexFormat", parsePosition.getIndex());
    }

    return (result);
  }

  /**
   * Parse a hex number into a Number object. Hexadecimal numbers may be
   * indicated with a leading character designation of '0x'. If up to 1 byte
   * is parsed, returns a Byte. If more than 1 and up to 2 bytes are parsed,
   * return a Short. If more than 2 and up to 4 bytes are parsed, return an
   * Integer. If more than 4 and up to 8 bytes are parsed, return a Long.
   * 
   * @param text
   *            a hexadecimal number
   * @param parsePosition
   *            position to start parsing from
   * @return return an integer form of Number object if parse is successful;
   *         <CODE>null</CODE> otherwise
   * 
   * @since 1.0
   */
  public Number parse(String text, ParsePosition parsePosition) {
    boolean skipWhitespace = true;
    int startIndex, nibbles;

    // remove whitespace
    StringCharacterIterator iter = new StringCharacterIterator(text,
        parsePosition.getIndex());
    for (char c = iter.current(); c != CharacterIterator.DONE; c = iter
        .next()) {
      if (skipWhitespace && Character.isWhitespace(c)) {
        // skip whitespace
        continue;
      }
      break;
    }

    // skip a leading hex designation of the characters '0x'
    if (text.regionMatches(iter.getIndex(), "0x", 0, 2)) {
      parsePosition.setIndex(iter.getIndex() + 2);
    } else {
      parsePosition.setIndex(iter.getIndex());
    }

    startIndex = parsePosition.getIndex();
    Number result = (Number) parseObject(text, parsePosition);

    if (result == null) {
      return (result);
    }

    nibbles = parsePosition.getIndex() - startIndex;
    if (nibbles <= 2) {
      result = new Byte(result.byteValue());
    } else if (nibbles <= 4) {
      result = new Short(result.shortValue());
    } else if (nibbles <= 8) {
      result = new Integer(result.intValue());
    } else if (nibbles <= 16) {
      result = new Long(result.longValue());
    }
    return (result);
  }

  /**
   * Parse a hexadecimal number, skipping leading whitespace. Does not throw
   * an exception; if no object can be parsed, index is unchanged! Hexadecimal
   * numbers may be indicated with a leading character designation of '0x'.
   * 
   * @param source
   *            the string to parse
   * @param status
   *            the string index to start at
   * @return The hexadecimal number as a Long object.
   * 
   * @since 1.0
   */
  public Object parseObject(String source, ParsePosition status) {
    int start = status.getIndex();
    boolean success = false;
    StringBuffer buffer = new StringBuffer();
    char c, c2;
    long result;

    StringCharacterIterator iter = new StringCharacterIterator(source,
        start);

    for (c = iter.current(); c != CharacterIterator.DONE; c = iter.next()) {
      if (Character.isWhitespace(c)) {
        // skip whitespace
        continue;
      }
      break;
    }

    if (c == CharacterIterator.DONE) {
      return (null);
    }

    if (c == '0') {
      c2 = iter.next();

      if (c2 == CharacterIterator.DONE) {
        return (null);
      }

      if (c2 == 'x') {
        // has a leading '0x' designation, so skip over it
      } else {
        // replace the two characters
        iter.previous();
        iter.previous();
      }
    } else {
      // skip back one character
      iter.previous();
    }

    // gather valid hex digits
    for (c = iter.next(); c != CharacterIterator.DONE; c = iter.next()) {
      if (hexDigits.indexOf(c) != -1) {
        success = true;
        buffer.append(c);
      } else {
        break;
      }
    }

    if (!success) {
      // no valid hex digits
      return (null);
    }

    // convert hex to long
    if (buffer.length() > 16) {
      // larger than a long, error
      // with a buffer full of nibbles, the maximum nibbles in a
      // 64 bit number is 16 nibbles
      return (null);
    }

    // parse number
    try {
      result = Long.parseLong(buffer.toString(), 16);
    } catch (NumberFormatException e) {
      // unable to parse number
      return (null);
    }

    status.setIndex(iter.getIndex());
    return (new Long(result));
  }

  /**
   * Set upper case mode for alpha characters.
   * 
   * @param upperCase
   *            true if upper case alpha characters should be used; false
   *            otherwise
   * 
   * @since 1.0
   */
  public void setUpperCase(boolean upperCase) {
    this.upperCase = upperCase;
  }

  /**
   * Get upper case mode for alpha characters.
   * 
   * @return true if upper case alpha characters should be used; false
   *         otherwise
   * 
   * @since 1.0
   */
  public boolean getUpperCase() {
    return (upperCase);
  }

  /**
   * Is upper case mode for alpha characters in affect?
   * 
   * @return true if upper case alpha characters should be used; false
   *         otherwise
   * 
   * @since 1.0
   */
  public boolean isUpperCase() {
    return (getUpperCase());
  }

  /**
   * Is lower case mode for alpha characters in affect?
   * 
   * @return true if lower case alpha characters should be used; false
   *         otherwise
   * 
   * @since 1.0
   */
  public boolean isLowerCase() {
    return (!getUpperCase());
  }

  // /////////////
  // self test //
  // /////////////
  public static void main(String[] args) {
    String result;
    HexFormat format = new HexFormat();

    // byte
    byte bNumber = 0x33;
    result = format.format(bNumber);
    if (result.equals("33")) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bNumber + " (0x" + result + ")");

    bNumber = (byte) 0x85;
    result = format.format(bNumber);
    if (result.equals("85")) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bNumber + " (0x" + result + ")");

    bNumber = (byte) 0x0f;
    result = format.format(bNumber);
    if (result.equals("0f")) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bNumber + " (0x" + result + ")");

    short sNumber = (short) 0xa2b6;
    result = format.format(sNumber);
    if (result.equals("a2b6")) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bNumber + " (0x" + result + ")");

    format.setUpperCase(true);

    int iNumber = (int) 0x4321fedc;
    result = format.format(iNumber);
    if (result.equals("4321FEDC")) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bNumber + " (0x" + result + ")");

    long lNumber = (long) 0x4321fedc4321fedcL;
    result = format.format(lNumber);
    if (result.equals("4321FEDC4321FEDC")) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bNumber + " (0x" + result + ")");

    String num = "0xfe";
    Number number = null;
    Byte bExpect = new Byte((byte) 0xfe);
    try {
      number = format.parse(num);
    } catch (ParseException e) {
      System.out.println(e);
      e.printStackTrace();
    }
    if ((number instanceof Byte) && (number.equals(bExpect))) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bExpect + " result: " + number);

    num = "0xf";
    number = null;
    bExpect = new Byte((byte) 0xf);
    try {
      number = format.parse(num);
    } catch (ParseException e) {
      System.out.println(e);
      e.printStackTrace();
    }
    if ((number instanceof Byte) && (number.equals(bExpect))) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Byte: " + bExpect + " result: " + number);

    num = "0xf0f0";
    number = null;
    Short sExpect = new Short((short) 0xf0f0);
    try {
      number = format.parse(num);
    } catch (ParseException e) {
      System.out.println(e);
      e.printStackTrace();
    }
    if ((number instanceof Short) && (number.equals(sExpect))) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Short: " + sExpect + " result: " + number);

    num = "0xdEAdbEEf";
    number = null;
    Integer iExpect = new Integer((int) 0xdEAdbEEf);
    try {
      number = format.parse(num);
    } catch (ParseException e) {
      System.out.println(e);
      e.printStackTrace();
    }
    if ((number instanceof Integer) && (number.equals(iExpect))) {
      System.out.print("Success => ");
    } else {
      System.out.print("FAILURE => ");
    }
    System.out.println("Integer: " + iExpect + " result: " + number);
  }
}

   
    
    
    
    
    
    
  








Related examples in the same category

1.Convert Decimal to Hexadecimal
2.Convert from decimal to hexadecimal
3.Convert from Byte array to hexadecimal string
4.Convert from decimal to hexadecimal with leading zeroes and uppercase
5.Hex encoder and decoder.
6.Decode hex string to a byte array
7.Returns the hexadecimal value of the supplied byte array
8.Convert byte array to Hex String
9.Convert the bytes to a hex string representation of the bytes
10.Hex decimal dump
11.hex decoder
12.Get Base64 From HEX
13.Converts a hex string to a byte array.
14.append hex digit
15.dump an array of bytes in hex form
16.Get byte array from hex string
17.Check if the current character is an Hex Char <hex> ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
18.Helper function that returns a char from an hex
19.Hex encoder/decoder implementation borrowed from BouncyCastle
20.Java Hex dump Library
21.Util for digesting and encoding bytes/strings.
22.Provide hex utility for converting bytes to hex string
23.Number in hexadecimal format are used throughout Freenet.
24.Convert to/from Hex string
25.This class provides methods for working with hexadecimal representations of data.
26.Hex Util