杰瑞科技汇

Java字符串如何转十六进制?

Of course! Working with hexadecimal (hex) representations of strings is a common task in Java. This involves two main operations:

  1. Encoding: Converting a standard String into a hex representation.
  2. Decoding: Converting a hex representation back into a String.

Here’s a comprehensive guide covering the most common and effective methods in modern Java.


Encoding a String to Hex

The core idea is to get the bytes of the string and then convert each byte into its two-digit hex representation.

Method 1: Using String.format() (Simple & No Libraries)

This is a straightforward, built-in approach. You loop through the bytes of the string and format each one as a two-digit hex number.

public class StringToHex {
    public static String stringToHex(String str) {
        // Get the bytes of the string using a specific charset (UTF-8 is recommended)
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            // Format each byte as a two-digit hex number, padded with a leading zero if needed
            hexString.append(String.format("%02x", b));
        }
        return hexString.toString();
    }
    public static void main(String[] args) {
        String originalString = "Hello, World!";
        String hexRepresentation = stringToHex(originalString);
        System.out.println("Original String: " + originalString);
        System.out.println("Hex Representation: " + hexRepresentation);
        // Output: Hex Representation: 48656c6c6f2c20576f726c6421
    }
}

Explanation:

  • str.getBytes(StandardCharsets.UTF_8): This is crucial. It converts the String into a sequence of bytes using the UTF-8 encoding. This ensures consistent results across different systems.
  • String.format("%02x", b): This is the key part.
    • %x: Formats the integer b as a hexadecimal string.
    • 02: Pads the result with a leading zero if it's only one digit long, ensuring every byte is represented by exactly two hex characters.

Method 2: Using Apache Commons Codec (Recommended for Production)

The Apache Commons Codec library provides a dedicated, highly optimized utility for this: Hex.encodeHexString(). This is the preferred method in most production environments as it's clean, fast, and well-tested.

First, add the dependency to your project:

Maven (pom.xml):

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version> <!-- Use the latest version -->
</dependency>

Gradle (build.gradle):

implementation 'commons-codec:commons-codec:1.15' // Use the latest version

Java Code:

import org.apache.commons.codec.binary.Hex;
public class StringToHexApache {
    public static String stringToHex(String str) {
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        // The encodeHexString method does all the work for you
        return Hex.encodeHexString(bytes);
    }
    public static void main(String[] args) {
        String originalString = "Hello, World!";
        String hexRepresentation = stringToHex(originalString);
        System.out.println("Original String: " + originalString);
        System.out.println("Hex Representation: " + hexRepresentation);
        // Output: Hex Representation: 48656c6c6f2c20576f726c6421
    }
}

Decoding Hex to a String

This is the reverse operation. You take a hex string and convert it back into the original String.

Method 1: Using BigInteger (Simple & No Libraries)

You can parse the hex string as a very large integer and then convert it into a byte array.

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
public class HexToString {
    public static String hexToString(String hex) {
        // Create a BigInteger from the hex string. The "16" specifies the radix (base).
        BigInteger bigInteger = new BigInteger(hex, 16);
        // Convert the BigInteger to a byte array. This correctly handles leading zeros.
        byte[] byteArray = bigInteger.toByteArray();
        // Create a String from the byte array using the same charset
        return new String(byteArray, StandardCharsets.UTF_8);
    }
    public static void main(String[] args) {
        String hexRepresentation = "48656c6c6f2c20576f726c6421";
        String originalString = hexToString(hexRepresentation);
        System.out.println("Hex Representation: " + hexRepresentation);
        System.out.println("Decoded String: " + originalString);
        // Output: Decoded String: Hello, World!
    }
}

Caveat: This method can sometimes add an extra leading zero byte to the array. For most common strings, this isn't a problem, but for very specific byte-level manipulations, it can be an edge case.


Method 2: Using Apache Commons Codec (Recommended for Production)

Just like with encoding, the Hex class provides a simple and reliable method: Hex.decodeHex().

import org.apache.commons.codec.binary.Hex;
public class HexToStringApache {
    public static String hexToString(String hex) throws Exception {
        // Decode the hex string into a byte array
        byte[] byteArray = Hex.decodeHex(hex);
        // Create a String from the byte array
        return new String(byteArray, StandardCharsets.UTF_8);
    }
    public static void main(String[] args) throws Exception {
        String hexRepresentation = "48656c6c6f2c20576f726c6421";
        String originalString = hexToString(hexRepresentation);
        System.out.println("Hex Representation: " + hexRepresentation);
        System.out.println("Decoded String: " + originalString);
        // Output: Decoded String: Hello, World!
    }
}

Important Considerations

  1. Character Encoding is Critical The most common source of errors is not specifying a character set. If you use str.getBytes() without a charset, it uses the platform's default encoding, which can vary (e.g., Windows-1252 on Windows, UTF-8 on Linux). This can lead to different hex outputs on different machines and garbled text when decoding.

    Always be explicit:

    // Good
    byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
    // Bad (platform-dependent)
    byte[] bytes = str.getBytes();
  2. Case Sensitivity Hexadecimal digits can be uppercase (A-F) or lowercase (a-f). The methods shown above (String.format and Apache Commons) produce lowercase hex by default. If you need uppercase, you can easily convert the result:

    String hex = stringToHex("Test");
    System.out.println(hex); // t657374
    System.out.println(hex.toUpperCase()); // T657374
  3. Handling Invalid Hex Strings When decoding, you must handle cases where the input string is not a valid hex string (e.g., contains 'G', 'Z', or has an odd length). The Hex.decodeHex() method from Apache Commons throws a DecoderException in these cases, which you should catch. The BigInteger approach will throw a NumberFormatException.

Summary: Which Method to Choose?

Scenario Recommended Method Why?
Quick Script / Simple Project String.format() or BigInteger No external dependencies needed. Good for learning the basics.
Production Application / Library Apache Commons Codec Best Practice. It's fast, reliable, well-tested, and the code is cleaner and more readable. It correctly handles edge cases.
Java 17+ Project DatatypeConverter (see below) If you're already using JAXB, this is a convenient built-in option. Otherwise, adding Commons Codec is still often preferred.

Bonus: Using javax.xml.bind.DatatypeConverter (Java 8 and below)

In older Java versions (before 9), javax.xml.bind.DatatypeConverter was a standard library utility for this. It's still available in Java 8 and can be used without external dependencies.

Note: This class is in the java.xml.bind module, which is no longer included in the Java SE module path by default in Java 9+. You would need to add it manually with --add-modules java.xml.bind.

import javax.xml.bind.DatatypeConverter;
public class HexConverterLegacy {
    public static String stringToHex(String str) {
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        return DatatypeConverter.printHexBinary(bytes);
    }
    public static String hexToString(String hex) {
        byte[] bytes = DatatypeConverter.parseHexBinary(hex);
        return new String(bytes, StandardCharsets.UTF_8);
    }
    public static void main(String[] args) {
        String original = "Test legacy";
        String hex = stringToHex(original);
        String decoded = hexToString(hex);
        System.out.println("Original: " + original);
        System.out.println("Hex: " + hex); // Outputs in uppercase: 54657374206c6567616379
        System.out.println("Decoded: " + decoded);
    }
}
分享:
扫描分享到社交APP
上一篇
下一篇