无法理解PowerShell中使用Unicode字符的C#URL解码

无法理解PowerShell中使用Unicode字符的C#URL解码,powershell,unicode,encoding,Powershell,Unicode,Encoding,我目前正在做一些事情,需要我将Base64字符串传递给PowerShell脚本。但是当我把字符串解码回原来的状态时,我得到了一些意想不到的结果,因为我需要在解码过程中使用UTF-7,我不明白为什么。有人知道为什么吗 如果字符串中有Unicode字符,则建议使用Base64是不够的。因此,您需要使用一种变通方法,包括使用encodeURIComponent和替换。我真的不明白为什么需要替换,并将其缩短为btoa(escape)✓ (a la mode'))对字符串进行编码。该操作的结果将是JXUy

我目前正在做一些事情,需要我将Base64字符串传递给PowerShell脚本。但是当我把字符串解码回原来的状态时,我得到了一些意想不到的结果,因为我需要在解码过程中使用UTF-7,我不明白为什么。有人知道为什么吗

如果字符串中有Unicode字符,则建议使用Base64是不够的。因此,您需要使用一种变通方法,包括使用
encodeURIComponent
和替换。我真的不明白为什么需要替换,并将其缩短为
btoa(escape)✓ (a la mode'))
对字符串进行编码。该操作的结果将是
JXUyNzEzJTIwJUUwJTIwbGElMjBtb2Rl

使用PowerShell将字符串解码回原始字符串,我需要首先撤消Base64编码。为了执行
System.Convert,可以使用
System.Text.Encoding
将其输出转换为UTF-8字符串(从而生成字节数组)。这两种情况合在一起如下所示:

$bytes = [System.Convert]::FromBase64String($inputstring)
$utf8string = [System.Text.Encoding]::UTF8.GetString($bytes)
剩下要做的就是对整个事情进行URL解码。由于它是一个UTF-8字符串,我希望只需要运行URL解码,而不需要任何其他参数。但如果你这样做,你最终会得到一个重音a,看起来像
在文件中或控制台上的
。要获得实际的原始字符串,需要告诉URL decode使用UTF-7作为字符集。这很好,但我真的不明白为什么它是必要的,因为字符串应该是UTF-8,UTF-8当然支持重音a。请参阅整个脚本的最后两行了解我的意思。使用这两行代码,您将得到一行有乱码文本的代码,另一行有UTF-8编码的同一文件中的原始文本

整个PowerShell脚本:

Add-Type -AssemblyName System.Web
$inputstring = "JXUyNzEzJTIwJUUwJTIwbGElMjBtb2Rl"
$bytes = [System.Convert]::FromBase64String($inputstring)
$utf8string = [System.Text.Encoding]::UTF8.GetString($bytes)
[System.Web.HttpUtility]::UrlDecode($utf8string) | Out-File -Encoding utf8 C:\temp\output.txt
[System.Web.HttpUtility]::UrlDecode($utf8string, [System.Text.UnicodeEncoding]::UTF7) | Out-File -Append -Encoding utf8 C:\temp\output.txt
澄清:
问题不是Base64到UTF-8的转换。问题在于C#的
UrlDecode
的某些不一致行为。如果运行
escape('✓ 在浏览器中,您将得到以下字符串
%u2713%20%E0%20la%20mode
。因此,我们有一个复选标记的Unicode表示和一个用于
á
的HTML实体。如果我们在
UrlDecode
中直接使用此选项,则会出现相同的错误。我目前的假设是,对PowerShell窗口进行编码并将字符粘贴到其中是一个问题。

事实证明,这并不奇怪。这只是为了我想做的,使用更新的函数是有好处的。如果使用UTF-7编码,我仍然不知道为什么它会起作用。但无论如何,作为一种解释:

。。。代码单位值为0xFF或以下的字符的十六进制形式是两位转义序列:%xx。对于代码单位较大的字符,使用四位格式%uxxx

正如TesselatingHecksler指出的那样,
%u
格式以前没有标准化。不过,存在一个用于转义字符的较新版本,即

函数的作用是:用表示字符UTF-8编码的一个、两个、三个或四个转义序列替换某些字符的每个实例,从而对统一资源标识符(URI)组件进行编码(对于由两个“代理”字符组成的字符,只会有四个转义序列)

该函数的输出实际上与
UrlDecode
的C#实现一起工作,而不提供额外的UTF-7编码

关于UTF-8字符串的Base64编码的原始链接Mozilla文章修改了整个过程,使您只需调用Base64解码函数即可获得整个字符串。这是通过将字符串的URL编码版本转换为字节来实现的