diff --git a/algorithms/pom.xml b/algorithms/pom.xml
index eda87d6c75..db4a1c2eff 100644
--- a/algorithms/pom.xml
+++ b/algorithms/pom.xml
@@ -17,6 +17,11 @@
commons-math3
${commons-math3.version}
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
org.projectlombok
lombok
@@ -85,6 +90,7 @@
3.7.0
1.0.1
3.9.0
+ 1.11
\ No newline at end of file
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java b/algorithms/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java
new file mode 100644
index 0000000000..d3e251d3fd
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/conversion/HexStringConverter.java
@@ -0,0 +1,110 @@
+package com.baeldung.algorithms.conversion;
+
+import java.math.BigInteger;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+
+import com.google.common.io.BaseEncoding;
+
+public class HexStringConverter {
+
+ /**
+ * Create a byte Array from String of hexadecimal digits using Character conversion
+ * @param hexString - Hexadecimal digits as String
+ * @return Desired byte Array
+ */
+ public byte[] decodeHexString(String hexString) {
+ if (hexString.length() % 2 == 1) {
+ throw new IllegalArgumentException("Invalid hexadecimal String supplied.");
+ }
+ byte[] bytes = new byte[hexString.length() / 2];
+
+ for (int i = 0; i < hexString.length(); i += 2) {
+ bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
+ }
+ return bytes;
+ }
+
+ /**
+ * Create a String of hexadecimal digits from a byte Array using Character conversion
+ * @param byteArray - The byte Array
+ * @return Desired String of hexadecimal digits in lower case
+ */
+ public String encodeHexString(byte[] byteArray) {
+ StringBuffer hexStringBuffer = new StringBuffer();
+ for (int i = 0; i < byteArray.length; i++) {
+ hexStringBuffer.append(byteToHex(byteArray[i]));
+ }
+ return hexStringBuffer.toString();
+ }
+
+ public String byteToHex(byte num) {
+ char[] hexDigits = new char[2];
+ hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
+ hexDigits[1] = Character.forDigit((num & 0xF), 16);
+ return new String(hexDigits);
+ }
+
+ public byte hexToByte(String hexString) {
+ int firstDigit = toDigit(hexString.charAt(0));
+ int secondDigit = toDigit(hexString.charAt(1));
+ return (byte) ((firstDigit << 4) + secondDigit);
+ }
+
+ private int toDigit(char hexChar) {
+ int digit = Character.digit(hexChar, 16);
+ if(digit == -1) {
+ throw new IllegalArgumentException("Invalid Hexadecimal Character: "+ hexChar);
+ }
+ return digit;
+ }
+
+ public String encodeUsingBigIntegerToString(byte[] bytes) {
+ BigInteger bigInteger = new BigInteger(1, bytes);
+ return bigInteger.toString(16);
+ }
+
+ public String encodeUsingBigIntegerStringFormat(byte[] bytes) {
+ BigInteger bigInteger = new BigInteger(1, bytes);
+ return String.format("%0" + (bytes.length << 1) + "x", bigInteger);
+ }
+
+ public byte[] decodeUsingBigInteger(String hexString) {
+ byte[] byteArray = new BigInteger(hexString, 16).toByteArray();
+ if (byteArray[0] == 0) {
+ byte[] output = new byte[byteArray.length - 1];
+ System.arraycopy(byteArray, 1, output, 0, output.length);
+ return output;
+ }
+ return byteArray;
+ }
+
+ public String encodeUsingDataTypeConverter(byte[] bytes) {
+ return DatatypeConverter.printHexBinary(bytes);
+ }
+
+ public byte[] decodeUsingDataTypeConverter(String hexString) {
+ return DatatypeConverter.parseHexBinary(hexString);
+ }
+
+ public String encodeUsingApacheCommons(byte[] bytes) throws DecoderException {
+ return Hex.encodeHexString(bytes);
+ }
+
+ public byte[] decodeUsingApacheCommons(String hexString) throws DecoderException {
+ return Hex.decodeHex(hexString);
+ }
+
+ public String encodeUsingGuava(byte[] bytes) {
+ return BaseEncoding.base16()
+ .encode(bytes);
+ }
+
+ public byte[] decodeUsingGuava(String hexString) {
+ return BaseEncoding.base16()
+ .decode(hexString.toUpperCase());
+ }
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java
new file mode 100644
index 0000000000..be61802705
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/conversion/ByteArrayConverterUnitTest.java
@@ -0,0 +1,127 @@
+package com.baeldung.algorithms.conversion;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import org.apache.commons.codec.DecoderException;
+import org.hamcrest.text.IsEqualIgnoringCase;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baeldung.algorithms.conversion.HexStringConverter;
+
+public class ByteArrayConverterUnitTest {
+
+ private HexStringConverter hexStringConverter;
+
+ @Before
+ public void setup() {
+ hexStringConverter = new HexStringConverter();
+ }
+
+ @Test
+ public void shouldEncodeByteArrayToHexStringUsingBigIntegerToString() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ if(hexString.charAt(0) == '0') {
+ hexString = hexString.substring(1);
+ }
+ String output = hexStringConverter.encodeUsingBigIntegerToString(bytes);
+ assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
+ }
+
+ @Test
+ public void shouldEncodeByteArrayToHexStringUsingBigIntegerStringFormat() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ String output = hexStringConverter.encodeUsingBigIntegerStringFormat(bytes);
+ assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
+ }
+
+ @Test
+ public void shouldDecodeHexStringToByteArrayUsingBigInteger() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ byte[] output = hexStringConverter.decodeUsingBigInteger(hexString);
+ assertArrayEquals(bytes, output);
+ }
+
+ @Test
+ public void shouldEncodeByteArrayToHexStringUsingCharacterConversion() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ String output = hexStringConverter.encodeHexString(bytes);
+ assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
+ }
+
+ @Test
+ public void shouldDecodeHexStringToByteArrayUsingCharacterConversion() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ byte[] output = hexStringConverter.decodeHexString(hexString);
+ assertArrayEquals(bytes, output);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldDecodeHexToByteWithInvalidHexCharacter() {
+ hexStringConverter.hexToByte("fg");
+ }
+
+ @Test
+ public void shouldEncodeByteArrayToHexStringDataTypeConverter() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ String output = hexStringConverter.encodeUsingDataTypeConverter(bytes);
+ assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
+ }
+
+ @Test
+ public void shouldDecodeHexStringToByteArrayUsingDataTypeConverter() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ byte[] output = hexStringConverter.decodeUsingDataTypeConverter(hexString);
+ assertArrayEquals(bytes, output);
+ }
+
+ @Test
+ public void shouldEncodeByteArrayToHexStringUsingGuava() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ String output = hexStringConverter.encodeUsingGuava(bytes);
+ assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
+ }
+
+ @Test
+ public void shouldDecodeHexStringToByteArrayUsingGuava() {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ byte[] output = hexStringConverter.decodeUsingGuava(hexString);
+ assertArrayEquals(bytes, output);
+ }
+
+ @Test
+ public void shouldEncodeByteArrayToHexStringUsingApacheCommons() throws DecoderException {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ String output = hexStringConverter.encodeUsingApacheCommons(bytes);
+ assertThat(output, IsEqualIgnoringCase.equalToIgnoringCase(hexString));
+ }
+
+ @Test
+ public void shouldDecodeHexStringToByteArrayUsingApacheCommons() throws DecoderException {
+ byte[] bytes = getSampleBytes();
+ String hexString = getSampleHexString();
+ byte[] output = hexStringConverter.decodeUsingApacheCommons(hexString);
+ assertArrayEquals(bytes, output);
+ }
+
+ private String getSampleHexString() {
+ return "0af50c0e2d10";
+ }
+
+ private byte[] getSampleBytes() {
+ return new byte[] { 10, -11, 12, 14, 45, 16 };
+ }
+
+}