String system.convert.TOBASE64字符串(以F#表示)

String system.convert.TOBASE64字符串(以F#表示),string,hash,encoding,f#,String,Hash,Encoding,F#,我真的不明白这个函数的作用 > System.Convert.ToBase64String [|7uy;243uy|];; val it : string = "B/M=" > System.Convert.ToBase64String [|243uy;7uy|];; val it : string = "8wc=" > System.Convert.ToBase64String [|243uy|];; val it : string = "8w==" > System.

我真的不明白这个函数的作用

> System.Convert.ToBase64String [|7uy;243uy|];;
val it : string = "B/M="
> System.Convert.ToBase64String [|243uy;7uy|];;
val it : string = "8wc="
> System.Convert.ToBase64String [|243uy|];;
val it : string = "8w=="
> System.Convert.ToBase64String [|243uy;7uy;3uy|];;
val it : string = "8wcD"
> System.Convert.ToBase64String [|243uy;7uy;3uy;5uy|];;
val it : string = "8wcDBQ=="
我本以为该函数是“可交换的”,如果我们假设第一个答案,那么
System.Convert.ToBase64String[| 243uy;7uy |]将产生

val it : string = "M=B/"
我还感到惊讶的是,对于一个包含1、2和3个元素的数组,大小是一个长度为4的字符串,然后我们从一个大小为4的数组移到了8

我没有找到任何解释

我原以为
System.Text.Encoding.UTF8.GetString
会做我想做的事情(手动生成一个字符串散列),但令人尴尬

> System.Text.Encoding.UTF8.GetString [|243uy;7uy|];;
val it : string = "�"
> System.Text.Encoding.UTF8.GetString [|7uy;243uy|];;
val it : string = "�"
一模一样 单独地

> System.Text.Encoding.UTF8.GetChars [|7uy;243uy|];;
val it : char [] = [|'\007'; '�'|]
> System.Text.Encoding.UTF8.GetChars [|243uy;7uy|];;
val it : char [] = [|'�'; '\007'|]

谢谢

不知道你的背景,请原谅我快速介绍了基本知识:

基数:首先,您需要了解基数的一般工作原理,以及二进制(基数2)的具体工作原理。如果你不明白我说的243=0b11110011或0b00000111=7是什么意思,你可以查看以下链接:--他比我解释得更好。:)我们需要知道这一点,因为为了理解Base64编码,您需要能够在十进制和二进制之间转换数字,反之亦然

Base64:要理解Base64编码,我们需要深入到位的级别。请参阅以获得非常清晰的图片。Base64的目的是帮助准备二进制数据,以便通过不可靠地处理非文本数据的方法在计算机系统之间发送,例如在支持附件之前的电子邮件。它通过组合字节的数据并重新切片它们的边界来实现这一点,这样每个单元都有6位而不是8位。6位可以容纳2^6=64个不同的值,整个可打印字符用于表示此base64单元。通常,A-Z表示值0-25、A-Z=26-51、0-9=52-61和两个最终字符,+表示值62和/或表示值63。这种数据表示需要更多的内存——它需要4字节的可打印字符来表示3字节的二进制数据,但好处是数据现在可以表示为文本(因此在不同的系统和字符集中更可能是相同的二进制数据)。当接收到数据时,这个过程会被反转,然后你会得到你的二进制数据

还有一件。二进制数据以3个字节的块消耗——这使得24个传入位可以很容易地重新划分为4个base64字符,每个字符6位。如果数据的结尾没有完全填满最后一个数据块,则编码将被填充,以便在另一端解码时保留正确的字节数。单个=将显示最后一个块填充了一个字节,而双等于(=)将显示最后一个块填充了两个字节。解码过程将知道最终创建的字节块将短1或2个字节

了解您的一些示例

让我们看一看您的第一个示例——您正在将字节7和243发送到函数中:

System.Convert.ToBase64String[|7uy;243uy|]
// byte 1    byte 2    no 3rd
// dec 7     dec 243   byte!
// 00000111  11110011  00000000
//  reslice 3*8 into 4*6
// 000001  111111  001100  000000
// dec 1   dec 63  dec 12  padding   <-- refer to wikipedia base64 table
// char B  char /  char M  char =
"B/M="
System.Convert.ToBase64String[|243uy;7uy|]
// byte 1    byte 2    no 3rd
// dec 243   dec 7     byte!
// 11110011  00000111  00000000
//  reslice 3*8 into 4*6
// 111100   110000  011100  000000
// dec 60   dec 48  dec 28  padding   <-- refer to wikipedia base64 table
// char 8  char w  char c   char =
"8wc="
您可以看到,交换一个3字节的块导致了4个字符输出块的完全交换

意外的输出大小您提到,您惊讶地看到长度为1、2和3的输入字节数组的输出为4个字符。到现在为止,您可能已经认识到Base64编码算法以3字节的块进行处理,为每个3字节的块生成4个字符的输出。结尾的等号是表示输入字节没有填充最后一个块的填充。要明确的是:

  • 1字节输入=4个字符输出,最后两个是填充
  • 2字节输入=4个字符输出,最后一个是填充
  • 3字节输入=4个字符输出,无填充
  • 4字节输入=8个字符输出,最后两个是填充
  • 等等
解码虽然您没有提到,但Base64是一种编码,这意味着存在解码。一旦拥有了字符,您就可以轻松地再次获取字节:

> System.Convert.FromBase64String "B/M=";;
val it : byte [] = [|7uy; 243uy|]

// or a more realistic string example:
> let bytes = System.Text.Encoding.UTF8.GetBytes( "foobar" );;
val bytes : byte [] = [|102uy; 111uy; 111uy; 98uy; 97uy; 114uy|]
> System.Convert.ToBase64String bytes;;
val it : string = "Zm9vYmFy"
> let bytes = System.Convert.FromBase64String "Zm9vYmFy";;
val bytes : byte [] = [|102uy; 111uy; 111uy; 98uy; 97uy; 114uy|]
> System.Text.Encoding.UTF8.GetString( bytes );;
val it : string = "foobar"
生成字符串哈希最后一个未回答的想法是你说你想生成字符串哈希。我不确定您是否打算将字符串编码为Base64(这可能是不必要的,因为字符串通常已经由可打印字符组成),除非它看起来像是被加密的(我猜有人会认为Base64可以很快解码)。但是,如果您想对字符串进行哈希,请记住所有对象都已经具有此功能。也许以下就是你想要的

> "Hash this please!".GetHashCode();;
val it : int = -1297461057

不管怎样,希望这有助于让事情变得更清楚。祝你好运

不知道你的背景,请原谅我快速介绍了基本知识:

基数:首先,您需要了解基数的一般工作原理,以及二进制(基数2)的具体工作原理。如果你不明白我说的243=0b11110011或0b00000111=7是什么意思,你可以查看以下链接:--他比我解释得更好。:)我们需要知道这一点,因为为了理解Base64编码,您需要能够在十进制和二进制之间转换数字,反之亦然

Base64:要理解Base64编码,我们需要深入到位的级别。请参阅以获得非常清晰的图片。Base64的目的是帮助准备二进制数据,以便通过不可靠地处理非文本数据的方法在计算机系统之间发送,例如在支持附件之前的电子邮件。它通过组合字节的数据并重新切片它们的边界来实现这一点,这样每个单元都有6位而不是8位。6位可以容纳2^6=64个不同的值,整个可打印字符用于表示此base64单元。通常,A-Z表示值0-25、A-Z=26-51、0-9=52-61和两个最终字符,+表示值62和/或表示值63。数据的这种表示需要更多的内存——它需要4字节的可打印字符
> "Hash this please!".GetHashCode();;
val it : int = -1297461057