Bael 2189: Convert Byte Array To/From hex String (#5396)
* BAEL-2159: Mini Article on "Separate double into integer and decimal parts" * BAEL-2189: Tutorial to convert Byte Array to/from hex String. * BEAL-2189: Code review comments incorporated. * 1. Added validations for Non-Hex String characters in hex String. 2. Moved classes to algorithms module. 3. Renamed unit test class name ends with *UnitTest. * 1. Added validations for Non-Hex String characters in hex String. 2. Moved classes to algorithms module. 3. Renamed unit test class name ends with *UnitTest. * removed: redundant property added for local testing.
This commit is contained in:
		
							parent
							
								
									15b7eacd43
								
							
						
					
					
						commit
						fe8488a8d5
					
				| @ -17,6 +17,11 @@ | ||||
|             <artifactId>commons-math3</artifactId> | ||||
|             <version>${commons-math3.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>commons-codec</groupId> | ||||
|             <artifactId>commons-codec</artifactId> | ||||
|             <version>${commons-codec.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.projectlombok</groupId> | ||||
|             <artifactId>lombok</artifactId> | ||||
| @ -85,6 +90,7 @@ | ||||
|         <io.jenetics.version>3.7.0</io.jenetics.version> | ||||
|         <org.jgrapht.core.version>1.0.1</org.jgrapht.core.version> | ||||
|         <org.assertj.core.version>3.9.0</org.assertj.core.version> | ||||
|         <commons-codec.version>1.11</commons-codec.version> | ||||
|     </properties> | ||||
| 
 | ||||
| </project> | ||||
| @ -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()); | ||||
|     } | ||||
| } | ||||
| @ -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 }; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user