it.greenvulcano.util.bin.BinaryUtils.java Source code

Java tutorial

Introduction

Here is the source code for it.greenvulcano.util.bin.BinaryUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2016 GreenVulcano ESB Open Source Project.
 * All rights reserved.
 *
 * This file is part of GreenVulcano ESB.
 *
 * GreenVulcano ESB 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 3 of the License, or
 * (at your option) any later version.
 *
 * GreenVulcano ESB 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 GreenVulcano ESB. If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package it.greenvulcano.util.bin;

import it.greenvulcano.util.txt.TextUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.io.IOUtils;

/**
 * This class contains static utility methods to manage binary buffers
 * 
 * @version 3.0.0 Feb 17, 2010
 * @author GreenVulcano Developer Team
 * 
 * 
 **/
public final class BinaryUtils {

    /**
     * Dumps the content of a byte array as a sequence of integers
     * 
     * @param arr
     *        the array to convert
     * @return the converted value
     */
    public static String dumpByteArrayAsInts(byte[] arr) {
        StringBuilder buf = new StringBuilder("");
        for (int i = 0; i < arr.length; i++) {
            buf.append(arr[i]);
            if (i != (arr.length - 1)) {
                buf.append(" ");
            }
        }
        return buf.toString();
    }

    /**
     * Dumps the content of a byte array as a sequence of integers (Hex format)
     * 
     * @param arr
     *        The byte array
     * @return The String conversion of the buffer bytes as integer values in
     *         2-Hex-digits output format
     */
    public static String dumpByteArrayAsHexInts(byte[] arr) {
        StringBuilder buf = new StringBuilder("");
        for (byte element : arr) {
            String byteValueAsHex = Integer.toHexString(element);
            if (byteValueAsHex.length() < 2) {
                buf.append("0").append(byteValueAsHex);
            } else {
                buf.append(byteValueAsHex.substring(byteValueAsHex.length() - 2));
            }
        }
        return buf.toString().toUpperCase();
    }

    /**
     * Dumps the Hex formatted sequence as a byte array
     * 
     * @param hexArr
     *        The 2-Hex-digits string to convert
     * @return the byte array, or an empy array if input is malformed
     */
    public static byte[] dumpHexIntsAsByteArray(String hexArr) {
        if ((hexArr.length() % 2) != 0) {
            return new byte[0];
        }
        byte[] byteArr = new byte[hexArr.length() / 2];
        int eb = 0;
        int ih = 0;
        while (eb < byteArr.length) {
            byteArr[eb] = (byte) Integer.parseInt(hexArr.substring(ih, ih + 2), 16);
            eb++;
            ih += 2;
        }
        return byteArr;
    }

    /**
     * Convert sequences of characters (into an input string) representing an
     * escape sequence into the corresponding escape sequences
     * 
     * @param input
     *        the input string
     * @return the converted string
     */
    public static String unescapeString(String input) {
        StringBuilder buf = new StringBuilder("");
        int i = 0;
        while (i < input.length()) {
            char currChar = input.charAt(i);
            if ((currChar == '\\') && (i < (input.length() - 1))) {
                char toAdd = 0;
                char nextChar = input.charAt(++i);
                if (nextChar == '0') {
                    // End-of-string escape sequence
                    toAdd = '\0';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == 'b') {
                    // backspace escape sequence
                    toAdd = '\b';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == 't') {
                    // tab escape sequence
                    toAdd = '\t';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == 'n') {
                    // linefeed escape sequence
                    toAdd = '\n';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == 'f') {
                    // formfeed escape sequence
                    toAdd = '\f';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == 'r') {
                    // carriage return escape sequence
                    toAdd = '\r';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == '\"') {
                    // double quote escape sequence
                    toAdd = '\"';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == '\'') {
                    // single quote escape sequence
                    toAdd = '\'';
                    buf.append(toAdd);
                    i++;
                } else if (nextChar == '\\') {
                    // backslash escape sequence
                    String strToAdd = "\\\\";
                    buf.append(strToAdd);
                    i++;
                } else {
                    // It's not an escape sequence
                    buf.append(currChar).append(nextChar);
                    i++;
                }
            } else {
                buf.append(currChar);
                i++;
            }
        }
        return buf.toString();
    }

    /**
     * This method tokenizes a given string using a given byte sequence as
     * separator and returns a <tt>List</tt> containing found tokens. The
     * returned <tt>List</tt> is NEVER null (it may have zero components,
     * anyway).
     * 
     * @param theString
     *        the <tt>String</tt> to be tokenized.
     * @param separatorByteSequence
     *        the byte sequence separator between tokens.
     * @return a <tt>List</tt> containing found tokens.
     */
    public static List<String> splitByByteSequenceSeparator(String theString, byte[] separatorByteSequence) {
        List<String> tokenList = new ArrayList<String>();

        if ((theString == null) || theString.equals("")) {
            return tokenList;
        }

        byte[] input = theString.getBytes();

        if (Arrays.equals(input, separatorByteSequence)) {
            return tokenList;
        }

        if ((separatorByteSequence == null) || (separatorByteSequence.length == 0)) {
            tokenList.add(theString);
            return tokenList;
        }

        if (findByteSequenceWithinByteArray(input, separatorByteSequence) == -1) {
            tokenList.add(theString);
            return tokenList;
        }

        int startNextToken = 0;
        int endNextToken = 0;
        int maxPosition = input.length;

        while (startNextToken < maxPosition) {
            endNextToken = findByteSequenceWithinByteArray(input, separatorByteSequence, startNextToken);
            if (endNextToken != -1) {

                if (endNextToken > startNextToken) {

                    byte[] buffer = new byte[endNextToken - startNextToken];
                    System.arraycopy(input, startNextToken, buffer, 0, buffer.length);
                    String currToken = new String(buffer);
                    tokenList.add(currToken);
                }
                startNextToken = endNextToken + separatorByteSequence.length;
            } else {
                if (startNextToken != (maxPosition - 1)) {
                    byte[] buffer = new byte[maxPosition - startNextToken];
                    System.arraycopy(input, startNextToken, buffer, 0, buffer.length);
                    String currToken = new String(buffer);
                    tokenList.add(currToken);
                    startNextToken = maxPosition;
                }
            }
        }
        return tokenList;
    }

    /**
     * Loads the full content of a file.<br>
     * The file must be reachable via the <i>parent classloader</i>, or at least
     * via the <i>system classloader</i>.<br>
     * The full content of a file is then stored into a <code>byte</code> array.<br>
     * 
     * @param filename
     *        the name of the file to be read
     * @return the full content of the file, stored into a <code>byte</code>
     *         array
     * @throws IOException
     *         if any I/O error occurs
     */
    public static byte[] readFileAsBytesFromCP(String filename) throws IOException {
        filename = TextUtils.adjustPath(filename);
        URL url = ClassLoader.getSystemResource(filename);
        if (url == null) {
            throw new IOException("File " + filename + " not found in classpath");
        }

        InputStream in = null;
        try {
            in = url.openStream();
            return inputStreamToBytes(in);
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

    /**
     * Loads the full content of a file into a <code>byte</code> array.<br>
     * 
     * @param filename
     *        the name of the file to be read
     * @return the full content of the file, stored into a <code>byte</code>
     *         array
     * @throws IOException
     *         if any I/O error occurs
     */
    public static byte[] readFileAsBytes(String filename) throws IOException {
        FileInputStream in = null;
        try {
            filename = TextUtils.adjustPath(filename);
            in = new FileInputStream(filename);
            return inputStreamToBytes(in);
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

    /**
     * Loads the full content of a file into a <code>byte</code> array.<br>
     * 
     * @param file
     *        the file to be read
     * @return the full content of the file, stored into a <code>byte</code>
     *         array
     * @throws IOException
     *         if any I/O error occurs
     */
    public static byte[] readFileAsBytes(File file) throws IOException {
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            return inputStreamToBytes(in);
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

    /**
     * Read all data from a source <code>InputStream</code> and stores them into
     * a <code>byte</code> array.<br>
     * It is assumed that the source <code>InputStream</code> will be closed by
     * the caller of this method.
     * 
     * @param in
     *        the <code>InputStream</code> to read from
     * @return the read bytes, stored into a <code>byte</code> array
     * @throws IOException
     *         if any I/O error occurs
     */
    public static byte[] inputStreamToBytes(InputStream in) throws IOException {
        return IOUtils.toByteArray(in);
    }

    /**
     * Read all data from a source <code>InputStream</code> and stores them into
     * a file on the local filesystem.<br>
     * It is assumed that the source <code>InputStream</code> will be closed by
     * the caller of this method.
     * 
     * @param in
     *        the <code>InputStream</code> to read from
     * @param filename
     *        the name of the file to be written to
     * @throws IOException
     *         if any I/O error occurs
     */
    public static void inputStreamToFile(InputStream in, String filename) throws IOException {
        OutputStream fOut = null;
        try {
            filename = TextUtils.adjustPath(filename);
            fOut = new FileOutputStream(filename);
            IOUtils.copyLarge(in, fOut);
        } finally {
            if (fOut != null) {
                fOut.close();
            }
        }
    }

    /**
     * Write the content of a <code>byte</code> array into a new file on the
     * local filesystem.
     * 
     * @param contentArray
     *        the <code>byte</code> array to be written to file
     * @param filename
     *        the name of the file to be written to
     * @throws IOException
     *         if any I/O error occurs
     */
    public static void writeBytesToFile(byte[] contentArray, String filename) throws IOException {
        writeBytesToFile(contentArray, filename, false);
    }

    /**
     * Write the content of a <code>byte</code> array into a file on the local
     * filesystem.
     * 
     * @param contentArray
     *        the <code>byte</code> array to be written to file
     * @param filename
     *        the name of the file to be written to
     * @param append
     *        If true the data are appended to existent file
     * @throws IOException
     *         if any I/O error occurs
     */
    public static void writeBytesToFile(byte[] contentArray, String filename, boolean append) throws IOException {
        BufferedOutputStream bufOut = null;
        try {
            filename = TextUtils.adjustPath(filename);
            bufOut = new BufferedOutputStream(new FileOutputStream(filename, append), 10240);
            IOUtils.write(contentArray, bufOut);
            bufOut.flush();
        } finally {
            if (bufOut != null) {
                bufOut.close();
            }
        }
    }

    /**
     * Write the content of a <code>byte</code> array into a new file on the
     * local filesystem.
     * 
     * @param contentArray
     *        the <code>byte</code> array to be written to file
     * @param file
     *        the file to be written to
     * @throws IOException
     *         if any I/O error occurs
     */
    public static void writeBytesToFile(byte[] contentArray, File file) throws IOException {
        writeBytesToFile(contentArray, file, false);
    }

    /**
     * Write the content of a <code>byte</code> array into a file on the local
     * filesystem.
     * 
     * @param contentArray
     *        the <code>byte</code> array to be written to file
     * @param file
     *        the file to be written to
     * @throws IOException
     *         if any I/O error occurs
     */
    public static void writeBytesToFile(byte[] contentArray, File file, boolean append) throws IOException {
        BufferedOutputStream bufOut = null;
        try {
            bufOut = new BufferedOutputStream(new FileOutputStream(file, append), 10240);
            IOUtils.write(contentArray, bufOut);
            bufOut.flush();
        } finally {
            if (bufOut != null) {
                bufOut.close();
            }
        }
    }

    /**
     * Returns <code>true</code> if the passed <code>byte</code> value is an
     * ASCII printable character, <code>false</code> otherwise.
     * 
     * @param b
     *        the passed <code>byte</code> value
     * @return <code>true</code> if the passed <code>byte</code> value is an
     *         ASCII printable character, <code>false</code> otherwise.
     */
    public static boolean isASCIIPrintableChar(byte b) {
        return ((b >= 0x20) && (b <= 0x7E));
    }

    /**
     * Returns the index of the first occurrence of the given byte sequence
     * within a given byte array starting at the specified index, or -1 if the
     * byte sequence does not occur.
     * 
     * @param input
     *        A given byte array.
     * @param byteSequence
     *        A given byte sequence.
     * @param fromIndex
     *        The index to start the search from.
     * @return the index of the first occurrence of the given byte sequence
     *         within a given byte array starting at the specified index, or -1
     *         if the byte sequence does not occur.
     */
    private static int findByteSequenceWithinByteArray(byte[] input, byte[] byteSequence, int fromIndex) {
        int result = -1;

        if ((input == null) || (byteSequence == null)) {
            return result;
        }
        if ((fromIndex < 0) || (fromIndex > (input.length - 1))) {
            return result;
        }
        if ((input.length - fromIndex) < byteSequence.length) {
            return result;
        }

        byte[] buffer = new byte[byteSequence.length];

        for (int i = fromIndex; i <= (input.length - byteSequence.length); i++) {
            System.arraycopy(input, i, buffer, 0, buffer.length);
            if (Arrays.equals(buffer, byteSequence)) {
                result = i;
                break;
            }
        }
        return result;
    }

    /**
     * Returns the index of the first occurrence of the given byte sequence into
     * a byte array obtained from the given string, or -1 if the byte sequence
     * does not occur.
     * 
     * @param input
     *        A given string.
     * @param byteSequence
     *        A given byte sequence.
     * @return the index of the first occurrence of the given byte sequence into
     *         a byte array obtained from the given string, or -1 if the byte
     *         sequence does not occur.
     * 
     */
    private static int findByteSequenceWithinByteArray(byte[] input, byte[] byteSequence) {
        return findByteSequenceWithinByteArray(input, byteSequence, 0);
    }

    /**
     * The following might seem useless but it's just a trick to have something
     * on which call the getClass().getClassloader().getResource() non-static
     * method calls chain.
     */
    private static BinaryUtils theInstance = null;

    /**
     * Private method to retrieve the one-and-only-private instance of
     * BinaryUtils (which does nothing).
     */
    @SuppressWarnings("unused")
    private static BinaryUtils getPrivateInstance() {
        if (theInstance != null) {
            theInstance = new BinaryUtils();
        }
        return theInstance;
    }

    /**
     * Private constructor
     */
    private BinaryUtils() {
        // do nothing
    }
}