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

com.cedarsoftware.util.ByteUtilities Maven / Gradle / Ivy

The newest version!
package com.cedarsoftware.util;

import java.util.Arrays;

/**
 * A utility class providing static methods for operations on byte arrays and hexadecimal representations.
 * 

* {@code ByteUtilities} simplifies common tasks such as encoding byte arrays to hexadecimal strings, * decoding hexadecimal strings back to byte arrays, and identifying if a byte array represents GZIP-compressed data. *

* *

Key Features

*
    *
  • Convert hexadecimal strings to byte arrays ({@link #decode(String)}).
  • *
  • Convert byte arrays to hexadecimal strings ({@link #encode(byte[])}).
  • *
  • Check if a byte array is GZIP-compressed ({@link #isGzipped(byte[])}).
  • *
  • Internally optimized for performance with reusable utilities like {@link #toHexChar(int)}.
  • *
* *

Usage Example

*
{@code
 * // Encode a byte array to a hexadecimal string
 * byte[] data = {0x1f, 0x8b, 0x3c};
 * String hex = ByteUtilities.encode(data); // "1F8B3C"
 *
 * // Decode a hexadecimal string back to a byte array
 * byte[] decoded = ByteUtilities.decode("1F8B3C"); // {0x1f, 0x8b, 0x3c}
 *
 * // Check if a byte array is GZIP-compressed
 * boolean isGzip = ByteUtilities.isGzipped(data); // true
 * }
* *

Design Notes

*
    *
  • The class is designed as a utility class, and its constructor is private to prevent instantiation.
  • *
  • All methods are static and thread-safe, making them suitable for use in concurrent environments.
  • *
  • The {@code decode} method returns {@code null} for invalid inputs (e.g., strings with an odd number of characters).
  • *
* *

Performance Considerations

*

* The methods in this class are optimized for performance: *

    *
  • {@link #encode(byte[])} avoids excessive memory allocations by pre-sizing the {@link StringBuilder}.
  • *
  • {@link #decode(String)} uses minimal overhead to parse hexadecimal strings into bytes.
  • *
*

* * @author John DeRegnaucourt ([email protected]) * Ken Partlow ([email protected]) *
* Copyright (c) Cedar Software LLC *

* 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 *

* License *

* 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. */ public final class ByteUtilities { // For encode: Array of hex digits. static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); // For decode: Precomputed lookup table for hex digits. // Maps ASCII codes (0–127) to their hex value or -1 if invalid. private static final int[] HEX_LOOKUP = new int[128]; static { Arrays.fill(HEX_LOOKUP, -1); for (char c = '0'; c <= '9'; c++) { HEX_LOOKUP[c] = c - '0'; } for (char c = 'A'; c <= 'F'; c++) { HEX_LOOKUP[c] = 10 + (c - 'A'); } for (char c = 'a'; c <= 'f'; c++) { HEX_LOOKUP[c] = 10 + (c - 'a'); } } /** * Magic number identifying a gzip byte stream. */ private static final byte[] GZIP_MAGIC = {(byte) 0x1f, (byte) 0x8b}; private ByteUtilities() { } /** * Convert the specified value (0 .. 15) to the corresponding hex digit. * * @param value to be converted * @return '0'...'F' in char format. */ public static char toHexChar(final int value) { return HEX_ARRAY[value & 0x0f]; } /** * Converts a hexadecimal string into a byte array. * Returns null if the string length is odd or any character is non-hex. */ public static byte[] decode(final String s) { return decode((CharSequence) s); } /** * Converts a hexadecimal CharSequence into a byte array. * Returns null if the sequence length is odd, null, or contains non-hex characters. */ public static byte[] decode(final CharSequence s) { if (s == null) { return null; } final int len = s.length(); // Must be even length if ((len & 1) != 0) { return null; } byte[] bytes = new byte[len >> 1]; for (int i = 0, j = 0; i < len; i += 2) { char c1 = s.charAt(i); char c2 = s.charAt(i + 1); // Check if the characters are within ASCII range if (c1 >= HEX_LOOKUP.length || c2 >= HEX_LOOKUP.length) { return null; } int hi = HEX_LOOKUP[c1]; int lo = HEX_LOOKUP[c2]; if (hi == -1 || lo == -1) { return null; } bytes[j++] = (byte) ((hi << 4) | lo); } return bytes; } /** * Converts a byte array into a string of hex digits. */ public static String encode(final byte[] bytes) { if (bytes == null) { return null; } char[] hexChars = new char[bytes.length * 2]; for (int i = 0, j = 0; i < bytes.length; i++) { int v = bytes[i] & 0xFF; hexChars[j++] = HEX_ARRAY[v >>> 4]; hexChars[j++] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars); } /** * Checks if the byte array represents gzip-compressed data. */ public static boolean isGzipped(byte[] bytes) { return isGzipped(bytes, 0); } /** * Checks if the byte array represents gzip-compressed data starting at the given offset. * * @param bytes the byte array to inspect * @param offset the starting offset within the array * @return true if the bytes appear to be GZIP compressed */ public static boolean isGzipped(byte[] bytes, int offset) { return bytes != null && bytes.length - offset >= 2 && bytes[offset] == GZIP_MAGIC[0] && bytes[offset + 1] == GZIP_MAGIC[1]; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy