如何将字节数组(MD5哈希)转换为字符串(36个字符)?我有一个使用哈希函数创建的字节数组。我想将此数组转换为字符串。到目前为止一切顺利,它会给我十六进制字符串。现在我想使用不同于十六进制字符的东西,我想用这36个字符对字节数组进行编码:[az][0-9]。我该怎么办?编辑:我这样做是因为我想要一个比十六进制字符串更小的字符串。我将这个任意长度的基本转换函数从这个答案改编为C#:varlength=number.Length;变种结果=字符串。空的;varnibbles=number.Select(c=>digits.IndexOf(c)).ToList();国际纽伦;做{变量值=0;纽伦=0;对于(vari=0;i=toBase){if(newlen==nibbles.Count){nibbles.Add(0);}nibbles[newlen++]=value/toBase;值%=toBase;}elseif(newlen>0){if(newlen==nibbles.Count){nibbles.Add(0);}半字节[newlen++]=0;}}长度=纽伦;结果=数字[值]+结果;//}while(newlen!=0);返回结果;因为它来自PHP,它可能不是太惯用的C#,并且没有参数有效性检查。但是,您可以输入十六进制编码的字符串,它会正常工作varresult=BaseConvert(hexEncoded,16,36);这不完全是您要求的,但是将byte[]编码为十六进制是微不足道的。看看它的实际效果。今晚早些时候,我遇到了围绕这里讨论的相同算法的转码问题。请参阅:https://codereview.stackexchange.com/questions/14084/base-36-encoding-of-a-byte-array/我提供了其早期答案之一的改进实现(均使用BigInteger)。请参阅:https://codereview.stackexchange.com/a/20014/20654。该解决方案采用byte[]并返回Base36字符串。原始的和我的都包含简单的基线信息。为了完整起见,下面是如何从字符串中解码byte[]。我还将包括上面链接中的编码功能。有关解码的一些简单基准信息,请参阅此代码块后面的文本。constintkByteBitCount=8;//一个字节中的位数//我们在FromBase36String和ToBase36String中使用的常量conststringkBase36Digits="0123456789abcdefghijklmnopqrstuvwxyz";staticreadonlydoublekBase36CharsLengthDivisor=Math.Log(kBase36Digits.Length,2);staticreadonlyBigIntegerkBigInt36=newBigInteger(36);//假设输入'chars'是大端顺序,MSB->LSBstaticbyte[]FromBase36String(stringchars){varbi=newBigInteger();for(intx=0;xLSBstaticstringToBase36String(byte[]bytes){//估计结果的长度,这样我们就不会浪费时间重新分配intresult_length=(int)Math.Ceiling(bytes.Length*kByteBitCount/kBase36CharsLengthDivisor);//我们使用一个列表,这样我们就不必复制到一个StringBuilder的字符//到一个char[],然后Array.Reverseitlatervarresult=newSystem.Collections.Generic.List(result_length);vardividend=newBigInteger(bytes);//IsZero的计算量少了c比评估“股息>0”更复杂//它调用BigInteger.CompareTo(BigInteger)while(!dividend.IsZero){BigIntegerremainder;dividend=BigInteger.DivRem(dividend,kBigInt36,outremainder);intdigit_index=Math.Abs??((int)remainder);结果.Add(kBase36Digits[digit_index]);}//以大端顺序定位字符result.Reverse();//ToArray还将修剪长度预测中使用的多余字符returnnewstring(result.ToArray());}“测试1234。稍微大一点!”编码为Base64为“165kkoorqxin775ct82ist5ysteekll7kaqlcnnu6mfe7ag7e63b5”在我的机器上解码Base36字符串1,000,000次需要12.6558909秒(我使用与答案中提供的相同的构建和机器条件)你提到你正在处理MD5哈希的字节[],不是它的十六进制字符串表示,所以我认为这个解决方案给你的开销最少如果您想要一个较短的字符串并且可以接受[a-zA-Z0-9]和+和/然后查看Convert.ToBase64StringUsingBigInteger(需要System.Numerics参考)UsingBigInteger(需要System.Numerics参考)conststringchars=“0123456789abcdefghijklmnopqrstuvwxyz”;//结果用chars[0]填充,使字符串长度//(int)Math.Ceiling(bytes.Length*8/Math.Log(chars.Length,2))//(这样对于任何值[0...0]-[255...255]个字节,结果字符串将具有相同的长度)publicstaticstringToBaseN(byte[]bytes,stringchars,boollittleEndian=true,intlen=-1){if(bytes.Length==0||len==0){返回String.Empty;}//BigInteger在最后一个字节中保存符号。>7F负,//0x7F?bytes.Length+1:bytes.Length];//我们复制并反转数组for(inti=bytes.Length-1,j=0;i>=0;i--,j++){bytes2[j]=bytes[i];}}BigIntegerbi=newBigInteger(bytes2);//一点优化。我们将根据//chars.Length进行许多划分。BigInteger长度=chars.Length;//我们预先计算字符串的长度。我们知道一个字节的//“信息”位是8。我们使用Log2计算新基数的//信息位。如果(len==-1){len=(int)Math.Ceiling(bytes.Length*8/Math.Log(chars.Length,2));}//我们将在char[]上构建我们的字符串varchs=newchar[len];intchsIndex=0;while(bi>0){BigInteger余数;bi=BigInteger.DivRem(bi,length,outremainder);chs[小字节序?chsIndex:len-chsIndex-1]=chars[(int)remainder];索引++;如果(chsIndex0){抛出新的OverflowException();}}}//我们附加我们在开头跳过的零if(littleEndian){while(chsIndex0x7Fif(len2>=2&&bytes[len2-1]==0){len2--;}intlen3=Math.Min(len,len2);byte[]bytes2;if(littleEndian){if(len==bytes.Length){bytes2=bytes;}else{bytes2=newbyte[len];Array.Copy(bytes,bytes2,len3);}}else{bytes2=newbyte[len];for(inti=0;i请注意,它们是真的这很慢!真慢!(10分钟2分钟)为了加快它们的速度,您可能需要重写除法/模运算,以便它们直接在缓冲区上工作,而不是每次由BigInteger完成时都重新创建暂存器。它仍然会很慢。问题在于编码第一个字节所需的时间是O(n),其中n是字节数组的长度(这是因为所有数组都需要除以36)。除非你想使用5字节块并丢失一些位。Base36每个符号携带大约5.169925001位。所以这些符号中的8个将携带41.35940001位。非常接近40字节。请注意,这些方法适用于小端模式和大端模式。输入和输出的字节顺序是一样的。两种方法都接受一个len参数。您可以使用它来修剪额外的0(零)。请注意,如果您尝试使输出太小而无法包含输入,则会抛出OverflowException。System.Text.Encodingenc=System.Text.Encoding.ASCII;字符串myString=enc.GetString(myByteArray);您可以使用所需的编码:System.Text.ASCIIEncoding、System.Text.UnicodeEncoding、System.Text.UTF7Encoding、System.Text.UTF8Encoding要匹配请求[az][0-9],您可以使用:Byte[]bytes=newByte[]{200,180,34};字符串结果=String.Join("a",bytes.Select(x=>x.ToString()).ToArray());您将使用char定界符来表示字节的字符串。要转换回来,您需要使用与.Select()相同的方法将string[]拆分并转换为byte[]。通常使用2的幂-这样一个字符映射到固定数量的位。例如,32位字母表将映射到5位。这种情况下唯一的挑战是如何反序列化可变长度字符串。对于36位,您可以将数据视为一个大数字,那么:也许说起来容易做起来难。您可以使用模数。此示例将您的字节数组编码为[0-9][az]的字符串。如果你想改变它。publicstringbyteToString(byte[]byteArr){inti;char[]charArr=newchar[byteArr.Length];for(i=0;i如果不想丢失解码数据,可以使用下面的例子:publicstringbyteToString(byte[]byteArr){inti;char[]charArr=newchar[byteArr.Length*2];for(i=0;i现在你有一个double字符串,当oddchar是36的乘积时,evenchar是残差。例如:200=36*5+20=>"5k"。以上就是C#学习教程:Howtoconvertbytearray(MD5hash)tostring(36characters)?分享所有内容,如果对你有用,需要了解更多C#学习教程,希望大家多多付出注意---本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除,如需转载请注明出处:
