如何把文本编码为 UTF-16 Base64
- 在 输入 · 文本 中输入或粘贴文本。字符集 已预设为 UTF-16LE。
- 从 输出 · Base64 复制 Base64。输入 数值显示 UTF-16 字节数,是普通英文文本长度的两倍。
- 如果接收方使用大端序,把 字符集 切换为 UTF-16BE。
- 互换 会把结果再解码一次,方便快速核对;专门的解码器是 Base64 转 UTF-16。
UTF-16LE 与 UTF-16BE
UTF-16 把每个字符存储为一个或两个 16 位码元。小端序先写低字节,大端序先写高字节。Windows 和 .NET 使用小端序;Java 的 UTF-16 编码器和许多网络格式使用大端序。
| 文本 | UTF-16LE 字节 | UTF-16LE Base64 | UTF-16BE Base64 |
|---|---|---|---|
Hi | 48 00 69 00 | SABpAA== | AEgAaQ== |
Hello | 10 字节 | SABlAGwAbABvAA== | AEgAZQBsAGwAbw== |
€ | AC 20 | rCA= | IKw= |
👋 | 3D D8 4B DC | PdhL3A== | 2D3cSw== |
基本多文种平面(BMP)以外的字符,包括所有 emoji,需要两个码元,称为代理对。👋(U+1F44B)变成 D83D DC4B,也就是最后一行中的 4 个字节。
由于每个 ASCII 字母都和一个零字节配对,英文文本的 UTF-16 Base64 中会夹杂大量 A。遇到有这种特征的陌生字符串,不妨按 UTF-16 解码试试。
UTF-16 Base64 用在哪里
- PowerShell
-EncodedCommand。powershell -EncodedCommand RwBlAHQALQBEAGEAdABlAA==会运行Get-Date。这类命令失败的一个常见原因是脚本被编码成了 UTF-8。PowerShell EncodedCommand 工具 会添加命令前缀,提醒cmd.exe的长度限制,还能解码日志中发现的命令。 - .NET 代码。 C# 中的
Encoding.Unicode就是 UTF-16LE,所以Convert.ToBase64String(Encoding.Unicode.GetBytes(s))的输出与本页面相同。 - Windows 数据。 注册表中的字符串、SQL Server 中转换为二进制的
NVARCHAR列,以及许多 Windows API 返回的字符串,都是 UTF-16LE。
字节顺序标记
本工具不写入字节顺序标记,这正是 PowerShell 和大多数 API 所需要的。有些库会自动添加 BOM:
| 来源 | 开头字节 | Hi 的 Base64 |
|---|---|---|
| 本工具,UTF-16LE | 48 00 | SABpAA== |
Python "Hi".encode("utf-16") | FF FE 48 00 | //5IAGkA |
Java "Hi".getBytes(UTF_16) | FE FF 00 48 | /v8ASABp |
如果你的 Base64 必须和其中某个一致,请在代码中显式指定字节序进行编码,如下所示。
在代码中把 UTF-16 转为 Base64
import base64
base64.b64encode("Get-Date".encode("utf-16-le")).decode() # 'RwBlAHQALQBEAGEAdABlAA=='
base64.b64encode("Hi".encode("utf-16-be")).decode() # 'AEgAaQ=='
// Node.js has a little-endian codec only
Buffer.from("Get-Date", "utf16le").toString("base64"); // "RwBlAHQALQBEAGEAdABlAA=="
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('Get-Date'))
在 Python 中,除非你需要 BOM,否则请使用 utf-16-le 而不是 utf-16。更多示例:Python、Node.js。
常见问题
为什么 PowerShell 需要 UTF-16LE 的 Base64?
powershell -EncodedCommand 需要的是脚本 UTF-16LE 字节的 Base64,因为 Windows 内部就是这样存储字符串的。UTF-8 的 Base64 会解码成错误的字符,命令随之失败。PowerShell EncodedCommand 工具 可以生成完整的命令行。
UTF-16LE 和 UTF-16BE 有什么区别?
区别在于每个码元中两个字节的顺序。H 在小端序中是 48 00,在大端序中是 00 48,所以 Hi 会编码为 SABpAA== 或 AEgAaQ==。
输出会以字节顺序标记(BOM)开头吗?
不会,只编码文本自身的字节。Python 的 "utf-16" 编解码器和 Java 的 UTF_16 字符集会添加 BOM,所以它们的 Base64 以 //5 或 /v8 开头。
为什么 UTF-16 的 Base64 这么长?
UTF-16 每个字符至少占 2 个字节,所以英文文本在 Base64 再增加三分之一之前,就已经翻了一倍。Hello 在 UTF-8 中是 8 个 Base64 字符,在 UTF-16 中是 16 个。