You can use Convert.ToHexString starting with .NET 5.
There's also a method for the reverse operation: Convert.FromHexString.


For older versions of .NET you can either use:

public static string ByteArrayToString(byte[] ba)
{
  StringBuilder hex = new StringBuilder(ba.Length * 2);
  foreach (byte b in ba)
    hex.AppendFormat("{0:x2}", b);
  return hex.ToString();
}

or:

public static string ByteArrayToString(byte[] ba)
{
  return BitConverter.ToString(ba).Replace("-","");
}

There are even more variants of doing it, for example here.

The reverse conversion would go like this:

public static byte[] StringToByteArray(String hex)
{
  int NumberChars = hex.Length;
  byte[] bytes = new byte[NumberChars / 2];
  for (int i = 0; i < NumberChars; i += 2)
    bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
  return bytes;
}

Using Substring is the best option in combination with Convert.ToByte. See this answer for more information. If you need better performance, you must avoid Convert.ToByte before you can drop SubString.

๐ŸŒ
Online String Tools
onlinestringtools.com โ€บ convert-bytes-to-string
Convert Bytes to a String โ€“ Online String Tools
This browser-based program converts bytes to a string. The input bytes can be entered as a space-separated array or as a long hex number. The conversion algorithm then takes these bytes and constructs a string from them.
๐ŸŒ
LDDGO
lddgo.net โ€บ en โ€บ string โ€บ hex
String Hex Converter
Each byte in the byte array is encoded into two hexadecimal characters to obtain the hex string result.
๐ŸŒ
Baeldung
baeldung.com โ€บ home โ€บ java โ€บ java array โ€บ converting between byte arrays and hexadecimal strings in java
Converting Between Byte Arrays and Hexadecimal Strings in Java | Baeldung
March 26, 2025 - At this point, we know how to convert a byte to the hexadecimal, and vice versa. Letโ€™s scale this algorithm and convert byte array to/from hexadecimal String.
๐ŸŒ
SCADACore
scadacore.com โ€บ home โ€บ tools โ€บ programming calculators โ€บ online hex converter
Online Hex Converter - Bytes, Ints, Floats, Significance, Endians - SCADACore
April 8, 2021 - We also perform to 16 bit conversions, ... and Hex-To-INT16 (16 bit Signed Integer) When interfacing with new hardware, it is sometimes difficult to determine the number format of a string of raw binary data. For industrial programmers and field technicians, looking at the communication data in byte format would show an array of bytes that ...
Top answer
1 of 16
1751

You can use Convert.ToHexString starting with .NET 5.
There's also a method for the reverse operation: Convert.FromHexString.


For older versions of .NET you can either use:

public static string ByteArrayToString(byte[] ba)
{
  StringBuilder hex = new StringBuilder(ba.Length * 2);
  foreach (byte b in ba)
    hex.AppendFormat("{0:x2}", b);
  return hex.ToString();
}

or:

public static string ByteArrayToString(byte[] ba)
{
  return BitConverter.ToString(ba).Replace("-","");
}

There are even more variants of doing it, for example here.

The reverse conversion would go like this:

public static byte[] StringToByteArray(String hex)
{
  int NumberChars = hex.Length;
  byte[] bytes = new byte[NumberChars / 2];
  for (int i = 0; i < NumberChars; i += 2)
    bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
  return bytes;
}

Using Substring is the best option in combination with Convert.ToByte. See this answer for more information. If you need better performance, you must avoid Convert.ToByte before you can drop SubString.

2 of 16
560

Performance Analysis

Note: new leader as of 2015-08-20.

I ran each of the various conversion methods through some crude Stopwatch performance testing, a run with a random sentence (n=61, 1000 iterations) and a run with a Project Gutenburg text (n=1,238,957, 150 iterations). Here are the results, roughly from fastest to slowest. All measurements are in ticks (10,000 ticks = 1 ms) and all relative notes are compared to the [slowest] StringBuilder implementation. For the code used, see below or the test framework repo where I now maintain the code for running this.

Disclaimer

WARNING: Do not rely on these stats for anything concrete; they are simply a sample run of sample data. If you really need top-notch performance, please test these methods in an environment representative of your production needs with data representative of what you will use.

