Format a number in hexadecimal in Java

Description

The following code shows how to format a number in hexadecimal.

Example


/*  www . ja v a  2  s. com*/
/*
 * 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;

public class Main{
  public static void main(String[] argv){
     System.out.println(new HexFormat().format(123));
  }
}

/**
 * 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
 */
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);
  }
}

The code above generates the following result.





















Home »
  Java Tutorial »
    Data Format »




Java Formatter
Java Number Formatter