how to convert c toHex method to java - java

Does anyone know how to convert blow code snippet to java code?
Thanks.
void
rawdata_to_hex (const unsigned char *rawdata, char *hex_str, int n_bytes)
{
static const char hex[] = "0123456789abcdef";
int i;
for (i = 0; i < n_bytes; i++) {
unsigned int val = *rawdata++;
*hex_str++ = hex[val >> 4];
*hex_str++ = hex[val & 0xf];
}
*hex_str = '\0';
}
I am using below code, but looks like it is not correct.
public static String toHex(byte[] buf) {
if (buf == null) return "";
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789abcdef";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
My question is how to covert that? anyone can help?

Using methods below works for me
/**
* Convert byte to Hexadecimal
*
* #param bytes
* #return
*/
private static String toHex(byte[] bytes) throws NoSuchAlgorithmException {
BigInteger bi = new BigInteger(1, bytes);
String hex = bi.toString(16);
int paddingLength = (bytes.length * 2) - hex.length();
if (paddingLength > 0) {
return String.format("%0" + paddingLength + "d", 0) + hex;
} else {
return hex;
}
}
or another way
public static String toHex(byte[] bytes) {
StringBuffer buff = new StringBuffer();
for (byte b : bytes) {
buff.append(String.format("%02X", b));
}
return buff.toString();
}

Related

How to parse string to byte array [duplicate]

I am looking for a way to convert a long string (from a dump), that represents hex values into a byte array.
I couldn't have phrased it better than the person that posted the same question here.
But to keep it original, I'll phrase it my own way: suppose I have a string "00A0BF" that I would like interpreted as the
byte[] {0x00,0xA0,0xBf}
what should I do?
I am a Java novice and ended up using BigInteger and watching out for leading hex zeros. But I think it is ugly and I am sure I am missing something simple.
Update (2021) - Java 17 now includes java.util.HexFormat (only took 25 years):
HexFormat.of().parseHex(s)
For older versions of Java:
Here's a solution that I think is better than any posted so far:
/* s must be an even-length string. */
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Reasons why it is an improvement:
Safe with leading zeros (unlike BigInteger) and with negative byte values (unlike Byte.parseByte)
Doesn't convert the String into a char[], or create StringBuilder and String objects for every single byte.
No library dependencies that may not be available
Feel free to add argument checking via assert or exceptions if the argument is not known to be safe.
One-liners:
import javax.xml.bind.DatatypeConverter;
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
Warnings:
in Java 9 Jigsaw this is no longer part of the (default) java.se root
set so it will result in a ClassNotFoundException unless you specify
--add-modules java.se.ee (thanks to #eckes)
Not available on Android (thanks to Fabian for noting that), but you can just take the source code if your system lacks javax.xml for some reason. Thanks to #Bert Regelink for extracting the source.
The Hex class in commons-codec should do that for you.
http://commons.apache.org/codec/
import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF
You can now use BaseEncoding in guava to accomplish this.
BaseEncoding.base16().decode(string);
To reverse it use
BaseEncoding.base16().encode(bytes);
Actually, I think the BigInteger is solution is very nice:
new BigInteger("00A0BF", 16).toByteArray();
Edit: Not safe for leading zeros, as noted by the poster.
One-liners:
import javax.xml.bind.DatatypeConverter;
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
For those of you interested in the actual code behind the One-liners from FractalizeR (I needed that since javax.xml.bind is not available for Android (by default)), this comes from com.sun.xml.internal.bind.DatatypeConverterImpl.java :
public byte[] parseHexBinary(String s) {
final int len = s.length();
// "111" is not a valid hex encoding.
if( len%2 != 0 )
throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);
byte[] out = new byte[len/2];
for( int i=0; i<len; i+=2 ) {
int h = hexToBin(s.charAt(i ));
int l = hexToBin(s.charAt(i+1));
if( h==-1 || l==-1 )
throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);
out[i/2] = (byte)(h*16+l);
}
return out;
}
private static int hexToBin( char ch ) {
if( '0'<=ch && ch<='9' ) return ch-'0';
if( 'A'<=ch && ch<='F' ) return ch-'A'+10;
if( 'a'<=ch && ch<='f' ) return ch-'a'+10;
return -1;
}
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
public String printHexBinary(byte[] data) {
StringBuilder r = new StringBuilder(data.length*2);
for ( byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}
The HexBinaryAdapter provides the ability to marshal and unmarshal between String and byte[].
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
public byte[] hexToBytes(String hexString) {
HexBinaryAdapter adapter = new HexBinaryAdapter();
byte[] bytes = adapter.unmarshal(hexString);
return bytes;
}
That's just an example I typed in...I actually just use it as is and don't need to make a separate method for using it.
Here is a method that actually works (based on several previous semi-correct answers):
private static byte[] fromHexString(final String encoded) {
if ((encoded.length() % 2) != 0)
throw new IllegalArgumentException("Input string must contain an even number of characters");
final byte result[] = new byte[encoded.length()/2];
final char enc[] = encoded.toCharArray();
for (int i = 0; i < enc.length; i += 2) {
StringBuilder curr = new StringBuilder(2);
curr.append(enc[i]).append(enc[i + 1]);
result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
The only possible issue that I can see is if the input string is extremely long; calling toCharArray() makes a copy of the string's internal array.
EDIT: Oh, and by the way, bytes are signed in Java, so your input string converts to [0, -96, -65] instead of [0, 160, 191]. But you probably knew that already.
In android ,if you are working with hex, you can try okio.
simple usage:
byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();
and result will be
[-64, 0, 6, 0, 0]
The BigInteger() Method from java.math is very Slow and not recommandable.
Integer.parseInt(HEXString, 16)
can cause problems with some characters without
converting to Digit / Integer
a Well Working method:
Integer.decode("0xXX") .byteValue()
Function:
public static byte[] HexStringToByteArray(String s) {
byte data[] = new byte[s.length()/2];
for(int i=0;i < s.length();i+=2) {
data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
}
return data;
}
Have Fun, Good Luck
EDIT: as pointed out by #mmyers, this method doesn't work on input that contains substrings corresponding to bytes with the high bit set ("80" - "FF"). The explanation is at Bug ID: 6259307 Byte.parseByte not working as advertised in the SDK Documentation.
public static final byte[] fromHexString(final String s) {
byte[] arr = new byte[s.length()/2];
for ( int start = 0; start < s.length(); start += 2 )
{
String thisByte = s.substring(start, start+2);
arr[start/2] = Byte.parseByte(thisByte, 16);
}
return arr;
}
For what it's worth, here's another version which supports odd length strings, without resorting to string concatenation.
public static byte[] hexStringToByteArray(String input) {
int len = input.length();
if (len == 0) {
return new byte[] {};
}
byte[] data;
int startIdx;
if (len % 2 != 0) {
data = new byte[(len / 2) + 1];
data[0] = (byte) Character.digit(input.charAt(0), 16);
startIdx = 1;
} else {
data = new byte[len / 2];
startIdx = 0;
}
for (int i = startIdx; i < len; i += 2) {
data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
+ Character.digit(input.charAt(i+1), 16));
}
return data;
}
I like the Character.digit solution, but here is how I solved it
public byte[] hex2ByteArray( String hexString ) {
String hexVal = "0123456789ABCDEF";
byte[] out = new byte[hexString.length() / 2];
int n = hexString.length();
for( int i = 0; i < n; i += 2 ) {
//make a bit representation in an int of the hex value
int hn = hexVal.indexOf( hexString.charAt( i ) );
int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );
//now just shift the high order nibble and add them together
out[i/2] = (byte)( ( hn << 4 ) | ln );
}
return out;
}
I've always used a method like
public static final byte[] fromHexString(final String s) {
String[] v = s.split(" ");
byte[] arr = new byte[v.length];
int i = 0;
for(String val: v) {
arr[i++] = Integer.decode("0x" + val).byteValue();
}
return arr;
}
this method splits on space delimited hex values but it wouldn't be hard to make it split the string on any other criteria such as into groupings of two characters.
The Code presented by Bert Regelink simply does not work.
Try the following:
import javax.xml.bind.DatatypeConverter;
import java.io.*;
public class Test
{
#Test
public void testObjectStreams( ) throws IOException, ClassNotFoundException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
String stringTest = "TEST";
oos.writeObject( stringTest );
oos.close();
baos.close();
byte[] bytes = baos.toByteArray();
String hexString = DatatypeConverter.printHexBinary( bytes);
byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);
assertArrayEquals( bytes, reconvertedBytes );
ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
String readString = (String) ois.readObject();
assertEquals( stringTest, readString);
}
}
I found Kernel Panic to have the solution most useful to me, but ran into problems if the hex string was an odd number. solved it this way:
boolean isOdd(int value)
{
return (value & 0x01) !=0;
}
private int hexToByte(byte[] out, int value)
{
String hexVal = "0123456789ABCDEF";
String hexValL = "0123456789abcdef";
String st = Integer.toHexString(value);
int len = st.length();
if (isOdd(len))
{
len+=1; // need length to be an even number.
st = ("0" + st); // make it an even number of chars
}
out[0]=(byte)(len/2);
for (int i =0;i<len;i+=2)
{
int hh = hexVal.indexOf(st.charAt(i));
if (hh == -1) hh = hexValL.indexOf(st.charAt(i));
int lh = hexVal.indexOf(st.charAt(i+1));
if (lh == -1) lh = hexValL.indexOf(st.charAt(i+1));
out[(i/2)+1] = (byte)((hh << 4)|lh);
}
return (len/2)+1;
}
I am adding a number of hex numbers to an array, so i pass the reference to the array I am using, and the int I need converted and returning the relative position of the next hex number. So the final byte array has [0] number of hex pairs, [1...] hex pairs, then the number of pairs...
Based on the op voted solution, the following should be a bit more efficient:
public static byte [] hexStringToByteArray (final String s) {
if (s == null || (s.length () % 2) == 1)
throw new IllegalArgumentException ();
final char [] chars = s.toCharArray ();
final int len = chars.length;
final byte [] data = new byte [len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
}
return data;
}
Because: the initial conversion to a char array spares the length checks in charAt
If you have a preference for Java 8 streams as your coding style then this can be achieved using just JDK primitives.
String hex = "0001027f80fdfeff";
byte[] converted = IntStream.range(0, hex.length() / 2)
.map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
.collect(ByteArrayOutputStream::new,
ByteArrayOutputStream::write,
(s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
.toByteArray();
The , 0, s2.size() parameters in the collector concatenate function can be omitted if you don't mind catching IOException.
If your needs are more than just the occasional conversion then you can use HexUtils.
Example:
byte[] byteArray = Hex.hexStrToBytes("00A0BF");
This is the most simple case. Your input may contain delimiters (think MAC addresses, certificate thumbprints, etc), your input may be streaming, etc. In such cases it gets easier to justify to pull in an external library like HexUtils, however small.
With JDK 17 the HexFormat class will fulfill most needs and the need for something like HexUtils is greatly diminished. However, HexUtils can still be used for things like converting very large amounts to/from hex (streaming) or pretty printing hex (think wire dumps) which the JDK HexFormat class cannot do.
(full disclosure: I'm the author of HexUtils)
public static byte[] hex2ba(String sHex) throws Hex2baException {
if (1==sHex.length()%2) {
throw(new Hex2baException("Hex string need even number of chars"));
}
byte[] ba = new byte[sHex.length()/2];
for (int i=0;i<sHex.length()/2;i++) {
ba[i] = (Integer.decode(
"0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
}
return ba;
}
My formal solution:
/**
* Decodes a hexadecimally encoded binary string.
* <p>
* Note that this function does <em>NOT</em> convert a hexadecimal number to a
* binary number.
*
* #param hex Hexadecimal representation of data.
* #return The byte[] representation of the given data.
* #throws NumberFormatException If the hexadecimal input string is of odd
* length or invalid hexadecimal string.
*/
public static byte[] hex2bin(String hex) throws NumberFormatException {
if (hex.length() % 2 > 0) {
throw new NumberFormatException("Hexadecimal input string must have an even length.");
}
byte[] r = new byte[hex.length() / 2];
for (int i = hex.length(); i > 0;) {
r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
}
return r;
}
private static int digit(char ch) {
int r = Character.digit(ch, 16);
if (r < 0) {
throw new NumberFormatException("Invalid hexadecimal string: " + ch);
}
return r;
}
Is like the PHP hex2bin() Function but in Java style.
Example:
String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"
Late to the party, but I have amalgamated the answer above by DaveL into a class with the reverse action - just in case it helps.
public final class HexString {
private static final char[] digits = "0123456789ABCDEF".toCharArray();
private HexString() {}
public static final String fromBytes(final byte[] bytes) {
final StringBuilder buf = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
buf.append(HexString.digits[bytes[i] & 0x0f]);
}
return buf.toString();
}
public static final byte[] toByteArray(final String hexString) {
if ((hexString.length() % 2) != 0) {
throw new IllegalArgumentException("Input string must contain an even number of characters");
}
final int len = hexString.length();
final byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return data;
}
}
And JUnit test class:
public class TestHexString {
#Test
public void test() {
String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};
for (int i = 0; i < tests.length; i++) {
String in = tests[i];
byte[] bytes = HexString.toByteArray(in);
String out = HexString.fromBytes(bytes);
System.out.println(in); //DEBUG
System.out.println(out); //DEBUG
Assert.assertEquals(in, out);
}
}
}
I know this is a very old thread, but still like to add my penny worth.
If I really need to code up a simple hex string to binary converter, I'd like to do it as follows.
public static byte[] hexToBinary(String s){
/*
* skipped any input validation code
*/
byte[] data = new byte[s.length()/2];
for( int i=0, j=0;
i<s.length() && j<data.length;
i+=2, j++)
{
data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
}
return data;
}
I think will do it for you. I cobbled it together from a similar function that returned the data as a string:
private static byte[] decode(String encoded) {
byte result[] = new byte[encoded/2];
char enc[] = encoded.toUpperCase().toCharArray();
StringBuffer curr;
for (int i = 0; i < enc.length; i += 2) {
curr = new StringBuffer("");
curr.append(String.valueOf(enc[i]));
curr.append(String.valueOf(enc[i + 1]));
result[i] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
For Me this was the solution, HEX="FF01" then split to FF(255) and 01(01)
private static byte[] BytesEncode(String encoded) {
//System.out.println(encoded.length());
byte result[] = new byte[encoded.length() / 2];
char enc[] = encoded.toUpperCase().toCharArray();
String curr = "";
for (int i = 0; i < encoded.length(); i=i+2) {
curr = encoded.substring(i,i+2);
System.out.println(curr);
if(i==0){
result[i]=((byte) Integer.parseInt(curr, 16));
}else{
result[i/2]=((byte) Integer.parseInt(curr, 16));
}
}
return result;
}

Java - 32 Byte Array to 64 Length String to 32 Byte Array again [duplicate]

I am looking for a way to convert a long string (from a dump), that represents hex values into a byte array.
I couldn't have phrased it better than the person that posted the same question here.
But to keep it original, I'll phrase it my own way: suppose I have a string "00A0BF" that I would like interpreted as the
byte[] {0x00,0xA0,0xBf}
what should I do?
I am a Java novice and ended up using BigInteger and watching out for leading hex zeros. But I think it is ugly and I am sure I am missing something simple.
Update (2021) - Java 17 now includes java.util.HexFormat (only took 25 years):
HexFormat.of().parseHex(s)
For older versions of Java:
Here's a solution that I think is better than any posted so far:
/* s must be an even-length string. */
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Reasons why it is an improvement:
Safe with leading zeros (unlike BigInteger) and with negative byte values (unlike Byte.parseByte)
Doesn't convert the String into a char[], or create StringBuilder and String objects for every single byte.
No library dependencies that may not be available
Feel free to add argument checking via assert or exceptions if the argument is not known to be safe.
One-liners:
import javax.xml.bind.DatatypeConverter;
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
Warnings:
in Java 9 Jigsaw this is no longer part of the (default) java.se root
set so it will result in a ClassNotFoundException unless you specify
--add-modules java.se.ee (thanks to #eckes)
Not available on Android (thanks to Fabian for noting that), but you can just take the source code if your system lacks javax.xml for some reason. Thanks to #Bert Regelink for extracting the source.
The Hex class in commons-codec should do that for you.
http://commons.apache.org/codec/
import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF
You can now use BaseEncoding in guava to accomplish this.
BaseEncoding.base16().decode(string);
To reverse it use
BaseEncoding.base16().encode(bytes);
Actually, I think the BigInteger is solution is very nice:
new BigInteger("00A0BF", 16).toByteArray();
Edit: Not safe for leading zeros, as noted by the poster.
One-liners:
import javax.xml.bind.DatatypeConverter;
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
For those of you interested in the actual code behind the One-liners from FractalizeR (I needed that since javax.xml.bind is not available for Android (by default)), this comes from com.sun.xml.internal.bind.DatatypeConverterImpl.java :
public byte[] parseHexBinary(String s) {
final int len = s.length();
// "111" is not a valid hex encoding.
if( len%2 != 0 )
throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);
byte[] out = new byte[len/2];
for( int i=0; i<len; i+=2 ) {
int h = hexToBin(s.charAt(i ));
int l = hexToBin(s.charAt(i+1));
if( h==-1 || l==-1 )
throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);
out[i/2] = (byte)(h*16+l);
}
return out;
}
private static int hexToBin( char ch ) {
if( '0'<=ch && ch<='9' ) return ch-'0';
if( 'A'<=ch && ch<='F' ) return ch-'A'+10;
if( 'a'<=ch && ch<='f' ) return ch-'a'+10;
return -1;
}
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
public String printHexBinary(byte[] data) {
StringBuilder r = new StringBuilder(data.length*2);
for ( byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}
The HexBinaryAdapter provides the ability to marshal and unmarshal between String and byte[].
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
public byte[] hexToBytes(String hexString) {
HexBinaryAdapter adapter = new HexBinaryAdapter();
byte[] bytes = adapter.unmarshal(hexString);
return bytes;
}
That's just an example I typed in...I actually just use it as is and don't need to make a separate method for using it.
Here is a method that actually works (based on several previous semi-correct answers):
private static byte[] fromHexString(final String encoded) {
if ((encoded.length() % 2) != 0)
throw new IllegalArgumentException("Input string must contain an even number of characters");
final byte result[] = new byte[encoded.length()/2];
final char enc[] = encoded.toCharArray();
for (int i = 0; i < enc.length; i += 2) {
StringBuilder curr = new StringBuilder(2);
curr.append(enc[i]).append(enc[i + 1]);
result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
The only possible issue that I can see is if the input string is extremely long; calling toCharArray() makes a copy of the string's internal array.
EDIT: Oh, and by the way, bytes are signed in Java, so your input string converts to [0, -96, -65] instead of [0, 160, 191]. But you probably knew that already.
In android ,if you are working with hex, you can try okio.
simple usage:
byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();
and result will be
[-64, 0, 6, 0, 0]
The BigInteger() Method from java.math is very Slow and not recommandable.
Integer.parseInt(HEXString, 16)
can cause problems with some characters without
converting to Digit / Integer
a Well Working method:
Integer.decode("0xXX") .byteValue()
Function:
public static byte[] HexStringToByteArray(String s) {
byte data[] = new byte[s.length()/2];
for(int i=0;i < s.length();i+=2) {
data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
}
return data;
}
Have Fun, Good Luck
EDIT: as pointed out by #mmyers, this method doesn't work on input that contains substrings corresponding to bytes with the high bit set ("80" - "FF"). The explanation is at Bug ID: 6259307 Byte.parseByte not working as advertised in the SDK Documentation.
public static final byte[] fromHexString(final String s) {
byte[] arr = new byte[s.length()/2];
for ( int start = 0; start < s.length(); start += 2 )
{
String thisByte = s.substring(start, start+2);
arr[start/2] = Byte.parseByte(thisByte, 16);
}
return arr;
}
For what it's worth, here's another version which supports odd length strings, without resorting to string concatenation.
public static byte[] hexStringToByteArray(String input) {
int len = input.length();
if (len == 0) {
return new byte[] {};
}
byte[] data;
int startIdx;
if (len % 2 != 0) {
data = new byte[(len / 2) + 1];
data[0] = (byte) Character.digit(input.charAt(0), 16);
startIdx = 1;
} else {
data = new byte[len / 2];
startIdx = 0;
}
for (int i = startIdx; i < len; i += 2) {
data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
+ Character.digit(input.charAt(i+1), 16));
}
return data;
}
I like the Character.digit solution, but here is how I solved it
public byte[] hex2ByteArray( String hexString ) {
String hexVal = "0123456789ABCDEF";
byte[] out = new byte[hexString.length() / 2];
int n = hexString.length();
for( int i = 0; i < n; i += 2 ) {
//make a bit representation in an int of the hex value
int hn = hexVal.indexOf( hexString.charAt( i ) );
int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );
//now just shift the high order nibble and add them together
out[i/2] = (byte)( ( hn << 4 ) | ln );
}
return out;
}
I've always used a method like
public static final byte[] fromHexString(final String s) {
String[] v = s.split(" ");
byte[] arr = new byte[v.length];
int i = 0;
for(String val: v) {
arr[i++] = Integer.decode("0x" + val).byteValue();
}
return arr;
}
this method splits on space delimited hex values but it wouldn't be hard to make it split the string on any other criteria such as into groupings of two characters.
The Code presented by Bert Regelink simply does not work.
Try the following:
import javax.xml.bind.DatatypeConverter;
import java.io.*;
public class Test
{
#Test
public void testObjectStreams( ) throws IOException, ClassNotFoundException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
String stringTest = "TEST";
oos.writeObject( stringTest );
oos.close();
baos.close();
byte[] bytes = baos.toByteArray();
String hexString = DatatypeConverter.printHexBinary( bytes);
byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);
assertArrayEquals( bytes, reconvertedBytes );
ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
String readString = (String) ois.readObject();
assertEquals( stringTest, readString);
}
}
I found Kernel Panic to have the solution most useful to me, but ran into problems if the hex string was an odd number. solved it this way:
boolean isOdd(int value)
{
return (value & 0x01) !=0;
}
private int hexToByte(byte[] out, int value)
{
String hexVal = "0123456789ABCDEF";
String hexValL = "0123456789abcdef";
String st = Integer.toHexString(value);
int len = st.length();
if (isOdd(len))
{
len+=1; // need length to be an even number.
st = ("0" + st); // make it an even number of chars
}
out[0]=(byte)(len/2);
for (int i =0;i<len;i+=2)
{
int hh = hexVal.indexOf(st.charAt(i));
if (hh == -1) hh = hexValL.indexOf(st.charAt(i));
int lh = hexVal.indexOf(st.charAt(i+1));
if (lh == -1) lh = hexValL.indexOf(st.charAt(i+1));
out[(i/2)+1] = (byte)((hh << 4)|lh);
}
return (len/2)+1;
}
I am adding a number of hex numbers to an array, so i pass the reference to the array I am using, and the int I need converted and returning the relative position of the next hex number. So the final byte array has [0] number of hex pairs, [1...] hex pairs, then the number of pairs...
Based on the op voted solution, the following should be a bit more efficient:
public static byte [] hexStringToByteArray (final String s) {
if (s == null || (s.length () % 2) == 1)
throw new IllegalArgumentException ();
final char [] chars = s.toCharArray ();
final int len = chars.length;
final byte [] data = new byte [len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
}
return data;
}
Because: the initial conversion to a char array spares the length checks in charAt
If you have a preference for Java 8 streams as your coding style then this can be achieved using just JDK primitives.
String hex = "0001027f80fdfeff";
byte[] converted = IntStream.range(0, hex.length() / 2)
.map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
.collect(ByteArrayOutputStream::new,
ByteArrayOutputStream::write,
(s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
.toByteArray();
The , 0, s2.size() parameters in the collector concatenate function can be omitted if you don't mind catching IOException.
If your needs are more than just the occasional conversion then you can use HexUtils.
Example:
byte[] byteArray = Hex.hexStrToBytes("00A0BF");
This is the most simple case. Your input may contain delimiters (think MAC addresses, certificate thumbprints, etc), your input may be streaming, etc. In such cases it gets easier to justify to pull in an external library like HexUtils, however small.
With JDK 17 the HexFormat class will fulfill most needs and the need for something like HexUtils is greatly diminished. However, HexUtils can still be used for things like converting very large amounts to/from hex (streaming) or pretty printing hex (think wire dumps) which the JDK HexFormat class cannot do.
(full disclosure: I'm the author of HexUtils)
public static byte[] hex2ba(String sHex) throws Hex2baException {
if (1==sHex.length()%2) {
throw(new Hex2baException("Hex string need even number of chars"));
}
byte[] ba = new byte[sHex.length()/2];
for (int i=0;i<sHex.length()/2;i++) {
ba[i] = (Integer.decode(
"0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
}
return ba;
}
My formal solution:
/**
* Decodes a hexadecimally encoded binary string.
* <p>
* Note that this function does <em>NOT</em> convert a hexadecimal number to a
* binary number.
*
* #param hex Hexadecimal representation of data.
* #return The byte[] representation of the given data.
* #throws NumberFormatException If the hexadecimal input string is of odd
* length or invalid hexadecimal string.
*/
public static byte[] hex2bin(String hex) throws NumberFormatException {
if (hex.length() % 2 > 0) {
throw new NumberFormatException("Hexadecimal input string must have an even length.");
}
byte[] r = new byte[hex.length() / 2];
for (int i = hex.length(); i > 0;) {
r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
}
return r;
}
private static int digit(char ch) {
int r = Character.digit(ch, 16);
if (r < 0) {
throw new NumberFormatException("Invalid hexadecimal string: " + ch);
}
return r;
}
Is like the PHP hex2bin() Function but in Java style.
Example:
String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"
Late to the party, but I have amalgamated the answer above by DaveL into a class with the reverse action - just in case it helps.
public final class HexString {
private static final char[] digits = "0123456789ABCDEF".toCharArray();
private HexString() {}
public static final String fromBytes(final byte[] bytes) {
final StringBuilder buf = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
buf.append(HexString.digits[bytes[i] & 0x0f]);
}
return buf.toString();
}
public static final byte[] toByteArray(final String hexString) {
if ((hexString.length() % 2) != 0) {
throw new IllegalArgumentException("Input string must contain an even number of characters");
}
final int len = hexString.length();
final byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return data;
}
}
And JUnit test class:
public class TestHexString {
#Test
public void test() {
String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};
for (int i = 0; i < tests.length; i++) {
String in = tests[i];
byte[] bytes = HexString.toByteArray(in);
String out = HexString.fromBytes(bytes);
System.out.println(in); //DEBUG
System.out.println(out); //DEBUG
Assert.assertEquals(in, out);
}
}
}
I know this is a very old thread, but still like to add my penny worth.
If I really need to code up a simple hex string to binary converter, I'd like to do it as follows.
public static byte[] hexToBinary(String s){
/*
* skipped any input validation code
*/
byte[] data = new byte[s.length()/2];
for( int i=0, j=0;
i<s.length() && j<data.length;
i+=2, j++)
{
data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
}
return data;
}
I think will do it for you. I cobbled it together from a similar function that returned the data as a string:
private static byte[] decode(String encoded) {
byte result[] = new byte[encoded/2];
char enc[] = encoded.toUpperCase().toCharArray();
StringBuffer curr;
for (int i = 0; i < enc.length; i += 2) {
curr = new StringBuffer("");
curr.append(String.valueOf(enc[i]));
curr.append(String.valueOf(enc[i + 1]));
result[i] = (byte) Integer.parseInt(curr.toString(), 16);
}
return result;
}
For Me this was the solution, HEX="FF01" then split to FF(255) and 01(01)
private static byte[] BytesEncode(String encoded) {
//System.out.println(encoded.length());
byte result[] = new byte[encoded.length() / 2];
char enc[] = encoded.toUpperCase().toCharArray();
String curr = "";
for (int i = 0; i < encoded.length(); i=i+2) {
curr = encoded.substring(i,i+2);
System.out.println(curr);
if(i==0){
result[i]=((byte) Integer.parseInt(curr, 16));
}else{
result[i/2]=((byte) Integer.parseInt(curr, 16));
}
}
return result;
}

Java ip2long equivalent

Hello I'm having a database to select the IP location from>
The script was in php and I'm converting it to java but I have no idea what is the equivalent of ip2long('127.0.0.1' )); in java
Basically, this will convert your dotted IP address string to long.
public static Long Dot2LongIP(String dottedIP) {
String[] addrArray = dottedIP.split("\\.");
long num = 0;
for (int i=0;i<addrArray.length;i++) {
int power = 3-i;
num += ((Integer.parseInt(addrArray[i]) % 256) * Math.pow(256,power));
}
return num;
}
public static Long ipToLong(String stringIp) {
return Arrays.stream(stringIp.split("\\."))
.mapToLong(Long::parseLong)
.reduce(0,
(a, b) -> (a << 8) + b);
}
public static String ipToString(Long longIp){
return ((longIp >> 24) & 0xFF) + "." +
((longIp >> 16) & 0xFF) + "." +
((longIp >> 8) & 0xFF) + "." +
(longIp & 0xFF);
}
I don't think there is a standard API to do that in Java, but
1/ The InetAddress class gives you a method to get an array of byte.
2/ If you really need a single integer, you can use this snippet, found on http://www.myteneo.net/blog/-/blogs/java-ip-address-to-integer-and-back/
public static String intToIp(int i) {
return ((i >> 24 ) & 0xFF) + "." +
((i >> 16 ) & 0xFF) + "." +
((i >> 8 ) & 0xFF) + "." +
( i & 0xFF);
}
public static Long ipToInt(String addr) {
String[] addrArray = addr.split("\\.");
long num = 0;
for (int i=0;i<addrArray.length;i++) {
int power = 3-i;
num += ((Integer.parseInt(addrArray[i])%256 * Math.pow(256,power)));
}
return num;
}
I would start by converting the string to octets:
static final String DEC_IPV4_PATTERN = "^(([0-1]?\\d{1,2}\\.)|(2[0-4]\\d\\.)|(25[0-5]\\.)){3}(([0-1]?\\d{1,2})|(2[0-4]\\d)|(25[0-5]))$";
static byte[] toOctets(String address){
if(address==null){
throw new NullPointerException("The IPv4 address cannot be null.");
}
if(!address.matches(DEC_IPV4_PATTERN)){
throw new IllegalArgumentException(String.format("The IPv4 address is invalid:%s ",address));
}
//separate octets into individual strings
String[] numbers = address.split("\\.");
//convert octets to bytes.
byte[] octets = new byte[4];
for(int i = 0; i < octets.length; i++){
octets[i] = Integer.valueOf(numbers[i]).byteValue();
}
return octets;
}
And then the octets to a BigInteger since it accepts a byte array, and from it to an integer:
static int toInteger(byte[] octets){
if(octets==null){
throw new NullPointerException("The array of octets cannot be null");
}
if(octets.length != 4){
throw new IllegalArgumentException(String.format("The byte array must contain 4 octets: %d",octets.length));
}
return new BigInteger(octets).intValue();
}
And from here, you can simply do:
String address = "127.0.0.1";
System.out.println(toInteger(toOctets(address)));
Or create a function named ip2long(String address )
This one works for IPv4 and IPv6:
public static String toLongString(final String ip) {
try {
final InetAddress address = InetAddress.getByName(ip);
final byte[] bytes = address.getAddress();
final byte[] uBytes = new byte[bytes.length + 1]; // add one byte at the top to make it unsigned
System.arraycopy(bytes, 0, uBytes, 1, bytes.length);
return new BigInteger(uBytes).toString();
} catch (final UnknownHostException e) {
throw new IllegalArgumentException(e);
}
}
I hope below link will help you, clearly provided vice versa too
https://www.mkyong.com/java/java-convert-ip-address-to-decimal-number.
Provided methods from above link:
public static long ipToLong(String ipAddress) {
String[] ipAddressInArray = ipAddress.split("\\.");
long result = 0;
for (int i = 0; i < ipAddressInArray.length; i++) {
int power = 3 - i;
int ip = Integer.parseInt(ipAddressInArray[i]);
result += ip * Math.pow(256, power);
}
return result;
}
public static String longToIp(long ip) {
StringBuilder result = new StringBuilder(15);
for (int i = 0; i < 4; i++) {
result.insert(0,Long.toString(ip & 0xff));
if (i < 3) {
result.insert(0,'.');
}
ip = ip >> 8;
}
return result.toString();
}

Convert hex string to binary string

I would like to convert a hex string to a binary string. For example, Hex 2 is 0010. Below is the code:
String HexToBinary(String Hex)
{
int i = Integer.parseInt(Hex);
String Bin = Integer.toBinaryString(i);
return Bin;
}
However this only works for Hex 0 - 9; it won't work for Hex A - F because it uses int. Can anyone enhance it?
You need to tell Java that the int is in hex, like this:
String hexToBinary(String hex) {
int i = Integer.parseInt(hex, 16);
String bin = Integer.toBinaryString(i);
return bin;
}
the accepted version will only work for 32 bit numbers.
Here's a version that works for arbitrarily long hex strings:
public static String hexToBinary(String hex) {
return new BigInteger(hex, 16).toString(2);
}
Here are some routines I wrote for manipulating hex, plaintext, and binary, hope they help. Since I borrowed ideas from these threads, thought I would share.
public static String zero_pad_bin_char(String bin_char){
int len = bin_char.length();
if(len == 8) return bin_char;
String zero_pad = "0";
for(int i=1;i<8-len;i++) zero_pad = zero_pad + "0";
return zero_pad + bin_char;
}
public static String plaintext_to_binary(String pt){
return hex_to_binary(plaintext_to_hex(pt));
}
public static String binary_to_plaintext(String bin){
return hex_to_plaintext(binary_to_hex(bin));
}
public static String plaintext_to_hex(String pt) {
String hex = "";
for(int i=0;i<pt.length();i++){
String hex_char = Integer.toHexString(pt.charAt(i));
if(i==0) hex = hex_char;
else hex = hex + hex_char;
}
return hex;
}
public static String binary_to_hex(String binary) {
String hex = "";
String hex_char;
int len = binary.length()/8;
for(int i=0;i<len;i++){
String bin_char = binary.substring(8*i,8*i+8);
int conv_int = Integer.parseInt(bin_char,2);
hex_char = Integer.toHexString(conv_int);
if(i==0) hex = hex_char;
else hex = hex+hex_char;
}
return hex;
}
public static String hex_to_binary(String hex) {
String hex_char,bin_char,binary;
binary = "";
int len = hex.length()/2;
for(int i=0;i<len;i++){
hex_char = hex.substring(2*i,2*i+2);
int conv_int = Integer.parseInt(hex_char,16);
bin_char = Integer.toBinaryString(conv_int);
bin_char = zero_pad_bin_char(bin_char);
if(i==0) binary = bin_char;
else binary = binary+bin_char;
//out.printf("%s %s\n", hex_char,bin_char);
}
return binary;
}
public static String hex_to_plaintext(String hex) {
String hex_char;
StringBuilder plaintext = new StringBuilder();
char pt_char;
int len = hex.length()/2;
for(int i=0;i<len;i++){
hex_char = hex.substring(2*i,2*i+2);
pt_char = (char)Integer.parseInt(hex_char,16);
plaintext.append(pt_char);
//out.printf("%s %s\n", hex_char,bin_char);
}
return plaintext.toString();
}
}
You need to use the other Integer.parseInt() method.
Integer.parseInt(hex, 16);
The accepted answer only works for 32-bit values, and the alternate BigInteger version truncates leading zeros in the binary string! Here's a function that should work in all cases.
public static String hexToBinary(String hex) {
int len = hex.length() * 4;
String bin = new BigInteger(hex, 16).toString(2);
//left pad the string result with 0s if converting to BigInteger removes them.
if(bin.length() < len){
int diff = len - bin.length();
String pad = "";
for(int i = 0; i < diff; ++i){
pad = pad.concat("0");
}
bin = pad.concat(bin);
}
return bin;
}
private static Map<String, String> digiMap = new HashMap<>();
static {
digiMap.put("0", "0000");
digiMap.put("1", "0001");
digiMap.put("2", "0010");
digiMap.put("3", "0011");
digiMap.put("4", "0100");
digiMap.put("5", "0101");
digiMap.put("6", "0110");
digiMap.put("7", "0111");
digiMap.put("8", "1000");
digiMap.put("9", "1001");
digiMap.put("A", "1010");
digiMap.put("B", "1011");
digiMap.put("C", "1100");
digiMap.put("D", "1101");
digiMap.put("E", "1110");
digiMap.put("F", "1111");
}
static String hexToBin(String s) {
char[] hex = s.toCharArray();
String binaryString = "";
for (char h : hex) {
binaryString = binaryString + digiMap.get(String.valueOf(h));
}
return binaryString;
}
Sorry, it's been a little bit late. But still, I think my answer is the most straight forward and simple one.

Is there a simpler way to convert a byte array to a 2-byte-size hexadecimal string?

Is there a simpler way of implement this? Or a implemented method in JDK or other lib?
/**
* Convert a byte array to 2-byte-size hexadecimal String.
*/
public static String to2DigitsHex(byte[] bytes) {
String hexData = "";
for (int i = 0; i < bytes.length; i++) {
int intV = bytes[i] & 0xFF; // positive int
String hexV = Integer.toHexString(intV);
if (hexV.length() < 2) {
hexV = "0" + hexV;
}
hexData += hexV;
}
return hexData;
}
public static void main(String[] args) {
System.out.println(to2DigitsHex(new byte[] {8, 10, 12}));
}
the output is: "08 0A 0C" (without the spaces)
Use at least StringBuilder#append() instead of stringA += stringB to improve performance and save memory.
public static String binaryToHexString(byte[] bytes) {
StringBuilder hex = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
int i = (b & 0xFF);
if (i < 0x10) hex.append('0');
hex.append(Integer.toHexString(i));
}
return hex.toString();
}
Apache Commons-Codec has the Hex class, which will do what you need:
String hexString = Hex.encodeHexString(bytes);
By far the easiest method. Don't mess with binary operators, use the libraries to do the dirty work =)
public static String to2DigitsHex(final byte[] bytes) {
final StringBuilder accum = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
b &= 0xff;
if (b < 16) accum.append("0");
accum.append(Integer.toHexString(b);
}
return accum.toString();
}
You're better off using an explicit StringBuilder of your own if this routine is going to be called a lot.
private static String to2DigitsHex(byte[] bs) {
String s = new BigInteger(bs).toString(16);
return s.length()%2==0? s : "0"+s;
}
You could use BigInteger for this.
Example:
(new BigInteger(1,bytes)).toString(16)
You will need to add an '0' at the beginning.
A more elegant solution (taken from here) is:
BigInteger i = new BigInteger(1,bytes);
System.out.println(String.format("%1$06X", i));
You need to know the number of bytes in advance in order to use the correct formatter.
I'm not taking any credit for this implementation as I saw it as part of a similar discussion and thought it was an elegant solution:
private static final String HEXES = "0123456789ABCDEF";
public String toHexString(byte[] bytes) {
final StringBuilder hex = new StringBuilder(2 * bytes.length);
for (final byte b : _bytes) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}

Categories

Resources