Results

  • Lookup by byte unsafe (via CodesInChaos) (added to test repo by airbreather)
    • Text: 4,727.85 (105.2X)
    • Sentence: 0.28 (99.7X)
  • Lookup by byte (via CodesInChaos)
    • Text: 10,853.96 (45.8X faster)
    • Sentence: 0.65 (42.7X faster)
  • Byte Manipulation 2 (via CodesInChaos)
    • Text: 12,967.69 (38.4X faster)
    • Sentence: 0.73 (37.9X faster)
  • Byte Manipulation (via Waleed Eissa)
    • Text: 16,856.64 (29.5X faster)
    • Sentence: 0.70 (39.5X faster)
  • Lookup/Shift (via Nathan Moinvaziri)
    • Text: 23,201.23 (21.4X faster)
    • Sentence: 1.24 (22.3X faster)
  • Lookup by nibble (via Brian Lambert)
    • Text: 23,879.41 (20.8X faster)
    • Sentence: 1.15 (23.9X faster)
  • BitConverter (via Tomalak)
    • Text: 113,269.34 (4.4X faster)
    • Sentence: 9.98 (2.8X faster)
  • {SoapHexBinary}.ToString (via Mykroft)
    • Text: 178,601.39 (2.8X faster)
    • Sentence: 10.68 (2.6X faster)
  • {byte}.ToString("X2") (using foreach) (derived from Will Dean's answer)
    • Text: 308,805.38 (2.4X faster)
    • Sentence: 16.89 (2.4X faster)
  • {byte}.ToString("X2") (using {IEnumerable}.Aggregate, requires System.Linq) (via Mark)
    • Text: 352,828.20 (2.1X faster)
    • Sentence: 16.87 (2.4X faster)
  • Array.ConvertAll (using string.Join) (via Will Dean)
    • Text: 675,451.57 (1.1X faster)
    • Sentence: 17.95 (2.2X faster)
  • Array.ConvertAll (using string.Concat, requires .NET 4.0) (via Will Dean)
    • Text: 752,078.70 (1.0X faster)
    • Sentence: 18.28 (2.2X faster)
  • {StringBuilder}.AppendFormat (using foreach) (via Tomalak)
    • Text: 672,115.77 (1.1X faster)
    • Sentence: 36.82 (1.1X faster)
  • {StringBuilder}.AppendFormat (using {IEnumerable}.Aggregate, requires System.Linq) (derived from Tomalak's answer)
    • Text: 718,380.63 (1.0X faster)
    • Sentence: 39.71 (1.0X faster)

Lookup tables have taken the lead over byte manipulation. Basically, there is some form of precomputing what any given nibble or byte will be in hex. Then, as you rip through the data, you simply look up the next portion to see what hex string it would be. That value is then added to the resulting string output in some fashion. For a long time byte manipulation, potentially harder to read by some developers, was the top-performing approach.

Your best bet is still going to be finding some representative data and trying it out in a production-like environment. If you have different memory constraints, you may prefer a method with fewer allocations to one that would be faster but consume more memory.

Testing Code

Feel free to play with the testing code I used. A version is included here but feel free to clone the repo and add your own methods. Please submit a pull request if you find anything interesting or want to help improve the testing framework it uses.

  1. Add the new static method (Func<byte[], string>) to /Tests/ConvertByteArrayToHexString/Test.cs.
  2. Add that method's name to the TestCandidates return value in that same class.
  3. Make sure you are running the input version you want, sentence or text, by toggling the comments in GenerateTestInput in that same class.
  4. Hit F5 and wait for the output (an HTML dump is also generated in the /bin folder).
static string ByteArrayToHexStringViaStringJoinArrayConvertAll(byte[] bytes) {
    return string.Join(string.Empty, Array.ConvertAll(bytes, b => b.ToString("X2")));
}
static string ByteArrayToHexStringViaStringConcatArrayConvertAll(byte[] bytes) {
    return string.Concat(Array.ConvertAll(bytes, b => b.ToString("X2")));
}
static string ByteArrayToHexStringViaBitConverter(byte[] bytes) {
    string hex = BitConverter.ToString(bytes);
    return hex.Replace("-", "");
}
static string ByteArrayToHexStringViaStringBuilderAggregateByteToString(byte[] bytes) {
    return bytes.Aggregate(new StringBuilder(bytes.Length * 2), (sb, b) => sb.Append(b.ToString("X2"))).ToString();
}
static string ByteArrayToHexStringViaStringBuilderForEachByteToString(byte[] bytes) {
    StringBuilder hex = new StringBuilder(bytes.Length * 2);
    foreach (byte b in bytes)
        hex.Append(b.ToString("X2"));
    return hex.ToString();
}
static string ByteArrayToHexStringViaStringBuilderAggregateAppendFormat(byte[] bytes) {
    return bytes.Aggregate(new StringBuilder(bytes.Length * 2), (sb, b) => sb.AppendFormat("{0:X2}", b)).ToString();
}
static string ByteArrayToHexStringViaStringBuilderForEachAppendFormat(byte[] bytes) {
    StringBuilder hex = new StringBuilder(bytes.Length * 2);
    foreach (byte b in bytes)
        hex.AppendFormat("{0:X2}", b);
    return hex.ToString();
}
static string ByteArrayToHexViaByteManipulation(byte[] bytes) {
    char[] c = new char[bytes.Length * 2];
    byte b;
    for (int i = 0; i < bytes.Length; i++) {
        b = ((byte)(bytes[i] >> 4));
        c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
        b = ((byte)(bytes[i] & 0xF));
        c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
    }
    return new string(c);
}
static string ByteArrayToHexViaByteManipulation2(byte[] bytes) {
    char[] c = new char[bytes.Length * 2];
    int b;
    for (int i = 0; i < bytes.Length; i++) {
        b = bytes[i] >> 4;
        c[i * 2] = (char)(55 + b + (((b - 10) >> 31) & -7));
        b = bytes[i] & 0xF;
        c[i * 2 + 1] = (char)(55 + b + (((b - 10) >> 31) & -7));
    }
    return new string(c);
}
static string ByteArrayToHexViaSoapHexBinary(byte[] bytes) {
    SoapHexBinary soapHexBinary = new SoapHexBinary(bytes);
    return soapHexBinary.ToString();
}
static string ByteArrayToHexViaLookupAndShift(byte[] bytes) {
    StringBuilder result = new StringBuilder(bytes.Length * 2);
    string hexAlphabet = "0123456789ABCDEF";
    foreach (byte b in bytes) {
        result.Append(hexAlphabet[(int)(b >> 4)]);
        result.Append(hexAlphabet[(int)(b & 0xF)]);
    }
    return result.ToString();
}
static readonly uint* _lookup32UnsafeP = (uint*)GCHandle.Alloc(_Lookup32, GCHandleType.Pinned).AddrOfPinnedObject();
static string ByteArrayToHexViaLookup32UnsafeDirect(byte[] bytes) {
    var lookupP = _lookup32UnsafeP;
    var result = new string((char)0, bytes.Length * 2);
    fixed (byte* bytesP = bytes)
    fixed (char* resultP = result) {
        uint* resultP2 = (uint*)resultP;
        for (int i = 0; i < bytes.Length; i++) {
            resultP2[i] = lookupP[bytesP[i]];
        }
    }
    return result;
}
static uint[] _Lookup32 = Enumerable.Range(0, 255).Select(i => {
    string s = i.ToString("X2");
    return ((uint)s[0]) + ((uint)s[1] << 16);
}).ToArray();
static string ByteArrayToHexViaLookupPerByte(byte[] bytes) {
    var result = new char[bytes.Length * 2];
    for (int i = 0; i < bytes.Length; i++)
    {
        var val = _Lookup32[bytes[i]];
        result[2*i] = (char)val;
        result[2*i + 1] = (char) (val >> 16);
    }
    return new string(result);
}
static string ByteArrayToHexViaLookup(byte[] bytes) {
    string[] hexStringTable = new string[] {
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
        "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
        "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
        "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
        "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
        "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
        "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
        "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
        "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
        "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
        "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
        "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
        "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
        "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
        "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF",
    };
    StringBuilder result = new StringBuilder(bytes.Length * 2);
    foreach (byte b in bytes) {
        result.Append(hexStringTable[b]);
    }
    return result.ToString();
}

Update (2010-01-13)

Added Waleed's answer to analysis. Quite fast.

Update (2011-10-05)

Added string.Concat Array.ConvertAll variant for completeness (requires .NET 4.0). On par with string.Join version.

Update (2012-02-05)

Test repo includes more variants such as StringBuilder.Append(b.ToString("X2")). None upset the results any. foreach is faster than {IEnumerable}.Aggregate, for instance, but BitConverter still wins.

Update (2012-04-03)

Added Mykroft's SoapHexBinary answer to analysis, which took over third place.

Update (2013-01-15)

Added CodesInChaos's byte manipulation answer, which took over first place (by a large margin on large blocks of text).

Update (2013-05-23)

Added Nathan Moinvaziri's lookup answer and the variant from Briโ€ฆ

๐ŸŒ
Quora
quora.com โ€บ How-do-you-convert-a-byte-array-to-a-hexadecimal-string
How to convert a byte array to a hexadecimal string - Quora
Answer (1 of 14): In the Plain English programming language, a string is essentially an array of bytes, and a nibble string is a string where each character represents four of the bits of an eight-bit byte in hexadecimal. So in Plain English we do it like this: To run: Start up. Put "Hello, worl...
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ java โ€บ java-program-to-convert-byte-array-to-hex-string
Java Program to Convert Byte Array to Hex String - GeeksforGeeks
July 23, 2025 - Eg: "245FC" is a hexadecimal string. Problem Statement - Given a byte array, the task is to convert the Byte Array to Hex String.
Top answer
1 of 16
1080

From the discussion here, and especially this answer, this is the function I currently use:

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}

My own tiny benchmarks (a million bytes a thousand times, 256 bytes 10 million times) showed it to be much faster than any other alternative, about half the time on long arrays. Compared to the answer I took it from, switching to bitwise ops --- as suggested in the discussion --- cut about 20% off of the time for long arrays. (Edit: When I say it's faster than the alternatives, I mean the alternative code offered in the discussions. Performance is equivalent to Commons Codec, which uses very similar code.)

2k20 version, with respect to Java 9 compact strings:

private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
public static String bytesToHex(byte[] bytes) {
    byte[] hexChars = new byte[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars, StandardCharsets.UTF_8);
}
2 of 16
545

The Apache Commons Codec library has a Hex class for doing just this type of work.

import org.apache.commons.codec.binary.Hex;

String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );
Find elsewhere
๐ŸŒ
Mkyong
mkyong.com โ€บ home โ€บ java โ€บ java โ€“ how to convert byte arrays to hex
Java โ€“ How to convert byte arrays to Hex | mkyong.com
June 5, 2020 - Note Both Apache Commons-Codec and Spring Security Crypto modules are using the similar 5. Bitwise shifting and masking techniques to convert byte arrays to a hex string, please study the source code below, it is useful for educational purposes.
๐ŸŒ
NI Community
forums.ni.com โ€บ community โ€บ discussion forums โ€บ most active software boards โ€บ labview โ€บ convert byte to hex string
Convert byte to hex string - NI Community - National Instruments
June 26, 2009 - The LabVIEW server should send IEEE 754 64-bit floating point measures (in binary) to the client, which decodes those received bytes as floating point numbers. I'm new to both LabView and Socket programming, but from what I understood, when it comes to TCP IP communications: LabVIEW only sends data in a string form. Since sending binary arrays is not allowed, I thought transforming those 64 bit arrays into hexadecimal strings and sending them over the TCP IP connection should do the job.
Top answer
1 of 6
177

Using str.format:

>>> array_alpha = [ 133, 53, 234, 241 ]
>>> print ''.join('{:02x}'.format(x) for x in array_alpha)
8535eaf1

or using format

>>> print ''.join(format(x, '02x') for x in array_alpha)
8535eaf1

Note: In the format statements, the 02 means it will pad with up to 2 leading 0s if necessary. This is important since [0x1, 0x1, 0x1] i.e. (0x010101) would be formatted to "111" instead of "010101"

or using bytearray with binascii.hexlify:

>>> import binascii
>>> binascii.hexlify(bytearray(array_alpha))
'8535eaf1'

Here is a benchmark of above methods in Python 3.6.1:

from timeit import timeit
import binascii

number = 10000

def using_str_format() -> str:
    return "".join("{:02x}".format(x) for x in test_obj)

def using_format() -> str:
    return "".join(format(x, "02x") for x in test_obj)

def using_hexlify() -> str:
    return binascii.hexlify(bytearray(test_obj)).decode('ascii')

def do_test():
    print("Testing with {}-byte {}:".format(len(test_obj), test_obj.__class__.__name__))
    if using_str_format() != using_format() != using_hexlify():
        raise RuntimeError("Results are not the same")

    print("Using str.format       -> " + str(timeit(using_str_format, number=number)))
    print("Using format           -> " + str(timeit(using_format, number=number)))
    print("Using binascii.hexlify -> " + str(timeit(using_hexlify, number=number)))

test_obj = bytes([i for i in range(255)])
do_test()

test_obj = bytearray([i for i in range(255)])
do_test()

Result:

Testing with 255-byte bytes:
Using str.format       -> 1.459474583090427
Using format           -> 1.5809937679100738
Using binascii.hexlify -> 0.014521426401399307
Testing with 255-byte bytearray:
Using str.format       -> 1.443447684109402
Using format           -> 1.5608712609513171
Using binascii.hexlify -> 0.014114164661833684

Methods using format do provide additional formatting options, as example separating numbers with spaces " ".join, commas ", ".join, upper-case printing "{:02X}".format(x)/format(x, "02X"), etc., but at a cost of great performance impact.

2 of 6
81

Consider the hex() method of the bytes type on Python 3.5 and up:

>>> array_alpha = [ 133, 53, 234, 241 ]
>>> print(bytes(array_alpha).hex())
8535eaf1

EDIT: it's also much faster than hexlify (modified @falsetru's benchmarks above)

from timeit import timeit
N = 10000
print("bytearray + hexlify ->", timeit(
    'binascii.hexlify(data).decode("ascii")',
    setup='import binascii; data = bytearray(range(255))',
    number=N,
))
print("byte + hex          ->", timeit(
    'data.hex()',
    setup='data = bytes(range(255))',
    number=N,
))

Result:

bytearray + hexlify -> 0.011218150997592602
byte + hex          -> 0.005952142993919551
๐ŸŒ
Programiz
programiz.com โ€บ java-programming โ€บ examples โ€บ convert-byte-array-hexadecimal
Java Program to Convert Byte Array to Hexadecimal
public class ByteHex { private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for ( int j = 0; j < bytes.length; j++ ) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } public static void main(String[] args) { byte[] bytes = {10, 2, 15, 11}; String s = bytesToHex(bytes); System.out.println(s); } }
๐ŸŒ
ZetCode
zetcode.com โ€บ csharp โ€บ bytearray-hexstring
C# byte array to hex string
July 5, 2023 - C# byte array to hex string tutorial shows how to convert a byte array to a hexadecimal string.
๐ŸŒ
Javainuse
javainuse.com โ€บ onlinebytes
Online Bytes to String(Text) Converter Tool
Online JWT Generator Online JWT Decoder Online JWT Validator JWT Brute Force Tester Online Bcrypt Generator and Validator Online Text Encryption and Decryption Tool Online File Encryption and Decryption Tool Password Strength Analyzer and Generator SAML Decoder and Parser Free Random Address Generator Mail Server Blacklist Checker Online MD5 Hash Generator Online Hex Encoder and Decoder Tool Online HTML Encoder Tool Online HTML Decoder Tool Online GZIP Compressor Tool Online GZIP Decompressor Tool Online Text to Deflate Compressor Tool Online Deflate to Text Decompressor Tool Online SHA512/256
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ python-convert-bytearray-to-hexadecimal-string
Convert Bytearray to Hexadecimal String - Python - GeeksforGeeks
July 12, 2025 - format(byte, '02x') ensures each byte is converted to a two-digit hexadecimal string (padded with zero if needed).
๐ŸŒ
Code Beautify
codebeautify.org โ€บ byte-to-string
Best Byte to String Online Converter
Convert Byte Array to String helps to read Byte Unicode as String Code. Upload Byte File or load from url.