简体   繁体   中英

Can a byte[] array ever not convert to a Base64 string?

Is there any combination of a byte[] that will cause this to fail, other than byteArray being null?

var myString = Convert.ToBase64String(byteArray);

I'm thinking something like... starting or ending with byte zero (null?). An Empty byte[] ? A very large byte[] ? Some sequence of bytes that wouldn't make sense in Base64? My issue is the unknown unknowns.

Is there any combination of a byte[] that will cause this to fail

byte[] byteArray = null;
var myString = Convert.ToBase64String(byteArray);
// NullArgumentException.

other than byteArray being null?

Nope.

starting or ending with byte zero (null?)

Ending in 0:

var byteArray = new byte[] {255, 255, 0};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString); // +voA

Leading 0:

var byteArray = new byte[] {0, 250, 250};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString); // APr6

By the way...

var byteArray = new byte[] {250, 250};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString); // +vo=

No, it is not just ignoring the 0.

An Empty byte[]?

var byteArray = new byte[] {};
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString.Length); // 0

Empty string.

A very large byte[]?

Ern...

var byteArray = new byte[int.MaxValue]; // OutOfMemoryException

Hmm...

var byteArray = new byte[int.MaxValue / 8];
var myString = Convert.ToBase64String(byteArray);
Console.WriteLine(myString.Length); // 357913940

It survived.

Some sequence of bytes that wouldn't make sense in Base64?

No such thing exists. You take the the input as binary (base 2), do base conversion to base 64, and follow the standard for representation.


My issue is the unknown unknowns.

In general, stick to the documentation and do no try to do something that is not documented.

I suppose there is a chance that there could be a bug in the platform. There are some bugs, none in ToBase64String that I know of . However - in general - it is not your responsability to fix them or work around them (sometimes you will have to). If you happen to stumble upon one, report it.

The thing with bugs is that they are unknown unknowns until discovered. You can try to have a look here and here . Beyond that, how will I be able to point you to them if I do not know them?

Oh, you want to find bugs? Alright, test (as I did for this answer), and review the source ( reference source , .NET Core ). Hey, they are using ReadOnlySpan , I guess that is why it did not blow up with the large array.

Is there any combination of a byte[] that will cause this to fail, other than byteArray being null?

As stated on the docs : no. Exception -wise the Convert.ToBase64String overload you are using only throws ArgumentNullException (when its parameter inArray is null).

Anything that can be represented as binary can be base64 encoded. This is because the algorithm deals with the binary representation of data, rather than whatever presentation you are using it as. For this reason any binary string can be encoded , however when you decode you have to be exact about the result type.

It would be a worthwhile exercise, or kata if you would, to create your own base64 encoder and decoder. I've included in my answer my own base64 encoding class to use as a reference. It is far from the most efficient way of doing this, and is probably considerably slower than .NET's native implementation, and it only decodes back into strings. But I think mine is probably easier to read from a beginner's point of view.

public class Base64Utility
{
    List<char> characterMap = new List<char>()
    {
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '+', '/'
    };

    public string Base64Encode(string source)
    {
        string result = string.Empty;
        int octetsMissing = 0;
        string byteString = string.Empty;

        byte[] bytes = new byte[source.Length];
        int[] base10Integers = new int[source.Length];

        for (int i = 0; i < source.Length; i++)
        {
            byte b = Convert.ToByte(source[i]);
            bytes[i] = (b);
            base10Integers[i] = Convert.ToInt32(bytes[i].ToString(), 10);
            byteString += Convert.ToString(bytes[i], 2).PadLeft(8, '0');
        }

        for (int byteIndex = 0; byteIndex < byteString.Length;)
        {
            int span = byteString.Length - byteIndex >= 6
                ? 6
                : byteString.Length - byteIndex;

            string subString = byteString.Substring(byteIndex, span);

            if (subString.Length < 6)
            {
                octetsMissing = (6 - subString.Length) / 2;
                for (int i = subString.Length; i < 6; i++)
                {
                    subString += '0';
                }
            }

            int index = Convert.ToInt32(subString, 2);

            result += characterMap[index];

            byteIndex += span;
        }

        for (int i = 0; i < octetsMissing; i++)
        {
            result += '=';
        }
        return result;
    }

    public string Base64Decode(string source)
    {
        string result = string.Empty;

        int[] mappedSource = new int[source.Length];
        string[] mappedSourceAsBinary = new string[source.Length];

        for (int i = 0; i < source.Length; i++)
        {
            if(source[i] != '=')
            {
                mappedSource[i] = characterMap.IndexOf(source[i]);
                mappedSourceAsBinary[i] = Convert.ToString(mappedSource[i], 2);
            }

            if(mappedSourceAsBinary[i] != null)
            {
                if(mappedSourceAsBinary[i].Length < 6)
                {
                    for(int j = mappedSourceAsBinary[i].Length; j < 6; j++)
                    {
                        mappedSourceAsBinary[i] = '0' + mappedSourceAsBinary[i];
                    }
                }
            }
        }

        string temp = string.Empty;
        for(int i = 0; i < mappedSourceAsBinary.Length; i++)
        {
            temp += mappedSourceAsBinary[i];
        }

        string[] t = new string[temp.Length / 8];

        for (int i = 0; i < t.Length; i++)
        {
            t[i] = temp.Substring(8*i, 8);
            int res = Convert.ToInt32(t[i], 2);
            char resAscii = Encoding.ASCII.GetString(new byte[] { (byte)res })[0];
            result += resAscii;
        }

        return result;
    }

}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM