DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 16.10 Converting Pointers to a Byte[ ], SByte[ ],or Char[ ] to a String

Problem

You have obtained a pointer to a byte array, an sbyte array, or a char array. You want to convert this array into its string equivalent.

Solution

Use one of the string object's constructors that build a string from either a byte*, sbyte*, or char* passed in as a parameter. The following overloaded ConvertToString methods accept a byte[], an sbyte[], or a char[] and return the equivalent string object created from these arrays:

public string ConvertToString(byte[] arr)
{
    unsafe
    {
        string returnStr;
        fixed(byte* fixedPtr = arr)
        {
            returnStr = new string((sbyte*)fixedPtr);
        }
    }

    return (returnStr);
}

public string ConvertToString(sbyte[] arr)
{
    unsafe
    {
        string returnStr;
        fixed(sbyte* fixedPtr = arr)
        {
            returnStr = new string(fixedPtr);
        }
    }

    return (returnStr);
}

public string ConvertToString(char[] arr)
{
    unsafe
    {
        string returnStr;
        fixed(char* fixedPtr = arr)
        {
            returnStr = new string(fixedPtr);
        }
    }

    return (returnStr);
}

The following code calls these methods, passing in one of the required array types:

Console.WriteLine(ConvertToString(new byte[3] {0x61,0x62,0x63}));
Console.WriteLine(ConvertToString(new char[3] {'a','b','c'}));
Console.WriteLine(ConvertToString(new sbyte[3] {0x61,0x62,0x63}));

Discussion

The System.String constructor that takes an sbyte* in the Solution code is expecting a null-terminated string in the buffer. There are also constructors on System.String that take an sbyte* and default to Unicode, or allow you to pass an Encoding object. One method to create a string from these arrays is to use a foreach loop to iterate over each element in the array and append the character value of each array element to the end of a StringBuilder object. However, this would operate slower than using the technique in this recipe. In fact, assuming a null-terminated string is in the byte array, the following unsafe code to convert a byte array to a string executes in 46% of the time of its equivalent safe code:

public string ConvertToString(byte[] arr)
{
    unsafe
    {
        string returnStr;
        fixed(byte* fixedPtr = arr)
        {
            returnStr = new string((sbyte*)fixedPtr);
        }
    }

    return (returnStr);
}

The safe code is shown here:

public string ConvertToStringSlow(byte[] arr)
{
    System.Text.StringBuilder returnStr = new System.Text.StringBuilder( );
    foreach (sbyte C in arr)
    {
        returnStr.Append(C);
    }

    return (returnStr.ToString( ));
}

In addition, the unsafe code is twice as fast as the following code, which uses the Encoding.ASCII class to convert a byte array to a string:

public string ConvertToASCIIStringSlow(byte[] arr)
{
    String retStr = Encoding.ASCII.GetString(arr);

    return (retStr);
}

This recipe uses two overloaded string constructors that accept either a pointer to a byte array or a pointer to a char array. The constructor then uses this array to construct a string from the array. The newly created string object is then initialized to this string created from the array. The constructors used in this recipe are defined as follows:

unsafe public String(char* value)
unsafe public String(sbyte* value)

The parameter for this constructor is defined as follows:

value

A pointer to either a char array or an sbyte array.

Note that if a pointer to a byte array is passed in, it must be cast to an sbyte:

returnStr = new string((sbyte*)fixedPtr);

Notice that the array's length is not passed in to the string constructor. Instead, the constructor will keep appending array values to the string until a null character is reached. If you know how many characters are in the array, then you should use the string overload that allows you to pass in the length.

See Also

See the "Unsafe Code Tutorial" and the "Encoding Class" topics in the MSDN documentation.

    [ Team LiB ] Previous Section Next Section