pmarreck/printable-binary
GitHub: pmarreck/printable-binary
PrintableBinary 是一款跨平台的二进制数据编码解码工具,旨在将二进制内容转换为人类可读的 UTF-8 文本,便于在终端和文本环境中安全查看和共享。
Stars: 1 | Forks: 0
# PrintableBinary
[](https://garnix.io/repo/pmarreck/printable-binary)
[](https://github.com/pmarreck/printable-binary/actions/workflows/ci.yml)
一款跨平台的实用工具(包含 LuaJIT、C、Zig 和 JavaScript 实现),用于将任意二进制数据编码为人类可读的 UTF-8 文本,然后再将其解码回原始二进制数据。
## 概述
PrintableBinary 旨在将二进制数据序列化/反序列化为一种视觉上独特、人类可读的格式,该格式也支持复制粘贴,并可嵌入任何支持 UTF-8 的环境中。它是十六进制编码的一种替代方案,提供了更好的视觉密度,并能立即识别出嵌入的 ASCII 文本,同时也能将二进制数据融入基于文本的格式(如 JSON、TOML、XML、YAML 等),而不会出现转义问题。
此实现允许您在终端中直接查看二进制数据(它甚至带有 `--passthrough` 管道检查模式),而不会破坏显示,这使得它在调试、日志记录、以人类可读的形式共享二进制数据,甚至将文件拖放到 Web 界面进行即时编码/解码方面特别有用。
## 功能特性
- **多实现**:以 LuaJIT 脚本、编译后的 C 二进制文件、Zig 二进制文件和 JavaScript 模块(由浏览器 UI 和 Node.js 工具共享)的形式提供,具有最大灵活性
- **Web 与 Node.js 工具**:拖放式浏览器界面和基于 Node 的 CLI 包装器共享相同的编码/解码核心,支持跨平台工作流
- **视觉独特的字符**:256 个可能的字节值中的每一个都映射到一个唯一的、视觉上独特的 UTF-8 字符
- **ASCII 透传**:标准可打印 ASCII 字符(32-126)基本上保持原样,便于即时识别
- **Shell 安全编码**:可能引发 shell 问题的特殊字符使用安全的 Unicode 替代方案进行编码
- **单字符宽度**:每个编码表示形式在等宽终端中都渲染为单个字符宽度
- **紧凑性**:使用 1-3 字节的 UTF-8 字符以实现最佳空间效率
- **易用性**:编码后的字符串易于复制、粘贴和打印
- **格式化**:可自定义输出格式,支持分组大小和行宽选项
- **二进制安全**:在编码和解码时保留所有二进制数据,包括 NUL 字节
- **透传模式**:同时将原始二进制数据输出到 stdout,并将编码文本输出到 stderr,适用于灵活的处理管道
### 实际益处(为什么使用这个?)
- **人类可扫描的快照**:比十六进制更密集,比 Base64 更易读;非常适合需要字面量 UTF-8 而不是转义十六进制块的固件/测试。
- **更好的差异比较和可搜索性**:控制字符和空格是显式的,因此结构一目了然;比 `strings(1)` 功能丰富得多,后者会丢弃大部分字节。
- **可调试的日志和粘贴板**:可打印、可逆,经过 Slack/电子邮件/维基处理后不会被破坏或换行损坏。
- **小型二进制固件**:将头部、协议帧、证书等嵌入文本文件,同时保持补丁/友好搜索的便利性。
- **跨平台**:可在任何能运行 LuaJIT/Node 或构建 C 版本的地方工作。
- **等宽安全字形集**:每个字形都经过验证,在常见等宽字体中占据相同的宽度,因此在编辑器/终端/差异比较中的对齐保持完整(令人惊讶的是,许多 Unicode 符号做不到这一点)。
### 与十六进制编码对比
- **更高的屏幕显示密度**:十六进制每个字节需要两个字形;PrintableBinary 将每个字节映射到单个可见字符,因此您每行可以看到大约两倍的数据量,同时仍保持 UTF-8 安全性。
- **ASCII 突出显示**:可打印 ASCII 字节保持不变(除了那些对 shell 不友好的符号,它们使用相似的替代品),因此嵌入的文本是立即可读的,而不需要在心里解码十六进制对。
- **控制字符被标记**:字节 0–31 和 DEL 渲染为助记符号(`⏎`、`↧`、`⌫` 等),使结构和控制流一目了然,无需额外工具。
- **权衡**:十六进制在字节上扩展数据正好 2 倍。PrintableBinary 在现实世界的二进制文件上平均约为 1.8–1.9 倍(得益于许多 1 字节和 2 字节 UTF-8 映射),最坏情况下仅接近 3 倍。这点额外的代价换来了显著提高的可读性和粘贴安全性。
## 性能
Zig 实现通过源代码级别的数据结构改进和可选的 PGO(性能引导优化)对吞吐量进行了深度优化:
| 实现 | 编码 (10 MB) | 解码 (10 MB) | 编码吞吐量 | 解码吞吐量 |
|---|---|---|---|---|
| **Zig** | 51 ms | 62 ms | 121 MB/s | 108 MB/s |
| **PGO (C FFI + Zig)** | 50 ms | 63 ms | 125 MB/s | 109 MB/s |
| **C (独立)** | — | — | 与 Zig 相当 | 与 Zig 相当 |
| **Lua (LuaJIT)** | 233 ms | 2,510 ms | 86 MB/s | 3.9 MB/s |
Zig 核心的主要优化:
- **预分配缓冲区**:预先确定编码/解码输出的大小(热循环中无增长检查)
- **扁平字符映射表**:编译期构建的连续字节缓冲区(约 1.5 KB),取代 256 个分散的指针——可放入 L1 缓存
- **O(1) 解码查找**:针对 1 字节、2 字节和 3 字节 UTF-8 序列的直接查找表,取代 O(log 256) 的二进制搜索
- **无内部解码循环**:每个字符只需一次 UTF-8 长度检查和直接查找
这些源代码级更改相比初始的 ReleaseFast 构建,**编码速度提升了 16%**,**解码速度提升了 61% (2.6倍)**。PGO 路径 (`make pgo-ffi`) 通过配置文件引导的分支布局额外提供约 1-3% 的提升,使用 C FFI 命令行工具通过其公共 C ABI 来实际测试 Zig 库。
基准测试在 Apple M4 上运行,使用 `hyperfine --warmup 5 --min-runs 20` 对 `/dev/urandom` 生成的随机二进制数据进行测试。
## 使用方法
### 作为命令行工具
```
# Use any implementation:
# LuaJIT version: ./bin/printable-binary
# Node.js CLI: ./bin/printable-binary-node.js
# C version: make release && ./bin/printable-binary-c
# Zig version: nix build .#printableBinaryZig && ./bin/printable-binary-zig
# (Examples below use the LuaJIT version; the others accept the same flags.)
# Encode binary data
echo -n "Hello, World!" | ./bin/printable-binary
# Output: Hello,␣World﹗
# Note: Direct encoding of binary data as command-line arguments is not supported
# because shell environments cannot represent all binary data (such as NUL bytes)
# Always pipe input or specify a file to encode
# Encode a file
./bin/printable-binary somefile.bin > encoded.txt
# Encode with formatting (groups of 8 characters, 10 groups per line)
./bin/printable-binary -f somefile.bin > formatted_encoded.txt
# Encode with custom formatting (groups of 4 characters, 16 groups per line)
./bin/printable-binary -f=4x16 somefile.bin > custom_formatted.txt
# Inspect the active character map (table/JSON/CSV)
./bin/printable-binary --mappings | head
./bin/printable-binary-c --mappings-json > mapping.json
./bin/printable-binary-node.js --mappings-csv > mapping.csv
# Decode data (whitespace is ignored during decoding)
echo -n "Hello,␣World﹗" | ./bin/printable-binary -d
# Output: Hello, World!
# Decode formatted data (formatting is ignored)
cat formatted_encoded.txt | ./bin/printable-binary -d > original.bin
# Preserve literal whitespace (spaces, tabs, newlines stay as-is instead of being encoded)
echo -n "A B C" | ./bin/printable-binary --spaces > encoded_with_spaces.txt
./bin/printable-binary -d -S encoded_with_spaces.txt > restored.bin
# Preserve all whitespace (shorthand for -s -t -n)
./bin/printable-binary -w input.bin > with_whitespace.txt
# Preserve specific characters (e.g., keep ! and " literal)
./bin/printable-binary -p '!"' input.bin > preserved.txt
# Decode block-formatted input (strip whitespace separators first)
./bin/printable-binary -d -S formatted_encoded.txt > original.bin
# Use passthrough mode to output both original binary (stdout) and encoded text (stderr)
# This is useful for binary data processing pipelines that need both representations
echo -n "Hello, World!" | ./bin/printable-binary --passthrough 2>encoded.txt | wc -c
# Binary data goes to stdout, encoded text to stderr
# Use the C implementation for better performance on large files
./bin/printable-binary-c large_file.bin > encoded_large.txt
```
### 网页界面
- 在线演示:
- 拖放或浏览以编码任何文件;`.pbt` 上传会自动解码回其原始二进制形式。
- 大型输出(>1 MB)会跳过文本框以避免浏览器卡顿——使用下载按钮获取 UTF-8 文本。
- 默认换行是每行 75 个字符,以平衡可读性和密度;复制/下载按钮重用 CLI 和 Node 实现产生的确切字节。
- 要在本地修改,可在任何现代浏览器中打开 `docs/index.html`(或 `index.html`);该页面加载共享的 `js/printable_binary.js` 模块,无需构建步骤。
### 作为 Lua 库
```
local PrintableBinary = require("printable_binary")
-- Encode binary data
local binary_data = "Hello, World!"
local encoded = PrintableBinary.encode(binary_data)
print(encoded) -- Output: Hello,␣World!
-- Decode back to binary
local decoded = PrintableBinary.decode(encoded)
print(decoded) -- Output: Hello, World!
```
### 作为 JavaScript 模块
```
import PrintableBinary from './js/printable_binary.js';
const pb = new PrintableBinary();
const input = new Uint8Array([0x00, 0xFF, 0x41]);
// Encode to printable UTF-8
const encoded = pb.encode(input, { format: '75x1' });
console.log(encoded);
// Decode back to bytes
const decoded = pb.decode(encoded);
console.log(Array.from(decoded)); // [0, 255, 65]
// Preserve literal spaces (tabs/newlines/CR still ignored on decode)
const encodedSpaces = pb.encodeString('A B C', { spaces: true });
const decodedSpaces = pb.decodeToString(encodedSpaces, { spaces: true });
```
相同的模块驱动浏览器 UI,并可在 Node.js (ESM) 中运行或打包用于其他环境。
### JavaScript CLI
为了与 LuaJIT/C 工具在命令行上保持一致,请使用基于 Node 的包装器:
```
# Encode (auto-detects stdin vs. file)
./bin/printable-binary-node.js input.bin > encoded.pbt
# Decode (whitespace is ignored automatically)
./bin/printable-binary-node.js --decode encoded.pbt > restored.bin
# Apply formatting (e.g., 75 characters per line)
./bin/printable-binary-node.js --format 75x1 input.bin > formatted.pbt
# Pipe data through stdin
cat input.bin | ./bin/printable-binary-node.js -f=8x10 > encoded.txt
# Dump the current character map
./bin/printable-binary-node.js --mappings-json > map.json
```
支持的标志:`-d/--decode`、`-f/--format NxM`、`-s/--spaces`、`--mappings*`、`-h/--help`。CLI 与浏览器 UI 共享完全相同的编码/解码实现。
### 字符映射表
每个 CLI(以及构建后的 WASM 版本)都内嵌了规范的 256 项表,因此您随时可以检查它:
```
./bin/printable-binary --mappings # human-readable table
./bin/printable-binary --mappings-json # machine-readable JSON
./bin/printable-binary --mappings-csv # spreadsheet-friendly CSV
```
这些命令显示的是当前活动的映射表。要覆盖默认值,请将一个 `character_map.txt` 文件放在可执行文件旁边(或设置 `PRINTABLE_BINARY_MAP` 环境变量),然后重新运行相同的标志以确认您的更改。文件格式很简单:**256 行 UTF-8 文本,每行一个字形,对应从 0x00 开始的字节值**。没有逗号、空格或索引——只有按顺序排列的字面字符。编辑后,运行 `./utils/audit_character_map.lua character_map.txt`(以及在 Unicode 发布新宽度表时运行 `./utils/update_eaw_data.sh`),还有 `./utils/generate_embedded_map.lua` 以便嵌入的头部保持同步。
运行时查找顺序为:
1. `PRINTABLE_BINARY_MAP` 环境变量(文件路径)
2. 位于可执行文件/模块旁边的 `character_map.txt` 文件(`bin/printable-binary`、`js/printable_binary.js`、`bin/printable-binary-c` 或 WASM 目录)
3. 当前工作目录
如果这些位置都不存在,则自动使用内嵌的表。编辑文件以尝试替代字形——LuaJIT、C、Node.js 和 WebAssembly 实现都将在下次运行时遵守此覆盖。
### 环境变量
PrintableBinary 在所有实现(LuaJIT、C、WASM、Node 和测试)中都遵循几个环境变量:
- `PRINTABLE_BINARY_MAP` – 覆盖内嵌表的 `character_map.txt` 文件的绝对或相对路径。查找顺序如上所述。
- `PRINTABLE_BINARY_MUTE_STATS` – 设置为 `1`、`true` 或 `yes` 以抑制通常写入 stderr 的“已编码...”/“解码模式...”统计信息。这对于期望干净 stderr 输出同时仍重用默认交互行为的脚本非常有用。
使用 wazero 启动 WASM 构建时,请记住它**不会**继承主机环境变量,除非您显式传递它们。构建 `bin/printable-binary.wasm`(例如通过 `make wasm`)后,使用 `wazero run --env=PRINTABLE_BINARY_MUTE_STATS=true bin/printable-binary.wasm`(或使用 `--env-inherit` 转发所有变量),以便行为与原生二进制文件保持一致。
### 检查流(透传模式)
一个强大的技巧是将 PrintableBinary 放入管道中,以便在原始字节继续向下游传递的同时,在 stderr 上查看编码流:
```
# Monitor traffic but keep the pipeline lossless
tcpdump -i en0 -w - | \
./bin/printable-binary --passthrough > capture.raw 2> capture.pbt
# Alternatively inspect a decompression stream:
gzip -c bigfile > /tmp/data.gz
gzip -dc /tmp/data.gz | \
./bin/printable-binary --passthrough | md5sum
# stdout (original bytes) flows into md5sum; stderr shows the printable view.
```
因为 `--passthrough` 将原始二进制数据发送到 stdout,所以您可以在 Unix 管道中的任何位置插入 PrintableBinary 以进行可观测性检查,而无需修改数据流。
### 现实用法示例
- **免转义的 JSON 嵌入** – 通过预先编码字节,然后将其直接放入 JSON 字符串,避免反斜杠/引号地狱:
```
ENCODED="$(./bin/printable-binary secret.bin)"
printf '{"payload":"%s"}\n' "$ENCODED" | jq .
# 稍后解码:
printf '%s' "$ENCODED" | ./bin/printable-binary -d > restored.bin
```
- **Bash 对二进制片段的断言** – 在 here-doc 中内联保持固件,无需转义。生成编码块一次(例如,`PRINTABLE_BINARY_MUTE_STATS=1 printf 'CAFÉ\n' | ./bin/printable-binary`),然后将其粘贴到 here-doc 中:
```
want=$'CAFÉ\n' # 逐字节期望值
got=$(./bin/printable-binary -d <<'EOF'
CAFĹɃ¶
EOF
)
[[ "$got" == "$want" ]] || { echo "mismatch"; exit 1; }
```
- **就地查看混合二进制/文本流** – 镜像一个活动的 HTTP POST,同时保持原始字节不变:
```
nc -l 8080 | ./bin/printable-binary --passthrough \
>requests.raw 2>requests.pbt
# tail -f requests.pbt 查看头部+正文,不会出现乱码。
```
- **网页嵌入 + JS 解码** – 将二进制数据作为纯文本嵌入 HTML,然后在浏览器中使用共享模块将其恢复:
```html
```
- **查看常见格式的魔数字节** – 无需十六进制查看器即可发现魔数:
```
head -c 16 some.pdf | ./bin/printable-binary
# 预期看到 %PDF␣1.7… 直接渲染出来。
head -c 8 image.png | ./bin/printable-binary
# 如果 PNG 签名完整,应显示 89PNG⏎␣␣。
```
## 格式兼容性
PrintableBinary 字符集专为与常见文本格式高度兼容而设计:
### ✅ **兼容性极佳的格式:**
- **JSON** - 在引号字符串中完美表现(我们将 `"` 重新编码为 `ˮ`)
- **XML/HTML** - 在文本内容和属性中完美表现(我们的编码中没有 `<>&`)
- **TOML** - 在引号字符串中完美表现
- **YAML** - 在引号字符串中完美表现,在无引号上下文中表现良好
- **C/C++/Java 等** - 在字符串字面量中完美表现(我们将 `\` 重新编码为 `⧹`)
- **Shell 脚本** - 在引号字符串中完美表现(我们将 `'` 重新编码为 `ʼ`)
- **SQL** - 在引号字符串中完美表现
- **大多数支持 UTF-8 的文本格式**
### 🎯 **兼容性关键设计决策:**
- **双引号** (34) → `ˮ` (U+02EE) - 避免 JSON/XML 属性冲突
- **单引号** (39) → `ʼ` (U+02BC) - 避免 shell/SQL 冲突
- **反斜杠** (92) → `⧹` (U+29F9) - 避免转义序列问题
- **控制字符** → 安全的 Unicode 符号(·, ¶, ⏎ 等)
- 我们的特殊编码中**没有问题分隔符**
### 📝 **使用建议:**
```
# JSON
echo '{"binary_data": "'$(./bin/printable-binary file.bin)'"}'
# XML/HTML
echo ''$(./bin/printable-binary file.bin)''
# YAML
echo 'data: "'$(./bin/printable-binary file.bin)'"'
# Shell variable
DATA="$(./bin/printable-binary file.bin)"
# C string literal
printf 'char data[] = "%s";\n' "$(./bin/printable-binary file.bin)"
```
**注意:** 如果您的原始二进制数据包含有问题字符(如 `{`),它们将原样显示,因为它们是可打印的 ASCII。在嵌入结构化格式时请使用引号上下文。
## 字形选择设计哲学
替换字形的选择旨在平衡三个相互竞争的目标:
1. **字节经济性** - 尽可能优先选择较短的 UTF-8 序列(1-2 字节)以最小化编码开销。大多数可打印 ASCII 以 1:1 通过,因此文本密集的数据扩展最小;纯随机二进制数据平均约为 1.85 倍。
2. **视觉暗示** - 每个字形应暗示它所替代的内容。例如:
- `␣` (开放方框) 代表空格 - 清楚地表示“这里有一个空格”
- `⏎` 代表回车 - 通用的“返回/回车”符号
- `⇥` 代表制表符 - 指向条形的箭头暗示制表
- `˂˃` 代表尖括号 - 形状相似,明显相关
3. **明确区分** - 字形**不得**与原始字符混淆。这解释了如下选择:
- `ˮ` 代表双引号 - 修饰字母双撇号,视觉上形象且只有 2 字节
- `ʼ` 代表单引号 - 修饰字母撇号看起来相似但明显不同
- `⧷` 代表反斜杠 - 中间带有一条水平线
**高字节排序 (0x80-0xFF):** 扩展字节映射大致按词法顺序排列 - 它们以 A 的变体(ă, Ă, Ǎ...)开始,以 Z 的变体(ź, Ź, ž, Ž, ż, Ż)结束。这允许开发人员只需瞥一眼字形的基本字母,就能大致猜测所表示的字节值。
## 字符编码
- **控制字符 (0-31)**:映射到视觉上独特的符号,如 ·, ¯, «, », µ 等。
- **空格 (32)**:编码为 ␣ 以提高可见性
- **Shell 不安全的 ASCII 字符**:映射到安全的 Unicode 替代方案:
- 感叹号 (33) → ﹗ (U+FE57) 小型感叹号
- 双引号 (34) → ˮ (U+02EE) 修饰字母双撇号
- 井号 (35) → ♯ (U+266F) 音乐升号
- 美元符号 (36) → ﹩ (U+FE69) 小型美元符号
- 百分号 (37) → ﹪ (U+FE6A) 小型百分号
- & 号 (38) → ⅋ (U+214B) 翻转的 & 号
- 单引号 (39) → ʼ (U+02BC) 修饰字母撇号
- 圆括号 (40-41) → ❨❩ (U+2768-2769) 中型圆括号装饰符
- 星号 (42) → ﹡ (U+FE61) 小型星号
- 加号 (43) → ﹢ (U+FE62) 小型加号
- 减号 (45) → ﹣ (U+FE63) 小型连字符减号
- 斜杠 (47) → ⁄ (U+2044) 分数斜线
- 冒号 (58) → ꞉ (U+A789) 修饰字母冒号
- 分号 (59) → ; (U+037E) 希腊问号
- 等号 (61) → ꞊ (U+A78A) 修饰字母短等号
- 问号 (63) → Ɂ (U+0241) 拉丁大写字母声门塞音
- @ 符号 (64) → @ (U+0040) 商业符号
- 反斜杠 (92) → ⧷ (U+29F7) 带水平线的反斜线
- 方括号 (91, 93) → ⟦⟧ (U+27E6-27E7) 数学白色方括号
- 反引号 (96) → ˋ (U+02CB) 修饰字母重音符
- 花括号 (123-125) → ❴∣❵(装饰符和数学变体)
- 波浪号 (126) → ˜ (U+02DC) 小型波浪号
- **DEL (127)**:编码为 ⌦
- **扩展字节 (128-255)**:直接取自 `character_map.txt` 并按字母顺序分组,以便相邻字节共享相关的字形
### 完整字符映射参考
此表根据 `character_map.txt` 生成,以确保所有实现保持同步:
| 字节 | 字符 | Unicode | UTF-8 | 名称 |
| --- | --- | --- | --- | --- |
| 0 | · | U+00B7 | C2 B7 | 中点 |
| 1 | ¯ | U+00AF | C2 AF | 长音符号 |
| 2 | « | U+00AB | C2 AB | 左双角引号 |
| 3 | » | U+00BB | C2 BB | 右双角引号 |
| 4 | ϟ | U+03DF | CF 9F | 希腊小写字母 Koppa |
| 5 | ¿ | U+00BF | C2 BF | 倒置问号 |
| 6 | ¡ | U+00A1 | C2 A1 | 倒置感叹号 |
| 7 | ª | U+00AA | C2 AA | 阴性序数标识符 |
| 8 | ⌫ | U+232B | E2 8C AB | 向左擦除 |
| 9 | ⇥ | U+21E5 | E2 87 A5 | 右向条形箭头 |
| 10 | ¶ | U+00B6 | C2 B6 | 段落符号 |
| 11 | ↧ | U+21A7 | E2 86 A7 | 从条形向下的箭头 |
| 12 | § | U+00A7 | C2 A7 | 分节符号 |
| 13 | ⏎ | U+23CE | E2 8F 8E | 返回符号 |
| 14 | ȯ | U+022F | C8 AF | 带上点的拉丁小写字母 O |
| 15 | ʘ | U+0298 | CA 98 | 拉丁字母双唇搭嘴音 |
| 16 | Ɣ | U+0194 | C6 94 | 拉丁大写字母 Gamma |
| 17 | ¹ | U+00B9 | C2 B9 | 上标一 |
| 18 | ² | U+00B2 | C2 B2 | 上标二 |
| 19 | º | U+00BA | C2 BA | 阳性序数标识符 |
| 20 | ³ | U+00B3 | C2 B3 | 上标三 |
| 21 | µ | U+00B5 | C2 B5 | 微符号 |
| 22 | ɨ | U+0268 | C9 A8 | 带笔划的拉丁小写字母 I |
| 23 | ⏹ | U+23F9 | E2 8F B9 | 停止用黑方块 |
| 24 | © | U+00A9 | C2 A9 | 版权符号 |
| 25 | ¦ | U+00A6 | C2 A6 | 断竖线 |
| 26 | Ƶ | U+01B5 | C6 B5 | 带笔划的拉丁大写字母 Z |
| 27 | ⎋ | U+238B | E2 8E 8B | 带西北箭头的断裂圆圈 |
| 28 | Ξ | U+039E | CE 9E | 希腊大写字母 Xi |
| 29 | ǁ | U+01C1 | C7 81 | 拉丁字母边搭嘴音 |
| 30 | ǀ | U+01C0 | C7 80 | 拉丁字母齿搭嘴音 |
| 31 | ¬ | U+00AC | C2 AC | 否定符号 |
| 32 | ␣ | U+2423 | E2 90 A3 | 开方框 |
| 33 | ǃ | U+01C3 | C7 83 | 拉丁字母卷舌搭嘴音 |
| 34 | ˮ | U+02EE | CB AE | 修饰字母双撇号 |
| 35 | ♯ | U+266F | E2 99 AF | 音乐升号 |
| 36 | Ꞩ | U+A7A8 | EA 9E A8 | 带斜笔划的拉丁大写字母 S |
| 37 | ‰ | U+2030 | E2 80 B0 | 千分号 |
| 38 | ⅋ | U+214B | E2 85 8B | 翻转的 & 号 |
| 39 | ʼ | U+02BC | CA BC | 修饰字母撇号 |
| 40 | ❨ | U+2768 | E2 9D A8 | 中型左圆括号装饰符 |
| 41 | ❩ | U+2769 | E2 9D A9 | 中型右圆括号装饰符 |
| 42 | ⁎ | U+204E | E2 81 8E | 低位星号 |
| 43 | ⨦ | U+2A26 | E2 A8 A6 | 带下波浪线的加号 |
| 44 | , | U+002C | 2C | 逗号 |
| 45 | ˗ | U+02D7 | CB 97 | 修饰字母减号 |
| 46 | . | U+002E | 2E | 句号 |
| 47 | ⁄ | U+2044 | E2 81 84 | 分数斜线 |
| 48 | 0 | U+0030 | 30 | 数字零 |
| 49 | 1 | U+0031 | 31 | 数字一 |
| 50 | 2 | U+0032 | 32 | 数字二 |
| 51 | 3 | U+0033 | 33 | 数字三 |
| 52 | 4 | U+0034 | 34 | 数字四 |
| 53 | 5 | U+0035 | 35 | 数字五 |
| 54 | 6 | U+0036 | 36 | 数字六 |
| 55 | 7 | U+0037 | 37 | 数字七 |
| 56 | 8 | U+0038 | 38 | 数字八 |
| 57 | 9 | U+0039 | 39 | 数字九 |
| 58 | ꞉ | U+A789 | EA 9E 89 | 修饰字母冒号 |
| 59 | ; | U+037E | CD BE | 希腊问号 |
| 60 | ˂ | U+02C2 | 3C | 修饰字母左箭头 |
| 61 | ꞊ | U+A78A | EA 9E 8A | 修饰字母短等号 |
| 62 | ˃ | U+02C3 | 3E | 修饰字母右箭头 |
| 63 | Ɂ | U+0241 | C9 81 | 拉丁大写字母声门塞音 |
| 64 | @ | U+0040 | 40 | 商业符号 |
| 65 | A | U+0041 | 41 | 拉丁大写字母 A |
| 66 | B | U+0042 | 42 | 拉丁大写字母 B |
| 67 | C | U+0043 | 43 | 拉丁大写字母 C |
| 68 | D | U+0044 | 44 | 拉丁大写字母 D |
| 69 | E | U+0045 | 45 | 母 E |
| 70 | F | U+0046 | 46 | 拉丁大写字母 F |
| 71 | G | U+0047 | 47 | 拉丁大写字母 G |
| 72 | H | U+0048 | 48 | 拉丁大写字母 H |
| 73 | I | U+0049 | 49 | 拉丁大写字母 I |
| 74 | J | U+004A | 4A | 拉丁大写字母 J |
| 75 | K | U+004B | 4B | 拉丁大写字母 K |
| 76 | L | U+004C | 4C | 拉丁大写字母 L |
| 77 | M | U+004D | 4D | 拉丁大写字母 M |
| 78 | N | U+004E | 4E | 拉丁大写字母 N |
| 79 | O | U+004F | 4F | 拉丁大写字母 O |
| 80 | P | U+0050 | 50 | 拉丁大写字母 P |
| 81 | Q | U+0051 | 51 | 拉丁大写字母 Q |
| 82 | R | U+0052 | 52 | 拉丁大写字母 R |
| 83 | S | U+0053 | 53 | 拉丁大写字母 S |
| 84 | T | U+0054 | 54 | 拉丁大写字母 T |
| 85 | U | U+0055 | 55 | 拉丁大写字母 U |
| 86 | V | U+0056 | 56 | 拉丁大写字母 V |
| 87 | W | U+0057 | 57 | 拉丁大写字母 W |
| 88 | X | U+0058 | 58 | 拉丁大写字母 X |
| 89 | Y | U+0059 | 59 | 拉丁大写字母 Y |
| 90 | Z | U+005A | 5A | 拉丁大写字母 Z |
| 91 | ⟦ | U+27E6 | E2 9F A6 | 数学左白色方括号 |
| 92 | ⧷ | U+29F7 | E2 A7 B7 | 带水平线的反斜线 |
| 93 | ⟧ | U+27E7 | E2 9F A7 | 数学右白色方括号 |
| 94 | ^ | U+005E | 5E | 抑扬音符 |
| 95 | _ | U+005F | 5F | 下划线 |
| 96 | ˋ | U+02CB | CB 8B | 修饰字母重音符 |
| 97 | a | U+0061 | 61 | 拉丁小写字母 A |
| 98 | b | U+0062 | 62 | 拉丁小写字母 B |
| 99 | c | U+0063 | 63 | 拉丁小写字母 C |
| 100 | d | U+0064 | 64 | 拉丁小写字母 D |
| 101 | e | U+0065 | 65 | 拉丁小写字母 E |
| 102 | f | U+0066 | 66 | 拉丁小写字母 F |
| 103 | g | U+0067 | 67 | 拉丁小写字母 G |
| 104 | h | U+0068 | 68 | 拉丁小写字母 H |
| 105 | i | U+0069 | 69 | 拉丁小写字母 I |
| 106 | j | U+006A | 6A | 拉丁小写字母 J |
| 107 | k | U+006B | 6B | 拉丁小写字母 K |
| 108 | l | U+006C | 6C | 拉丁小写字母 L |
| 109 | m | U+006D | 6D | 拉丁小写字母 M |
| 110 | n | U+006E | 6E | 拉丁小写字母 N |
| 111 | o | U+006F | 6F | 拉丁小写字母 O |
| 112 | p | U+0070 | 70 | 拉丁小写字母 P |
| 113 | q | U+0071 | 71 | 拉丁小写字母 Q |
| 114 | r | U+0072 | 72 | 拉丁小写字母 R |
| 115 | s | U+0073 | 73 | 拉丁小写字母 S |
| 116 | t | U+0074 | 74 | 拉丁小写字母 T |
| 117 | u | U+0075 | 75 | 拉丁小写字母 U |
| 118 | v | U+0076 | 76 | 拉丁小写字母 V |
| 119 | w | U+0077 | 77 | 拉丁小写字母 W |
| 120 | x | U+0078 | 78 | 拉丁小写字母 X |
| 121 | y | U+0079 | 79 | 拉丁小写字母 Y |
| 122 | z | U+007A | 7A | 拉丁小写字母 Z |
| 123 | ❴ | U+2774 | E2 9D B4 | 中型左花括号装饰符 |
| 124 | ∣ | U+2223 | E2 88 A3 | 除号 |
| 125 | ❵ | U+2775 | E2 9D B5 | 中型右花括号装饰符 |
| 126 | ˜ | U+02DC | CB 9C | 小型波浪号 |
| 127 | ⌦ | U+2326 | E2 8C A6 | 向右擦除 |
| 128 | ă | U+0103 | C4 83 | 带短音符号的拉丁小写字母 A |
| 129 | Ă | U+0102 | C4 82 | 带短音符号的拉丁大写字母 A |
| 130 | Ǎ | U+01CD | C7 8D | 带抑扬符号的拉丁大写字母 A |
| 131 | ǟ | U+01DF | C7 9F | 带分音符和长音符号的拉丁小写字母 A |
| 132 | Ǟ | U+01DE | C7 9E | 带分音符和长音符号的拉丁大写字母 A |
| 133 | ȧ | U+0227 | C8 A7 | 带上点的拉丁小写字母 A |
| 134 | Ȧ | U+0226 | C8 A6 | 带上点的拉丁大写字母 A |
| 135 | ǡ | U+01E1 | C7 A1 | 带上点和长音符号的拉丁小写字母 A |
| 136 | ƀ | U+0180 | C6 80 | 带笔划的拉丁小写字母 B |
| 137 | Ƀ | U+0243 | C9 83 | 带笔划的拉丁大写字母 B |
| 138 | Ɓ | U+0181 | C6 81 | 带钩的拉丁大写字母 B |
| 139 | ƃ | U+0183 | C6 83 | 带顶条的拉丁小写字母 B |
| 140 | Ƃ | U+0182 | C6 82 | 带顶条的拉丁大写字母 B |
| 141 | ć | U+0107 | C4 87 | 带尖音符号的拉丁小写字母 C |
| 142 | Ć | U+0106 | C4 86 | 带尖音符号的拉丁大写字母 C |
| 143 | ĉ | U+0109 | C4 89 | 带抑扬符号的拉丁小写字母 C |
| 144 | Ĉ | U+0108 | C4 88 | 带抑扬符号的拉丁大写字母 C |
| 145 | č | U+010D | C4 8D | 带抑扬符号的拉丁小写字母 C |
| 146 | Č | U+010C | C4 8C | 带抑扬符号的拉丁大写字母 C |
| 147 | ċ | U+010B | C4 8B | 带上点的拉丁小写字母 C |
| 148 | Ċ | U+010A | C4 8A | 带上点的拉丁大写字母 C |
| 149 | ď | U+010F | C4 8F | 带抑扬符号的拉丁小写字母 D |
| 150 | Ď | U+010E | C4 8E | 带抑扬符号的拉丁大写字母 D |
| 151 | Đ | U+0110 | C4 90 | 带笔划的拉丁大写字母 D |
| 152 | ȸ | U+0238 | C8 B8 | 拉丁小写字母 Db 双字母 |
| 153 | Ɗ | U+018A | C6 8A | 带钩的拉丁大写字母 D |
| 154 | ƌ | U+018C | C6 8C | 带顶条的拉丁小写字母 D |
| 155 | Ƌ | U+018B | C6 8B | 带顶条的拉丁大写字母 D |
| 156 | ȡ | U+0221 | C8 A1 | 带卷曲的拉丁小写字母 D |
| 157 | ĕ | U+0115 | C4 95 | 带短音符号的拉丁小写字母 E |
| 158 | Ĕ | U+0114 | C4 94 | 带短音符号的拉丁大写字母 E |
| 159 | Ě | U+011A | C4 9A | 带抑扬符号的拉丁大写字母 E |
| 160 | ė | U+0117 | C4 97 | 带上点的拉丁小写字母 E |
| 161 | ȩ | U+0229 | C8 A9 | 带下加符的拉丁小写字母 E |
| 162 | Ȩ | U+0228 | C8 A8 | 带下加符的拉丁大写字母 E |
| 163 | ƒ | U+0192 | C6 92 | 带钩的拉丁小写字母 F |
| 164 | Ƒ | U+0191 | C6 91 | 带钩的拉丁大写字母 F |
| 165 | ǵ | U+01F5 | C7 B5 | 带尖音符号的拉丁小写字母 G |
| 166 | Ǵ | U+01F4 | C7 B4 | 带尖音符号的拉丁大写字母 G |
| 167 | ğ | U+011F | C4 9F | 带短音符号的拉丁小写字母 G |
| 168 | Ğ | U+011E | C4 9E | 带短音符号的拉丁大写字母 G |
| 169 | ǧ | U+01E7 | C7 A7 | 带抑扬符号的拉丁小写字母 G |
| 170 | Ǧ | U+01E6 | C7 A6 | 带抑扬符号的拉丁大写字母 G |
| 171 | ḡ | U+1E21 | E1 B8 A1 | 带长音符号的拉丁小写字母 G |
| 172 | Ḡ | U+1E20 | E1 B8 A0 | 带长音符号的拉丁大写字母 G |
| 173 | ĥ | U+0125 | C4 A5 | 带抑扬符号的拉丁小写字母 H |
| 174 | Ĥ | U+0124 | C4 A4 | 带抑扬符号的拉丁大写字母 H |
| 175 | ȟ | U+021F | C8 9F | 带抑扬符号的拉丁小写字母 H |
| 176 | Ȟ | U+021E | C8 9E | 带抑扬符号的拉丁大写字母 H |
| 177 | ƕ | U+0195 | C6 95 | 拉丁小写字母 Hv |
| 178 | Ƕ | U+01F6 | C7 B6 | 拉丁大写字母 Hwair |
| 179 | ĭ | U+012D | C4 AD | 带短音符号的拉丁小写字母 I |
| 180 | Ĭ | U+012C | C4 AC | 带短音符号的拉丁大写字母 I |
| 181 | Ǐ | U+01CF | C7 8F | 带抑扬符号的拉丁大写字母 I |
| 182 | İ | U+0130 | C4 B0 | 带上点的拉丁大写字母 I |
| 183 | ȉ | U+0209 | C8 89 | 带双沉音符号的拉丁小写字母 I |
| 184 | ȋ | U+020B | C8 8B | 带倒短音符号的拉丁小写字母 I |
| 185 | ĵ | U+0135 | C4 B5 | 带抑扬符号的拉丁小写字母 J |
| 186 | Ĵ | U+0134 | C4 B4 | 带抑扬符号的拉丁大写字母 J |
| 187 | ǰ | U+01F0 | C7 B0 | 带抑扬符号的拉丁小写字母 J |
| 188 | ǩ | U+01E9 | C7 A9 | 带抑扬符号的拉丁小写字母 K |
| 189 | Ǩ | U+01E8 | C7 A8 | 带抑扬符号的拉丁大写字母 K |
| 190 | ķ | U+0137 | C4 B7 | 带下加符的拉丁小写字母 K |
| 191 | Ķ | U+0136 | C4 B6 | 带下加符的拉丁大写字母 K |
| 192 | ƙ | U+0199 | C6 99 | 带钩的拉丁小写字母 K |
| 193 | Ƙ | U+0198 | C6 98 | 带钩的拉丁大写字母 K |
| 194 | ĺ | U+013A | C4 BA | 带尖音符号的拉丁小写字母 L |
| 195 | Ĺ | U+0139 | C4 B9 | 带尖音符号的拉丁大写字母 L |
| 196 | ľ | U+013E | C4 BE | 带抑扬符号的拉丁小写字母 L |
| 197 | Ľ | U+013D | C4 BD | 带抑扬符号的拉丁大写字母 L |
| 198 | ƚ | U+019A | C6 9A | 带笔划的拉丁小写字母 L |
| 199 | Ƚ | U+023D | C8 BD | 带笔划的拉丁大写字母 L |
| 200 | Ń | U+0143 | C5 83 | 带尖音符号的拉丁大写字母 N |
| 201 | ǹ | U+01F9 | C7 B9 | 带沉音符号的拉丁小写字母 N |
| 202 | Ň | U+0147 | C5 87 | 带抑扬符号的拉丁大写字母 N |
| 203 | ņ | U+0146 | C5 86 | 带下加符的拉丁小写字母 N |
| 204 | Ņ | U+0145 | C5 85 | 带下加符的拉丁大写字母 N |
| 205 | ȵ | U+0235 | C8 B5 | 带卷曲的拉丁小写字母 N |
| 206 | ŏ | U+014F | C5 8F | 带短音符号的拉丁小写字母 O |
| 207 | Ŏ | U+014E | C5 8E | 带短音符号的拉丁大写字母 O |
| 208 | Ǒ | U+01D1 | C7 91 | 带抑扬符号的拉丁大写字母 O |
| 209 | ȫ | U+022B | C8 AB | 带分音符和长音符号的拉丁小写字母 O |
| 210 | Ȫ | U+022A | C8 AA | 带分音符和长音符号的拉丁大写字母 O |
| 211 | ȱ | U+0231 | C8 B1 | 带上点和长音符号的拉丁小写字母 O |
| 212 | ƥ | U+01A5 | C6 A5 | 带钩的拉丁小写字母 P |
| 213 | Ƥ | U+01A4 | C6 A4 | 带钩的拉丁大写字母 P |
| 214 | ȹ | U+0239 | C8 B9 | 拉丁小写字母 Qp 双字母 |
| 215 | ɋ | U+024B | C9 8B | 带钩尾的拉丁小写字母 Q |
| 216 | ŕ | U+0155 | C5 95 | 带尖音符号的拉丁小写字母 R |
| 217 | Ŕ | U+0154 | C5 94 | 带尖音符号的拉丁大写字母 R |
| 218 | ř | U+0159 | C5 99 | 带抑扬符号的拉丁小写字母 R |
| 219 | Ř | U+0158 | C5 98 | 带抑扬符号的拉丁大写字母 R |
| 220 | ŗ | U+0157 | C5 97 | 带下加符的拉丁小写字母 R |
| 221 | Ŗ | U+0156 | C5 96 | 带下加符的拉丁大写字母 R |
| 222 | ś | U+015B | C5 9B | 带尖音符号的拉丁小写字母 S |
| 223 | Ś | U+015A | C5 9A | 带尖音符号的拉丁大写字母 S |
| 224 | š | U+0161 | C5 A1 | 带抑扬符号的拉丁小写字母 S |
| 225 | Š | U+0160 | C5 A0 | 带抑扬符号的拉丁大写字母 S |
| 226 | ş | U+015F | C5 9F | 带下加符的拉丁小写字母 S |
| 227 | Ş | U+015E | C5 9E | 带下加符的拉丁大写字母 S |
| 228 | ť | U+0165 | C5 A5 | 带抑扬符号的拉丁小写字母 T |
| 229 | Ť | U+0164 | C5 A4 | 带抑扬符号的拉丁大写字母 T |
| 230 | ţ | U+0163 | C5 A3 | 带下加符的拉丁小写字母 T |
| 231 | Ţ | U+0162 | C5 A2 | 带下加符的拉丁大写字母 T |
| 232 | ț | U+021B | C8 9B | 带下逗号的拉丁小写字母 T |
| 233 | Ț | U+021A | C8 9A | 带下逗号的拉丁大写字母 T |
| 234 | ŭ | U+016D | C5 AD | 带短音符号的拉丁小写字母 U |
| 235 | Ŭ | U+016C | C5 AC | 带短音符号的拉丁大写字母 U |
| 236 | Ǔ | U+01D3 | C7 93 | 带抑扬符号的拉丁大写字母 U |
| 237 | ű | U+0171 | C5 B1 | 带双尖音符号的拉丁小写字母 U |
| 238 | ȕ | U+0215 | C8 95 | 带双沉音符号的拉丁小写字母 U |
| 239 | Ʉ | U+0244 | C9 84 | 拉丁大写字母 U Bar |
| 240 | Ṿ | U+1E7E | E1 B9 BE | 带下点的拉丁大写字母 V |
| 241 | Ʋ | U+01B2 | C6 B2 | 带钩的拉丁大写字母 V |
| 242 | ŵ | U+0175 | C5 B5 | 带抑扬符号的拉丁小写字母 W |
| 243 | Ŵ | U+0174 | C5 B4 | 带抑扬符号的拉丁大写字母 W |
| 244 | ŷ | U+0177 | C5 B7 | 带抑扬符号的拉丁小写字母 Y |
| 245 | Ŷ | U+0176 | C5 B6 | 带抑扬符号的拉丁大写字母 Y |
| 246 | Ÿ | U+0178 | C5 B8 | 带分音符的拉丁大写字母 Y |
| 247 | ȳ | U+0233 | C8 B3 | 带长音符号的拉丁小写字母 Y |
| 248 | ƴ | U+01B4 | C6 B4 | 带钩的拉丁小写字母 Y |
| 249 | Ƴ | U+01B3 | C6 B3 | 带钩的拉丁大写字母 Y |
| 250 | ź | U+017A | C5 BA | 带尖音符号的拉丁小写字母 Z |
| 251 | Ź | U+0179 | C5 B9 | 带尖音符号的拉丁大写字母 Z |
| 252 | ž | U+017E | C5 BE | 带抑扬符号的拉丁小写字母 Z |
| 253 | Ž | U+017D | C5 BD | 带抑扬符号的拉丁大写字母 Z |
| 254 | ż | U+017C | C5 BC | 带上点的拉丁小写字母 Z |
| 255 | Ż | U+017B | C5 BB | 带上点的拉丁大写字母 Z |
此实现使用一组精心选择的 UTF-8 字符来表示每个可能的字节值:
- 控制字符 (0-31) 使用视觉上独特的符号,主要来自数学符号、箭头和拉丁文扩展等 Unicode 区块
- 标准可打印 ASCII 字符 (33-126, 除 ", ', 和 \\ 外) 保持原样
- 特殊字符(空格、双引号、单引号、反斜杠)获得更可见的表示形式
- 扩展字节 (128-255) 由 `character_map.txt` 驱动,并按字母顺序排列,以使相邻字形在视觉上相关
### 编码/解码映射表
实现会在初始化时构建两个查找表:
- `encode_map`:将字节值 (0-255) 映射到它们的 UTF-8 字符串表示形式
- `decode_map`:将 UTF-8 字符串表示形式映射回字节值
这些双向映射确保了两个方向上高效且准确的转换。
## 许可证
本项目采用 MIT 许可证 - 详情请参阅 LICENSE 文件。
标签:ASCII, CMS安全, GNU通用公共许可证, JavaScript, LuaJIT, MITM代理, Node.js, UTF-8, WebAssembly, Zig, 二进制数据, 二进制编码, 人类可读, 反序列化器, 客户端加密, 序列化器, 拖放界面, 数据共享, 数据可视化, 数据序列化, 数据编码工具, 日志, 终端兼容, 编码, 解码