我目前正在处理需要将Base64字符串传递给PowerShell脚本的内容。但是,当将字符串解码回原始字符串时,由于我需要在解码期间使用UTF-7而我得到了一些意想不到的结果,我不明白为什么。有人知道为什么吗?
Mozilla documentation表示如果您的字符串中包含Unicode字符,则不足以使用Base64。因此,您需要使用包含使用encodeURIComponent
和替换的变通方法。我真的不明白为什么需要替换并将其缩短为btoa(escape('✓ à 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解码。但是如果你这样做,你最终会得到一个在文件中看起来像�
或在控制台上看起来像?
的重音符号。要获取实际的原始字符串,必须告诉URL解码使用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('✓ à la mode')
,则最终会得到以下字符串%u2713%20%E0%20la%20mode
。因此,我们有一个复选标记的Unicode表示和á
的HTML实体。如果我们直接在UrlDecode
中使用它,我们最终会遇到相同的错误。我目前的假设是PowerShell窗口的编码和将字符粘贴到其中是一个问题。
答案 0 :(得分:0)
事实证明它实际上并不奇怪。它只是为了我想要做的事情,使用更新的功能的优点。如果您使用UTF-7编码,我仍然不确定它为什么会起作用。但无论如何,作为解释:
...字符的十六进制形式,其代码单位值为0xFF或更小,是一个两位数的转义序列:%xx。对于具有更大代码单元的字符,使用四位数格式的%uxxxx。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape
正如TesselatingHecksler所指出的,What is the proper way to URL encode Unicode characters?表明%u
格式以前没有标准化。现在存在一个用于转义字符的较新版本,即encodeURIComponent
。
encodeURIComponent()函数通过将某些字符的每个实例替换为表示字符的UTF-8编码的一个,两个,三个或四个转义序列来编码统一资源标识符(URI)组件(将只有四个转义符号)由两个"代理"字符组成的字符的序列。
此函数的输出实际上与UrlDecode
的C#实现一起使用,而不提供额外的UTF-7编码。
关于UTF-8字符串的Base64编码的原始链接Mozilla文章修改了整个过程,允许您只调用Base64解码函数以获取整个字符串。这是通过将字符串的URL编码版本转换为字节来实现的。