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

com.github.katjahahn.parser.ByteArrayUtil Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright 2014 Katja Hahn
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.github.katjahahn.parser;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.sql.Array;
import java.util.Arrays;

/**
 * Utilities to convert from and to byte arrays.
 * 

* Supports hex string conversion and long/int conversion. Little endian only. *

* Differences to methods of {@link java.nio.ByteBuffer}: *

* {@link #bytesToInt(byte[])} and {@link #bytesToLong(byte[])} don't care about * the proper minimum length of the given byte array: No * {@link java.nio.BufferUnderflowException} is thrown. Thus they are more * robust. *

* {@link #byteToHex(byte[])} delimits bytes with spaces and every single byte * value is converted including prepended zero bytes in the array. *

* {@link #getBytesLongValueSafely(byte[], int, int)} will also convert arrays * that are too short for the offset and the length given. It will assume the * missing values to be zero. *

* This class is not meant to be used by library users. * * @author Katja Hahn * */ public class ByteArrayUtil { private static final Logger logger = LogManager .getLogger(ByteArrayUtil.class.getName()); /** * Utility class. Not intended to be used as object. */ private ByteArrayUtil() { } /** * Retrieves the integer value of a subarray of bytes. The values are * considered little endian. The subarray is determined by offset and * length. *

* Presumes the bytes to be not null and the length must be between 1 and 4 * inclusive. The length of bytes must be larger than or equal to length + * offset. * * @param bytes * the little endian byte array that shall be converted to int * @param offset * the index to start reading the integer value from * @param length * the number of bytes used to convert to int * @return int value */ public static int getBytesIntValue(byte[] bytes, int offset, int length) { assert length <= 4 && length > 0; assert bytes != null && bytes.length >= length + offset; byte[] value = Arrays.copyOfRange(bytes, offset, offset + length); return bytesToInt(value); } /** * Creates a byte array string representation similar to Python's strings. * Bytes are converted to ascii strings unless they are non-visible characters. In such case the byte value is * shown as hex value prefixed with "\x" * Example: \x00HelloWorld\x00 * @param bytes * @return */ public static String bytesToAsciiHexMix(byte[] bytes) { String result = ""; for(byte b : bytes) { if(b == 0x5c) { // this character --> \ result += "\\\\"; // add another escape --> \\ } else if((b <= 32 || b == 127) || (b > 127)) { // check if is visible ascii byte[] arr = {b}; result += "\\x" + byteToHex(arr); } else { // see https://stackoverflow.com/questions/17912640/byte-and-char-conversion-in-java result += (char) (b & 0xFF); } } return result; } /** * Retrieves the long value of a subarray of bytes. *

* The values are considered little endian. The subarray is determined by * offset and length. *

* Presumes the byte array to be not null and its length should be between 1 * and 8 inclusive. The length of bytes must be larger than or equal to * length + offset. * * @param bytes * the little endian byte array that shall be converted to long * @param offset * the index to start reading the long value from * @param length * the number of bytes used to convert to long * @return long value */ public static long getBytesLongValue(byte[] bytes, int offset, int length) { assert length <= 8 && length > 0; assert bytes != null && bytes.length >= length + offset; byte[] value = Arrays.copyOfRange(bytes, offset, offset + length); return bytesToLong(value); } /** * Retrieves the long value of a subarray of bytes. *

* The values are considered little endian. The subarray is determined by * offset and length. If bytes length is not large enough for given offset * and length the values are considered 0. *

* This should be used for file format fields, where part of the value has * been cut. Example: TinyPE *

* Presumes the byte array to be not null and its length should be between 0 * and 8 inclusive. * * @param bytes * the little endian byte array that shall be converted to long * @param offset * the index to start reading the long value from * @param length * the number of bytes used to convert to long * @return long value */ public static long getBytesLongValueSafely(byte[] bytes, int offset, int length) { assert length <= 8 && length >= 0 && bytes != null; byte[] value = new byte[length]; if (offset + length > bytes.length) { logger.warn("byte array not large enough for given offset + length"); } for (int i = 0; offset + i < bytes.length && i < length; i++) { value[i] = bytes[offset + i]; } return bytesToLong(value); } /** * Converts a byte array to a hex string. *

* Every single byte is shown in the string, also prepended zero bytes. * Single bytes are delimited with a space character. * * @param array * byte array to convert * @return hexadecimal string representation of the byte array */ public static String byteToHex(byte[] array) { assert array != null; return byteToHex(array, " "); } /** * Converts a byte array to a hex string. *

* Every single byte is shown in the string, also prepended zero bytes. * Single bytes are delimited with the separator. * * @param array * byte array to convert * @param separator * the delimiter of the bytes * @return hexadecimal string representation of the byte array */ public static String byteToHex(byte[] array, String separator) { assert array != null; StringBuilder buffer = new StringBuilder(); for (int i = 0; i < array.length; i++) { // add separator in between, not before the first byte if (i != 0) { buffer.append(separator); } // (b & 0xff) treats b as unsigned byte // first nibble is 0 if byte is less than 0x10 if ((array[i] & 0xff) < 0x10) { buffer.append("0"); } // use java's hex conversion for the rest buffer.append(Integer.toString(array[i] & 0xff, 16)); } return buffer.toString(); } /** * Converts a byte array to an short. The bytes are considered unsigned and * little endian (first byte is the least significant). *

* Presumes the array bytes to be not null and its length smaller than or * equal to 4 * * @param bytes * the little endian byte array that shall be converted to Short * @return short value */ public static int bytesToShort(byte[] bytes) { assert bytes != null && bytes.length <= 2; final int BYTE_SIZE = 8; int value = 0; for (int i = 0; i < bytes.length; i++) { // shift byte i times, so it gets the correct significance int shift = BYTE_SIZE * i; // (b & 0xff) treats b as unsigned byte // calculate the value to add by performing the shift value += (bytes[i] & 0xff) << shift; } return value; } /** * Converts a byte array to an int. The bytes are considered unsigned and * little endian (first byte is the least significant). *

* Presumes the array bytes to be not null and its length smaller than or * equal to 4 * * @param bytes * the little endian byte array that shall be converted to int * @return int value */ public static int bytesToInt(byte[] bytes) { assert bytes != null && bytes.length <= 4; final int BYTE_SIZE = 8; int value = 0; for (int i = 0; i < bytes.length; i++) { // shift byte i times, so it gets the correct significance int shift = BYTE_SIZE * i; // (b & 0xff) treats b as unsigned byte // calculate the value to add by performing the shift value += (bytes[i] & 0xff) << shift; } return value; } public static byte[] intToWord(int a) { byte[] ret = new byte[2]; ret[0] = (byte) (a & 0xFF); ret[1] = (byte) ((a >> 8) & 0xFF); return ret; } /** * Converts a byte array to a long. The bytes are considered unsigned and * little endian (first byte is the least significant). *

* Presumes the array bytes to be not null and its length smaller than or * equal to 8 * * @param bytes * the little endian byte array that shall be converted to int * @return long value */ public static long bytesToLong(byte[] bytes) { assert bytes != null && bytes.length <= 8; final int BYTE_SIZE = 8; long value = 0; for (int i = 0; i < bytes.length; i++) { // shift byte i times, so it gets the correct significance int shift = BYTE_SIZE * i; // (b & 0xff) treats b as unsigned byte // calculate the value to add by performing the shift value += (long) (bytes[i] & 0xff) << shift; } return value; } public static byte[] longToDWord(long a) { byte[] ret = new byte[4]; ret[0] = (byte) (a & 0xFF); ret[1] = (byte) ((a >> 8) & 0xFF); ret[2] = (byte) ((a >> 16) & 0xFF); ret[3] = (byte) ((a >> 24) & 0xFF); return ret; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy