All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.util.ByteUtil Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.*;

import com.hfg.util.io.ByteSource;

//------------------------------------------------------------------------------
/**
 * General byte utility functions.
 *
 * @author J. Alex Taylor, hairyfatguy.com
 */
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// 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.1 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  USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------

public class ByteUtil
{

   private static final int BIT1 = 1;
   private static final int BIT2 = 2;
   private static final int BIT3 = 4;
   private static final int BIT4 = 8;
   private static final int BIT5 = 16;
   private static final int BIT6 = 32;
   private static final int BIT7 = 64;
   private static final int BIT8 = 128;

   private static final byte[] bit = new byte[8];
   static
   {
      bit[0] = BIT1;
      bit[1] = BIT2;
      bit[2] = BIT3;
      bit[3] = BIT4;
      bit[4] = BIT5;
      bit[5] = BIT6;
      bit[6] = BIT7;
      bit[7] = (byte)BIT8;
   }

   private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();

   //**************************************************************************
   // PUBLIC FUNCTIONS
   //**************************************************************************

   //--------------------------------------------------------------------------
   /**
    Returns a string like "10110011" to represent the specified 8-bit byte.
    @param inByte the byte to be represented as a bit string
    @return the bit string representing the specified byte
    */
   public static String getBitString(byte inByte)
   {
      StringBuilder buffer = new StringBuilder();
      buffer.append(((inByte & BIT8) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT7) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT6) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT5) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT4) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT3) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT2) > 0 ? "1" : "0"));
      buffer.append(((inByte & BIT1) > 0 ? "1" : "0"));

      return buffer.toString();
   }

   //--------------------------------------------------------------------------
   /**
    Returns the 8-bit byte corresponding to a specified string like "10110011".
    @param inByteString the bit string to be converted to a byte
    @return the byte represented by the specified bit string
    */
   public static byte getByteFromBitString(String inByteString)
   {
      int outByte = 0;
      for (int i = 0; i < 8; i++)
      {
         if (inByteString.charAt(i) == '1') outByte += bit[7 - i];
      }

      return (byte) outByte;
   }

   //--------------------------------------------------------------------------
   /**
    Decomposes a byte (8-bits) into two 4-bit bytes.
    @param inByte the source byte to be converted
    @return the byte array (length of 2) of 4-bit bytes
    */
   public static byte[] get4bitBytes(byte inByte)
   {
      byte[] bytes = new byte[1];
      bytes[0] = inByte;
      return marshallBytes(bytes, 8, 4);
   }

   //--------------------------------------------------------------------------
   /**
    Decomposes a byte[] into 5-bit bytes.
    @param inBytes the source byte[] to be converted
    @return the byte array of 5-bit bytes
    */
   public static byte[] get5bitBytes(byte[] inBytes)
   {
      return marshallBytes(inBytes, 8, 5);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a hex string representing the given byte array.
    @param inBytes the source byte array
    @return the hexadecimal string represented by the specified byte array.
    */
   public static String getHexString(byte[] inBytes)
   {
      char[] chars = new char[2 * inBytes.length];
      for (int i = 0; i < inBytes.length; ++i)
      {
         chars[2 * i]     = HEX_CHARS[(inBytes[i] & 0xF0) >>> 4];
         chars[2 * i + 1] = HEX_CHARS[inBytes[i] & 0x0F];
      }

      return new String(chars);
   }

   //--------------------------------------------------------------------------
   /**
    Returns an int from the given byte array.
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the int
    @param inByteOrder the byte order of the int
    @return the integer represented by the specified byte array.
    */
   public static int getInt(byte[] inBytes, int inOffset, ByteOrder inByteOrder)
   {
      return ByteBuffer.wrap(inBytes, inOffset, 4).order(inByteOrder).getInt();
   }

   //--------------------------------------------------------------------------
   /**
    Returns an int from the given byte array.
    @param inStream the InputStream source of bytes
    @param inByteOrder the byte order of the int
    @return the integer represented by the next 4 bytes from the specified InputStream
    */
   public static int getInt(InputStream inStream, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[4];
      inStream.read(bytes);
      ByteBuffer byteBuffer = ByteBuffer.wrap(bytes, 0, 4);

      return byteBuffer.order(inByteOrder).getInt();
   }

   //--------------------------------------------------------------------------
   /**
    Returns an int from the current position of the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes
    @return the integer represented in the next 4 bytes of the specified RandomAccessFile
    */
   public static int getInt(RandomAccessFile inRandomAccessFile)
      throws IOException
   {
      byte[] bytes = new byte[4];
      inRandomAccessFile.read(bytes);

      return ByteBuffer.wrap(bytes, 0, 4).getInt();
   }

   //--------------------------------------------------------------------------
   /**
    Returns an int from the current position of the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes
    @param inByteOrder the byte order of the int
    @return the integer represented in the next 4 bytes of the specified RandomAccessFile
    */
   public static int getInt(RandomAccessFile inRandomAccessFile, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[4];
      inRandomAccessFile.read(bytes);

      return ByteBuffer.wrap(bytes, 0, 4).order(inByteOrder).getInt();
   }

   //--------------------------------------------------------------------------
   /**
    Returns an int from the current position of the specified ByteSource.
    @param inByteSource the source of bytes
    @param inByteOrder the byte order of the int
    @return the integer represented in the next 4 bytes of the specified ByteSource
    */
   public static int getInt(ByteSource inByteSource, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[4];
      inByteSource.read(bytes);

      return ByteBuffer.wrap(bytes, 0, 4).order(inByteOrder).getInt();
   }

   //--------------------------------------------------------------------------
   /**
    Returns an long from the current position of the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes
    @param inByteOrder the byte order of the long
    @return the long represented in the next 8 bytes of the specified RandomAccessFile
    */
   public static long getLong(RandomAccessFile inRandomAccessFile, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[8];
      inRandomAccessFile.read(bytes);

      return ByteBuffer.wrap(bytes, 0, 8).order(inByteOrder).getLong();
   }

   //--------------------------------------------------------------------------
   /**
    Returns an long from the current position of the specified ByteSource.
    @param inByteSource the source of bytes
    @param inByteOrder the byte order of the long
    @return the long represented in the next 8 bytes of the specified ByteSource
    */
   public static long getLong(ByteSource inByteSource, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[8];
      inByteSource.read(bytes);

      return ByteBuffer.wrap(bytes, 0, 8).order(inByteOrder).getLong();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the given byte array.
    @param inBytes the source byte array
    @return the 2-byte integer represented in the first two bytes of the specified byte array
    */
   public static int get2ByteInt(byte[] inBytes)
   {
      return get2ByteInt(inBytes, 0);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the given byte[].
    @param inBytes the source byte array
    @param inByteOrder the byte order of the int
    @return the 2-byte integer represented in the first two bytes of the specified byte array
    */
   public static int get2ByteInt(byte[] inBytes, ByteOrder inByteOrder)
      throws IOException
   {
      return get2ByteInt(inBytes, 0, inByteOrder);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the given byte[].
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the int
    @param inByteOrder the byte order of the int
    @return the 2-byte integer represented in the first two bytes of the specified byte array
    */
   public static int get2ByteInt(byte[] inBytes, int inOffset, ByteOrder inByteOrder)
      throws IOException
   {
      return (int) ByteBuffer.wrap(inBytes, inOffset, 2).order(inByteOrder).getShort();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the given InputStream.
    @param inStream the InputStream source of bytes
    @return the 2-byte integer represented in the next two bytes of the specified stream
    */
   public static int get2ByteInt(InputStream inStream)
      throws IOException
   {
      byte[] bytes = new byte[2];
      inStream.read(bytes);
      return get2ByteInt(bytes, 0);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the given InputStream.
    @param inStream the InputStream source of bytes
    @param inByteOrder the byte order of the int
    @return the 2-byte integer represented in the next two bytes of the specified stream
    */
   public static int get2ByteInt(InputStream inStream, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[2];
      inStream.read(bytes);

      return (int) ByteBuffer.wrap(bytes, 0, 2).order(inByteOrder).getShort();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the current position of the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes
    @param inByteOrder the byte order of the int
    @return the 2-byte integer represented in the next two bytes of the specified stream
    */
   public static int get2ByteInt(RandomAccessFile inRandomAccessFile, ByteOrder inByteOrder)
      throws IOException
   {
      return get2ByteInt(new ByteSource(inRandomAccessFile), inByteOrder);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the current position of the specified ByteSource.
    @param inByteSource the source of bytes
    @param inByteOrder the byte order of the int
    @return the 2-byte integer represented in the next two bytes of the specified ByteSource
    */
   public static int get2ByteInt(ByteSource inByteSource, ByteOrder inByteOrder)
         throws IOException
   {
      byte[] bytes = new byte[2];
      inByteSource.read(bytes);

      return (int) ByteBuffer.wrap(bytes, 0, 2).order(inByteOrder).getShort();
   }


   //--------------------------------------------------------------------------
   /**
    Returns a 2-byte int from the given byte array.
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the int
    @return the 2-byte integer represented in the first two bytes at the specified offset of the specified byte array
    */
   public static int get2ByteInt(byte[] inBytes, int inOffset)
   {
      return (int) ByteBuffer.wrap(inBytes, inOffset, inOffset + 2).getShort();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a 1-byte int from the given byte array.
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the int
    @return the 1-byte integer represented in the first byte of the specified byte array
    */
   public static int get1ByteInt(byte[] inBytes, int inOffset)
   {
      return inBytes[inOffset] & 0xff;
   }

   //--------------------------------------------------------------------------
   /**
    Returns a short from the first 2 bytes of the given byte array.
    @param inBytes the source byte array
    @return the sort represented in the first two bytes of the specified byte array
    */
   public static short getShort(byte[] inBytes)
   {
      return getShort(inBytes, 0);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a short from the first 2 bytes of the given byte array.
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the int
    @return the short represented in the first two bytes at the specified offset of the specified byte array
    */
   public static short getShort(byte[] inBytes, int inOffset)
   {
      return (short) (inBytes[inOffset]<<8 | inBytes[inOffset + 1] & 0xFF);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a short from the first 2 bytes of the given byte array.
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the int
    @param inByteOrder the byte order of the short
    @return the short represented in the first two bytes at the specified offset of the specified byte array
    */
   public static short getShort(byte[] inBytes, int inOffset, ByteOrder inByteOrder)
   {
      return ByteBuffer.wrap(inBytes, inOffset, 2).order(inByteOrder).getShort();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a float from the given byte array.
    @param inStream the InputStream source of bytes
    @param inByteOrder the byte order of the float
    @return the float represented by the next 4 bytes from the specified InputStream
    */
   public static float getFloat(InputStream inStream, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[4];
      inStream.read(bytes);
      ByteBuffer byteBuffer = ByteBuffer.wrap(bytes, 0, 4);

      return byteBuffer.order(inByteOrder).getFloat();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a string from the bytes.
    @param inBytes the source byte array
    @param inOffset the offset within the source byte array from which to extract the String
    @param inLength the number of bytes to include in the String
    @param inByteOrder the byte order of the string
    @return the String represented at the specified offset of the specified byte array
    */
   public static String getString(byte[] inBytes, int inOffset, int inLength, ByteOrder inByteOrder)
   {
      String result = ByteBuffer.wrap(inBytes, inOffset, inLength).order(inByteOrder).asCharBuffer().toString();
      int index = result.indexOf(0x00);
      if (index >= 0)
      {
         result = result.substring(0, index);
      }

      return result;
   }

   //--------------------------------------------------------------------------
   /**
    Returns a string from the bytes.
    @param inStream the InputStream source of bytes
    @param inLength the number of bytes to include in the String
    @return the String represented at the specified offset of the specified byte array
    */
   public static String getString(InputStream inStream, int inLength)
      throws IOException
   {
      byte[] bytes = new byte[inLength];
      inStream.read(bytes);
      String result = new String(bytes);
      int index = result.indexOf(0x00);
      if (index >= 0)
      {
         result = result.substring(0, index);
      }

      return result;
   }

   //--------------------------------------------------------------------------
   /**
    Returns a String from the current position of the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes
    @param inLength the number of bytes to include in the String
    @return the String represented at the specified offset of the specified RandomAccessFile
    */
   public static String getString(RandomAccessFile inRandomAccessFile, int inLength)
      throws IOException
   {
      byte[] bytes = new byte[inLength];
      inRandomAccessFile.read(bytes);

      String result = new String(bytes);
      int index = result.indexOf(0x00);
      if (index >= 0)
      {
         result = result.substring(0, index);
      }

      return result;
   }

   //--------------------------------------------------------------------------
   /**
    Returns a String from the current position of the specified ByteSource.
    @param inByteSource the source of bytes
    @param inLength the number of bytes to include in the String
    @return the String represented at the specified offset of the specified ByteSource
    */
   public static String getString(ByteSource inByteSource, int inLength)
      throws IOException
   {
      byte[] bytes = new byte[inLength];
      inByteSource.read(bytes);

      String result = new String(bytes);
      int index = result.indexOf(0x00);
      if (index >= 0)
      {
         result = result.substring(0, index);
      }

      return result;
   }

   //--------------------------------------------------------------------------
   /**
    Returns a byte[] corresponding to an int.
    @param inValue the int to decompose into an array of 4 bytes
    @return the byte[] represented by the specified int
    */
   public static byte[] getBytesFromInt(int inValue)
      throws IOException
   {
      return ByteBuffer.allocate(4).putInt(inValue).array();
   }

   //--------------------------------------------------------------------------
   /**
    Returns a short[] derived from the specified byte[].
    @param inBytes the source byte array
    @param inNumValues the number of shorts to extract from the source byte array
    @param inByteOrder the byte order of the string
    @return a short[] derived from the specified byte[]
    */
   public static short[] getShortArray(byte[] inBytes, int inNumValues, ByteOrder inByteOrder)
   {
      short[] array = new short[inNumValues];
      for (int i = 0; i < inNumValues; i++)
      {
         array[i] = getShort(inBytes, i * 2, inByteOrder);
      }

      return array;
   }

   //--------------------------------------------------------------------------
   /**
    Returns a short[] derived from the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes; assumes that the file is already set to the proper position
    @param inNumValues the number of shorts to extract from the source byte array
    @param inByteOrder the byte order of the string
    @return a short[] derived from the specified RandomAccessFile
    */
   public static short[] getShortArray(RandomAccessFile inRandomAccessFile, int inNumValues, ByteOrder inByteOrder)
      throws IOException
   {
      return getShortArray(new ByteSource(inRandomAccessFile), inNumValues, inByteOrder);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a short[] derived from the specified ByteSource.
    @param inByteSource the source of bytes; assumes that the file is already set to the proper position
    @param inNumValues the number of shorts to extract from the source byte array
    @param inByteOrder the byte order of the string
    @return a short[] derived from the specified ByteSource
    */
   public static short[] getShortArray(ByteSource inByteSource, int inNumValues, ByteOrder inByteOrder)
      throws IOException
   {
      byte[] bytes = new byte[2 * inNumValues];
      inByteSource.read(bytes);

      return getShortArray(bytes, inNumValues, inByteOrder);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a char[] derived from the specified RandomAccessFile.
    @param inRandomAccessFile the source of bytes; assumes that the file is already set to the proper position
    @param inNumValues the number of shorts to extract from the source byte array
    @return a char[] derived from the specified RandomAccessFile
    */
   public static char[] getCharArray(RandomAccessFile inRandomAccessFile, int inNumValues)
      throws IOException
   {
      return getCharArray(new ByteSource(inRandomAccessFile), inNumValues);
   }

   //--------------------------------------------------------------------------
   /**
    Returns a char[] derived from the specified ByteSource.
    @param inByteSource the source of bytes; assumes that the file is already set to the proper position
    @param inNumValues the number of shorts to extract from the source byte array
    @return a char[] derived from the specified ByteSource
    */
   public static char[] getCharArray(ByteSource inByteSource, int inNumValues)
      throws IOException
   {
      byte[] bytes = new byte[inNumValues];
      inByteSource.read(bytes);

      char[] chars = new char[inNumValues];
      for (int i = 0; i < bytes.length; i++)
      {
         chars[i] = (char) bytes[i];
      }

      return chars;
   }

   //--------------------------------------------------------------------------
   /**
    Take bytes in one size and chunks them into bytes of the desired size.
    @param inBytes the input byte array
    @param inOrigBitsPerByte the number of (significant) bits per byte in the input byte array
    @param inOutBitsPerByte the desired number of (significant) bits per byte in the output byte array
    @return the returned byte array
     */
   public static byte[] marshallBytes(byte[] inBytes, int inOrigBitsPerByte, int inOutBitsPerByte)
   {
      int totalOutBits = inBytes.length * inOrigBitsPerByte;

      int outBytesLength;
      if (inOrigBitsPerByte > inOutBitsPerByte)
      {
         outBytesLength = (int) Math.ceil(totalOutBits / (float) inOutBitsPerByte);
      }
      else
      {
         outBytesLength = (int) Math.floor(totalOutBits / (float) inOutBitsPerByte);
      }

      byte[] outBytes = new byte[outBytesLength];
      int oldByteIdx = 0;
      byte oldByte = inBytes[oldByteIdx];
      int oldBit = inOrigBitsPerByte;
      for (int newByteIdx = 0; newByteIdx < outBytesLength; newByteIdx++)
      {
         int outByte = 0;

         for (int newBit = inOutBitsPerByte; newBit > 0; newBit--)
         {
            if ((oldByte & bit[oldBit - 1]) != 0)
            {
               outByte += bit[newBit - 1];
            }

            oldBit--;
            if (oldBit <= 0)
            {
               oldByteIdx++;
               if (oldByteIdx >= inBytes.length)
               {
                  break;
               }
               oldByte = inBytes[oldByteIdx];
               oldBit = inOrigBitsPerByte;
            }
         }

         outBytes[newByteIdx] = (byte) outByte;
      }

      return outBytes;
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy