目录

📚 引言
❓ 什么是 text_encoding4cj?
text_encoding4cj 是一个专为仓颉编程语言设计的文本编码/解码库,提供了 TextEncoder 和 TextDecoder API,用于将字符串编码为字节数组或将字节数组解码为字符串。本库遵循 Web 标准的 TextEncoder/TextDecoder API 规范,支持 30+ 种字符编码格式。
💡 为什么需要 text_encoding4cj?
在实际开发中,我们经常需要处理不同编码格式的文本数据:
- 📁 文件处理:读取不同编码格式的文本文件
- 🌐 网络通信:处理来自不同系统的网络数据
- 📊 数据解析:解析包含多语言字符的配置文件
- 🔄 数据转换:在不同编码格式之间转换数据
text_encoding4cj 库提供了统一的 API,让这些操作变得简单高效。
✅ 支持的编码格式
本库支持以下编码格式:
- 🌍 Unicode 系列:UTF-8、UTF-16BE、UTF-16LE
- 📝 ISO-8859 系列:ISO-8859-1 到 ISO-8859-16
- 🪟 Windows 代码页:windows-1250 到 windows-1258、windows-874
- 🇨🇳 中文编码:Big5、GBK(部分支持)
- 🇯🇵 日文编码:Shift_JIS
- 🔧 特殊编码:x-user-defined
🚀 快速开始
📦 安装
在项目的 cjpm.toml 文件中添加依赖:
[dependencies]
text_encoding4cj = "1.0.0"
然后运行:
cjpm update
cjpm build
💻 第一个示例
让我们从一个简单的例子开始:
import text_encoding4cj.*
main() {
// 创建编码器(默认UTF-8)
let encoder = TextEncoder(None, None)
let text = "Hello, 世界!"
// 编码字符串为字节数组
let encoded = encoder.encode(Some(text), None)
println("编码后的字节数: " + encoded.size.toString())
// 创建解码器
let decoder = TextDecoder(None, None)
// 解码字节数组为字符串
let decoded = decoder.decode(Some(encoded), None)
println("解码后的文本: " + decoded)
// 验证往返转换
if (decoded == text) {
println("✓ 编码解码成功!")
}
}
输出结果:
编码后的字节数: 17
解码后的文本: Hello, 世界!
✓ 编码解码成功!
🎯 基础使用
1️⃣ 基本编码和解码
📌 使用 UTF-8 编码(默认)
import text_encoding4cj.*
main() {
// 方式1:使用默认编码(UTF-8)
let encoder = TextEncoder(None, None)
let decoder = TextDecoder(None, None)
// 方式2:显式指定UTF-8编码
let encoder2 = TextEncoder(Some("utf-8"), None)
let decoder2 = TextDecoder(Some("utf-8"), None)
let text = "Hello, 世界!🌍"
let encoded = encoder.encode(Some(text), None)
let decoded = decoder.decode(Some(encoded), None)
println("原文: " + text)
println("解码: " + decoded)
}
📌 使用其他编码格式
import text_encoding4cj.*
main() {
// UTF-16BE 编码
let encoder = TextEncoder(Some("utf-16be"), None)
let decoder = TextDecoder(Some("utf-16be"), None)
let text = "Hello"
let encoded = encoder.encode(Some(text), None)
let decoded = decoder.decode(Some(encoded), None)
println("UTF-16BE编码: " + encoded.size.toString() + " 字节")
println("解码结果: " + decoded)
}
2️⃣ 查看编码器属性
import text_encoding4cj.*
main() {
let encoder = TextEncoder(Some("utf-8"), None)
let decoder = TextDecoder(Some("utf-8"), None)
// 获取编码名称
println("编码器编码: " + encoder.getEncoding()) // 输出: utf-8
println("解码器编码: " + decoder.getEncoding()) // 输出: utf-8
// 获取解码器属性
println("Fatal模式: " + decoder.isFatal().toString()) // 输出: false
println("忽略BOM: " + decoder.getIgnoreBOM().toString()) // 输出: false
}
3️⃣ 处理不同语言的文本
import text_encoding4cj.*
main() {
// 测试用例:各种语言的文本
let testCases = [
("UTF-8", "utf-8", "Hello, 世界!🌍"),
("UTF-16BE", "utf-16be", "Hello"),
("ISO-8859-1", "iso-8859-1", "Café"),
("Big5", "big5", "Hello"),
("Shift_JIS", "shift_jis", "Hello")
]
for ((name, encoding, text) in testCases) {
let encoder = TextEncoder(Some(encoding), None)
let decoder = TextDecoder(Some(encoding), None)
let encoded = encoder.encode(Some(text), None)
let decoded = decoder.decode(Some(encoded), None)
if (decoded == text) {
println("✓ " + name + ": 编码解码成功")
} else {
println("✗ " + name + ": 编码解码失败")
}
}
}
🚀 高级功能
1️⃣ 流式处理
流式处理适用于处理大文件或网络数据流,可以分块处理数据而不需要一次性加载到内存中。
📌 流式解码示例
import text_encoding4cj.*
main() {
let encoder = TextEncoder(Some("utf-8"), None)
let fullText = "Hello, World! 这是一个测试文本。"
let encoded = encoder.encode(Some(fullText), None)
// 创建解码器
let decoder = TextDecoder(Some("utf-8"), None)
// 模拟分块接收数据
let chunkSize = 5
var offset = 0
var decodedText = ""
// 流式解码选项
let streamOpts = DecodeOptions()
streamOpts.stream = true
// 分块解码
while (offset < encoded.size) {
let remaining = encoded.size - offset
let currentChunkSize = if (remaining < chunkSize) { remaining } else { chunkSize }
// 构建当前块
let chunk = Array<Int64>(currentChunkSize, {i => encoded[offset + i]})
// 解码当前块(流模式)
decodedText = decodedText + decoder.decode(Some(chunk), Some(streamOpts))
offset = offset + currentChunkSize
}
// 完成流(刷新缓冲区)
let finalOpts = DecodeOptions()
finalOpts.stream = false
decodedText = decodedText + decoder.decode(None, Some(finalOpts))
println("原文: " + fullText)
println("解码: " + decodedText)
println("匹配: " + (decodedText == fullText).toString())
}
📌 流式编码示例
import text_encoding4cj.*
main() {
let encoder = TextEncoder(Some("utf-8"), None)
// 流式编码选项
let streamOpts = EncodeOptions()
streamOpts.stream = true
// 分块编码
let chunk1 = "Hello, "
let chunk2 = "World!"
let encoded1 = encoder.encode(Some(chunk1), Some(streamOpts))
let encoded2 = encoder.encode(Some(chunk2), Some(streamOpts))
// 完成流
streamOpts.stream = false
let finalEncoded = encoder.encode(None, Some(streamOpts))
// 合并所有编码结果
let allEncoded = ArrayList<Int64>()
allEncoded.add(all: encoded1)
allEncoded.add(all: encoded2)
// 解码验证
let decoder = TextDecoder(Some("utf-8"), None)
let decoded = decoder.decode(Some(allEncoded.toArray()), None)
println("解码结果: " + decoded)
}
2️⃣ 错误处理模式
解码器支持两种错误处理模式:
- ⚠️ replacement 模式(默认):遇到无效字节序列时使用替换字符(U+FFFD)
- ❌ fatal 模式:遇到无效字节序列时返回错误(目前实现为返回替换字符)
import text_encoding4cj.*
main() {
// 创建包含无效UTF-8序列的字节数组
let invalidBytes = [0xFF, 0xFE, 0xFD] // 无效的UTF-8序列
// 1. 使用默认模式(replacement)
let decoder1 = TextDecoder(Some("utf-8"), None)
let decoded1 = decoder1.decode(Some(invalidBytes), None)
println("Replacement模式解码: " + decoded1)
// 输出会包含替换字符(U+FFFD)
// 2. 使用fatal模式
let opts = DecodeOptions()
opts.fatal = true
let decoder2 = TextDecoder(Some("utf-8"), Some(opts))
let decoded2 = decoder2.decode(Some(invalidBytes), None)
println("Fatal模式解码: " + decoded2)
println("Fatal模式: " + decoder2.isFatal().toString())
}
3️⃣ BOM(字节顺序标记)处理
BOM 是 UTF-8 和 UTF-16 编码中用于标识字节顺序的标记。解码器默认会自动处理并移除 BOM。
import text_encoding4cj.*
main() {
// UTF-8 BOM: 0xEF, 0xBB, 0xBF
let utf8BOM = [0xEF, 0xBB, 0xBF]
let utf8Text = [0x48, 0x65, 0x6C, 0x6C, 0x6F] // "Hello"
let utf8WithBOM = ArrayList<Int64>()
utf8WithBOM.add(all: utf8BOM)
utf8WithBOM.add(all: utf8Text)
// 默认处理:自动移除BOM
let decoder1 = TextDecoder(Some("utf-8"), None)
let decoded1 = decoder1.decode(Some(utf8WithBOM.toArray()), None)
println("自动处理BOM: " + decoded1) // 输出: Hello
// 忽略BOM选项:保留BOM字符
let opts = DecodeOptions()
opts.ignoreBOM = true
let decoder2 = TextDecoder(Some("utf-8"), Some(opts))
let decoded2 = decoder2.decode(Some(utf8WithBOM.toArray()), None)
println("忽略BOM: " + decoded2) // 输出可能包含BOM字符
println("忽略BOM设置: " + decoder2.getIgnoreBOM().toString())
}
4️⃣ 编码标签别名
本库支持多种编码标签别名,方便使用不同的名称指定同一编码。
import text_encoding4cj.*
main() {
// UTF-8 的多种别名
let utf8Aliases = ["utf-8", "utf8", "unicode-1-1-utf-8"]
for (alias in utf8Aliases) {
let encoder = TextEncoder(Some(alias), None)
println(alias + " -> " + encoder.getEncoding()) // 都输出: utf-8
}
// ISO-8859-1 的多种别名
let iso88591Aliases = ["iso-8859-1", "iso8859-1", "latin1", "latin-1"]
for (alias in iso88591Aliases) {
let decoder = TextDecoder(Some(alias), None)
println(alias + " -> " + decoder.getEncoding()) // 都输出: iso-8859-1
}
// Big5 的多种别名
let big5Aliases = ["big5", "big5-hkscs", "cn-big5"]
for (alias in big5Aliases) {
let encoder = TextEncoder(Some(alias), None)
println(alias + " -> " + encoder.getEncoding()) // 都输出: big5
}
}
5️⃣ 编码信息查询
import text_encoding4cj.*
main() {
// 查询编码信息
let encodingOpt = getEncoding("utf-8")
if (encodingOpt.isSome()) {
let encoding = encodingOpt.getOrThrow()
println("编码名称: " + encoding.name)
println("标签别名: " + String.join(encoding.labels, delimiter: ", "))
}
// 查询不存在的编码
let invalidOpt = getEncoding("invalid-encoding")
if (invalidOpt.isNone()) {
println("编码不存在,使用默认编码: " + DEFAULT_ENCODING)
}
}
🎬 实际应用场景
📁 场景1:读取不同编码格式的文件
假设你需要读取一个可能是不同编码格式的文本文件:
import text_encoding4cj.*
import std.collection.*
// 模拟从文件读取字节数据
func readFileAsBytes(filePath: String): Array<Int64> {
// 实际实现中,这里会从文件系统读取字节
// 这里返回模拟数据
return [0x48, 0x65, 0x6C, 0x6C, 0x6F] // "Hello" 的UTF-8编码
}
// 尝试使用不同编码格式解码文件
func decodeFileWithMultipleEncodings(bytes: Array<Int64>) {
let encodings = ["utf-8", "iso-8859-1", "windows-1252", "utf-16be"]
for (encoding in encodings) {
let decoder = TextDecoder(Some(encoding), None)
let decoded = decoder.decode(Some(bytes), None)
println("使用 " + encoding + " 解码: " + decoded)
}
}
main() {
let fileBytes = readFileAsBytes("example.txt")
decodeFileWithMultipleEncodings(fileBytes)
}
🌐 场景2:网络数据传输
处理来自不同系统的网络数据,需要转换编码格式:
import text_encoding4cj.*
// 模拟接收网络数据
func processNetworkData(data: Array<Int64>, sourceEncoding: String, targetEncoding: String): String {
// 1. 使用源编码解码
let decoder = TextDecoder(Some(sourceEncoding), None)
let text = decoder.decode(Some(data), None)
// 2. 使用目标编码重新编码
let encoder = TextEncoder(Some(targetEncoding), None)
let reencoded = encoder.encode(Some(text), None)
// 3. 使用目标编码解码验证
let targetDecoder = TextDecoder(Some(targetEncoding), None)
let finalText = targetDecoder.decode(Some(reencoded), None)
return finalText
}
main() {
// 模拟从Windows系统接收的GBK编码数据
let gbkData = [0xC4, 0xE3, 0xBA, 0xC3] // "你好" 的GBK编码(示例)
// 转换为UTF-8
let result = processNetworkData(gbkData, "gbk", "utf-8")
println("转换结果: " + result)
}
📊 场景3:处理CSV文件
处理包含多语言字符的CSV文件:
import text_encoding4cj.*
// 模拟CSV数据处理
func processCSVFile(fileBytes: Array<Int64>, encoding: String): Array<String> {
// 解码文件内容
let decoder = TextDecoder(Some(encoding), None)
let content = decoder.decode(Some(fileBytes), None)
// 简单的CSV解析(按行分割)
let lines = ArrayList<String>()
var currentLine = ""
for (ch in content) {
if (ch == '\n') {
lines.add(currentLine)
currentLine = ""
} else {
currentLine = currentLine + String(Rune(ch))
}
}
if (currentLine != "") {
lines.add(currentLine)
}
return lines.toArray()
}
main() {
// 模拟CSV文件数据(UTF-8编码)
let csvData = [0x4E, 0x61, 0x6D, 0x65, 0x2C, 0x41, 0x67, 0x65, 0x0A, // "Name,Age\n"
0xE5, 0xBC, 0xA0, 0xE4, 0xB8, 0x89, 0x2C, 0x32, 0x30, 0x0A] // "张三,20\n"
let lines = processCSVFile(csvData, "utf-8")
for (line in lines) {
println("CSV行: " + line)
}
}
📦 场景4:流式处理大文件
处理大文件时使用流式处理,避免一次性加载到内存:
import text_encoding4cj.*
// 模拟流式读取大文件
func processLargeFileStream(chunks: Array<Array<Int64>>, encoding: String): String {
let decoder = TextDecoder(Some(encoding), None)
var result = ""
// 流式解码选项
let streamOpts = DecodeOptions()
streamOpts.stream = true
// 处理每个数据块
for (chunk in chunks) {
result = result + decoder.decode(Some(chunk), Some(streamOpts))
}
// 完成流处理
streamOpts.stream = false
result = result + decoder.decode(None, Some(streamOpts))
return result
}
main() {
// 模拟大文件分成多个块
let encoder = TextEncoder(Some("utf-8"), None)
let fullText = "这是一个很长的文本,需要分成多个块来处理。" +
"这样可以避免一次性加载到内存中。" +
"适合处理大文件或网络流数据。"
let encoded = encoder.encode(Some(fullText), None)
// 分成3个块
let chunk1 = Array<Int64>(encoded.size / 3, {i => encoded[i]})
let chunk2 = Array<Int64>(encoded.size / 3, {i => encoded[i + encoded.size / 3]})
let chunk3 = Array<Int64>(encoded.size - 2 * (encoded.size / 3),
{i => encoded[i + 2 * (encoded.size / 3)]})
let chunks = [chunk1, chunk2, chunk3]
let result = processLargeFileStream(chunks, "utf-8")
println("原文长度: " + fullText.size.toString())
println("解码长度: " + result.size.toString())
println("匹配: " + (result == fullText).toString())
}
💡 最佳实践
1️⃣ 编码选择建议
- 🌍 通用场景:优先使用 UTF-8,它支持所有Unicode字符,兼容性好
- 🪟 Windows系统:处理Windows文件时,可能需要使用 windows-1252 或 windows-1251
- 🇨🇳 中文处理:简体中文使用UTF-8,繁体中文使用Big5
- 🇯🇵 日文处理:使用 Shift_JIS 或 UTF-8
2️⃣ 错误处理
import text_encoding4cj.*
func safeDecode(bytes: Array<Int64>, encoding: String): Option<String> {
let decoder = TextDecoder(Some(encoding), None)
// 尝试解码
let decoded = decoder.decode(Some(bytes), None)
// 检查是否包含替换字符(可能表示解码错误)
// 注意:这里简化处理,实际应该检查解码器状态
return Some(decoded)
}
main() {
let bytes = [0xFF, 0xFE] // 可能的无效序列
let result = safeDecode(bytes, "utf-8")
if (result.isSome()) {
let text = result.getOrThrow()
println("解码成功: " + text)
} else {
println("解码失败")
}
}
3️⃣ 性能优化
对于大量数据的处理:
import text_encoding4cj.*
// 使用流式处理避免内存峰值
func processLargeData(data: Array<Array<Int64>>, encoding: String): String {
let decoder = TextDecoder(Some(encoding), None)
let streamOpts = DecodeOptions()
streamOpts.stream = true
var result = ""
for (chunk in data) {
result = result + decoder.decode(Some(chunk), Some(streamOpts))
}
streamOpts.stream = false
result = result + decoder.decode(None, Some(streamOpts))
return result
}
// 重用编码器/解码器实例
func processMultipleTexts(texts: Array<String>, encoding: String): Array<Array<Int64>> {
let encoder = TextEncoder(Some(encoding), None)
let results = ArrayList<Array<Int64>>()
for (text in texts) {
let encoded = encoder.encode(Some(text), None)
results.add(encoded)
}
return results.toArray()
}
4️⃣ 编码检测
虽然本库不直接提供编码检测功能,但可以通过尝试多种编码来检测:
import text_encoding4cj.*
func detectEncoding(bytes: Array<Int64>): Option<String> {
// 常见的编码格式列表(按可能性排序)
let encodings = ["utf-8", "iso-8859-1", "windows-1252", "utf-16be", "utf-16le"]
for (encoding in encodings) {
let decoder = TextDecoder(Some(encoding), None)
let decoded = decoder.decode(Some(bytes), None)
// 简单检查:如果解码结果不包含太多替换字符,可能是正确编码
// 注意:这是简化实现,实际编码检测更复杂
let hasReplacement = decoded.contains("\u{FFFD}")
if (!hasReplacement) {
return Some(encoding)
}
}
return None
}
main() {
let encoder = TextEncoder(Some("utf-8"), None)
let testBytes = encoder.encode(Some("Hello, 世界!"), None)
let detected = detectEncoding(testBytes)
if (detected.isSome()) {
println("检测到的编码: " + detected.getOrThrow())
}
}
❓ 常见问题解答
❓ Q1: 如何选择合适的编码格式?
💡 A: 根据数据来源选择:
- 如果数据来自现代Web应用,通常使用 UTF-8
- 如果数据来自Windows系统,可能需要 windows-1252 或 windows-1251
- 如果数据是中文繁体,使用 Big5
- 如果不确定,先尝试 UTF-8
❓ Q2: 编码和解码后字符串不匹配怎么办?
💡 A: 检查以下几点:
- 编码和解码使用的编码格式是否一致
- 输入数据是否完整(流式处理时是否调用了最后的flush)
- 是否使用了正确的编码标签别名
// 确保编码和解码使用相同的编码格式
let encoding = "utf-8"
let encoder = TextEncoder(Some(encoding), None)
let decoder = TextDecoder(Some(encoding), None)
let text = "测试文本"
let encoded = encoder.encode(Some(text), None)
let decoded = decoder.decode(Some(encoded), None)
// 验证
if (decoded != text) {
println("警告:编码解码不匹配!")
}
❓ Q3: 如何处理无效的字节序列?
💡 A: 使用适当的错误处理模式:
// 使用 replacement 模式(默认):自动替换无效字符
let decoder1 = TextDecoder(Some("utf-8"), None)
// 使用 fatal 模式:在遇到错误时返回错误(当前实现返回替换字符)
let opts = DecodeOptions()
opts.fatal = true
let decoder2 = TextDecoder(Some("utf-8"), Some(opts))
❓ Q4: 流式处理时数据不完整怎么办?
💡 A: 确保在流式处理的最后调用 flush:
// 流式处理模式
let streamOpts = DecodeOptions()
streamOpts.stream = true
// 处理数据块
let decoded1 = decoder.decode(Some(chunk1), Some(streamOpts))
let decoded2 = decoder.decode(Some(chunk2), Some(streamOpts))
// 重要:最后必须调用 flush
streamOpts.stream = false
let finalDecoded = decoder.decode(None, Some(streamOpts))
let complete = decoded1 + decoded2 + finalDecoded
❓ Q5: 如何检查编码是否支持?
💡 A: 使用 getEncoding 函数:
let encodingOpt = getEncoding("utf-8")
if (encodingOpt.isSome()) {
let encoding = encodingOpt.getOrThrow()
println("编码支持: " + encoding.name)
} else {
println("编码不支持,使用默认编码")
}
❓ Q6: 性能如何优化?
💡 A:
- ♻️ 重用编码器/解码器实例:避免频繁创建新实例
- 🌊 使用流式处理:处理大文件时分块处理
- ⚡ 选择合适的编码:UTF-8通常是性能最好的选择
// 好的做法:重用实例
let encoder = TextEncoder(Some("utf-8"), None)
for (text in texts) {
let encoded = encoder.encode(Some(text), None)
// 处理编码结果
}
// 避免的做法:每次都创建新实例
for (text in texts) {
let encoder = TextEncoder(Some("utf-8"), None) // 不推荐
let encoded = encoder.encode(Some(text), None)
}
📝 总结
text_encoding4cj 库为仓颉语言提供了强大的文本编码/解码功能。通过本教程,你应该能够:
- ✅ 理解库的基本概念和用途
- ✅ 掌握基本的编码/解码操作
- ✅ 使用高级功能(流式处理、错误处理等)
- ✅ 在实际项目中应用这些功能
- ✅ 遵循最佳实践,编写高效的代码
21万+

被折叠的 条评论
为什么被折叠?



