【问题标题】:Can a byte[] array ever not convert to a Base64 string?byte[] 数组不能转换为 Base64 字符串吗?
【发布时间】:2019-12-30 23:59:50
【问题描述】:

除了 byteArray 为空之外,是否有任何 byte[] 组合会导致此操作失败?

var myString = Convert.ToBase64String(byteArray);

我在想……以字节零(null?)开始或结束。一个空的byte[]?一个很大的byte[]?一些在 Base64 中没有意义的字节序列?我的问题是未知的未知数。

【问题讨论】:

  • AFAIK,不...虽然内存大小可能是个问题
  • 是否有一些假设的边缘情况会失败?几乎可以肯定...但是您实际上要解决什么问题?
  • Base64Encoding 适用于任何可以用二进制表示的东西,包括字节。
  • 我假设您的意思是文档中未指定的任何内容。如果是这样,答案是否定的,只是无法证明。

标签: c# tobase64string


【解决方案1】:

除了 byteArray 为 null 之外,是否有任何 byte[] 组合会导致此操作失败?

如docs 所述:没有。 Exception-明智的是,您使用的 Convert.ToBase64String 重载只会抛出 ArgumentNullException(当其参数 inArray 为空时)。

【讨论】:

  • 不是反对者,但这个回复和评论一样有效
  • @ĴošħWilliard 你能详细说明原因吗?
【解决方案2】:

是否有任何字节[]的组合会导致失败

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

除了 byteArray 是否为空?

没有。

以字节零开始或结束(null?)

以 0 结尾:

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

领先0:

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

顺便说一句……

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

不,这不仅仅是忽略 0。

一个空字节[]?

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

空字符串。

一个非常大的字节[]?

恩...

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

嗯……

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

它活了下来。

一些在 Base64 中没有意义的字节序列?

不存在这样的东西。您将输入作为二进制(基数 2),将基数转换为基数 64,并遵循表示标准。


我的问题是未知的未知数。

一般来说,坚持the documentation,不要尝试做没有记录的事情。

我认为平台中可能存在错误。 我知道有一些错误,ToBase64String 中没有。但是 - 通常 - 修复它们或解决它们不是您的责任(有时您必须这样做)。如果你偶然发现了一个,请报告它。

bug 的问题是它们在被发现之前都是未知的未知数。你可以试试看here和here。除此之外,如果我不认识他们,我怎么能给你指点呢?

哦,你想找错误吗?好吧,测试(就像我为这个答案所做的那样),并查看源代码(reference source、.NET Core)。 嘿,他们正在使用ReadOnlySpan,我想这就是为什么它没有被大数组炸毁的原因。

【讨论】:

    【解决方案3】:

    任何可以表示为二进制的东西都可以进行 base64 编码。这是因为该算法处理数据的二进制表示,而不是您使用它的任何表示。出于这个原因,任何二进制字符串都可以被编码,但是当你解码时你必须准确的知道结果类型。

    创建自己的 base64 编码器和解码器将是一个值得练习的练习,或者如果你愿意的话。我在回答中包含了我自己的 base64 编码类以用作参考。它远不是最有效的方法,而且可能比 .NET 的本机实现慢得多,而且它只解码回字符串。但我认为从初学者的角度来看,我的可能更容易阅读。

    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;
        }
    
    }
    }
    

    【讨论】:

    • 我在问题的任何地方都没有看到 throw 或 exception 一词;)但是,是的,你是对的。文档确实概述了抛出的异常,我更关注直觉,即为什么除了一组非常特定的输入之外没有抛出异常。
    猜你喜欢
    • 2011-06-17
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2012-07-21
    • 2016-10-21
    相关资源
    最近更新 更多