Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Java Coding Problems

You're reading from   Java Coding Problems Become an expert Java programmer by solving over 250 brand-new, modern, real-world problems

Arrow left icon
Product type Paperback
Published in Mar 2024
Publisher Packt
ISBN-13 9781837633944
Length 798 pages
Edition 2nd Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Anghel Leonard Anghel Leonard
Author Profile Icon Anghel Leonard
Anghel Leonard
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Preface 1. Text Blocks, Locales, Numbers, and Math 2. Objects, Immutability, Switch Expressions, and Pattern Matching FREE CHAPTER 3. Working with Date and Time 4. Records and Record Patterns 5. Arrays, Collections, and Data Structures 6. Java I/O: Context-Specific Deserialization Filters 7. Foreign (Function) Memory API 8. Sealed and Hidden Classes 9. Functional Style Programming – Extending APIs 10. Concurrency – Virtual Threads and Structured Concurrency 11. Concurrency ‒ Virtual Threads and Structured Concurrency: Diving Deeper 12. Garbage Collectors and Dynamic CDS Archives 13. Socket API and Simple Web Server 14. Other Books You May Enjoy
15. Index

44. Converting between bytes and hex-encoded strings

Converting bytes to hexadecimal (and vice versa) is a common operation in applications that manipulate fluxes of files/messages, perform encoding/decoding tasks, process images, and so on.

A Java byte is a number in the [-128, +127] range and is represented using 1 signed byte (8 bits). A hexadecimal (base 16) is a system based on 16 digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F). In other words, those 8 bits of a byte value accommodate exactly 2 hexadecimal characters in the range 00 to FF. The decimal <-> binary <-> hexadecimal mapping is resumed in the following figure:

Figure 2.27.png

Figure 2.27: Decimal to binary to hexadecimal conversion

For instance, 122 in binary is 01111010. Since 0111 is in hexadecimal 7, and 1010 is A, this results in 122 being 7A in hexadecimal (also written as 0x7A).

How about a negative byte? We know from the previous chapter that Java represents a negative number as two’s complement of the positive number. This means that -122 in binary is 10000110 (retain the first 7 bits of positive 122 = 1111010, flip(1111010) = 0000101, add(0000001) = 00000110, and append sign bit 1, 10000110) and in hexadecimal, is 0x86.

Converting a negative number to hexadecimal can be done in several ways, but we can easily obtain the lower 4 bits as 10000110 & 0xF = 0110, and the higher four bits as (10000110>> 4) & 0xF = 1000 & 0xF = 1000 (here, the 0xF (binary, 1111) mask is useful only for negative numbers). Since, 0110 = 6 and 1000 = 8, we see that 10000110 is in hexadecimal 0x86.

If you need a deep coverage of bits manipulation in Java or you simply face issues in understanding the current topic, then please consider the book The Complete Coding Interview Guide in Java, especially Chapter 9.

So, in code lines, we can rely on this simple algorithm and Character.forDigit(int d, int r), which returns the character representation for the given digit (d) in the given radix (r):

public static String byteToHexString(byte v) {
  int higher = (v >> 4) & 0xF;
  int lower = v & 0xF;
  String result = String.valueOf(
    new char[]{
      Character.forDigit(higher, 16),
      Character.forDigit(lower, 16)}
    );
  return result;
}

There are many other ways to solve this problem (in the bundled code, you can see another flavor of this solution). For example, if we know that the Integer.toHexString(int n) method returns a string that represents the unsigned integer in base 16 of the given argument, then all we need is to apply the 0xFF (binary, 11111111) mask for negatives as:

public static String byteToHexString(byte v) {
  return Integer.toHexString(v & 0xFF);
}

If there is an approach that we should avoid, then that is the one based on String.format(). The String.format("%02x ", byte_nr) approach is concise but very slow!

How about the reverse process? Converting a given hexadecimal string (for instance, 7d, 09, and so on) to a byte is quite easy. Just take the first (d1) and second (d2) character of the given string and apply the relation, (byte) ((d1 << 4) + d2):

public static byte hexToByte(String s) {
  int d1 = Character.digit(s.charAt(0), 16);
  int d2 = Character.digit(s.charAt(1), 16);
  return (byte) ((d1 << 4) + d2);
} 

More examples are available in the bundled code. If you rely on third-party libraries, then check Apache Commons Codec (Hex.encodeHexString()), Guava (BaseEncoding), Spring Security (Hex.encode()), Bouncy Castle (Hex.toHexString()), and so on.

JDK 17+

Starting with JDK 17, we can use the java.util.HexFormat class. This class has plenty of static methods for handling hexadecimal numbers, including String toHexDigits(byte value) and byte[]parseHex(CharSequence string). So, we can convert a byte to a hexadecimal string as follows:

public static String byteToHexString(byte v) {
  HexFormat hex = HexFormat.of();
  return hex.toHexDigits(v);
}

And, vice versa as follows:

public static byte hexToByte(String s) {
  HexFormat hex = HexFormat.of();
  return hex.parseHex(s)[0];
}

In the bundled code, you can also see the extrapolation of these solutions for converting an array of bytes (byte[]) to a String, and vice versa.

You have been reading a chapter from
Java Coding Problems - Second Edition
Published in: Mar 2024
Publisher: Packt
ISBN-13: 9781837633944
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image