ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Nodejs 进阶:服务端字符编解码与乱码处理实战指南

Nodejs 进阶:服务端字符编解码与乱码处理实战指南 文档教程后端【免费下载链接】nodejs-learning-guideNodejs学习笔记以及经验总结公众号程序猿小卡项目地址https://gitcode.com/gh_mirrors/no/nodejs-learning-guide点击查看免费下载导读本指南以 nodejs-learning-guide 进阶篇中的服务端字符编解码与乱码处理为核心系统讲解字符集与字符编码的基础概念并结合仓库内 examples/2017.09.03-charset-enc-dec 目录下的可运行示例演示如何使用iconv-lite在 Node.js 中完成 GBK/UTF-8 等编码的编解码转换。读完本文你将理解乱码产生的根本原因掌握网络请求场景下服务端正确解码客户端数据、避免乱码的完整实战方案。写在前面为什么 Node 开发总是遇到乱码在 Web 服务端开发中字符的编解码几乎每天都要打交道。编解码一旦处理不当就会出现令人头疼的乱码问题。不少从事 Node 服务端开发的同学由于对字符编码相关知识了解不足遇到问题时经常会一筹莫展花大量时间在排查、解决问题。本文先对字符编解码的基础知识进行简单介绍然后举例说明如何在 Node 中进行编解码最后给出服务端的完整代码案例。文中涉及的全部示例代码均可在仓库的 examples/2017.09.03-charset-enc-dec 目录中找到。关于字符编解码传输的本质是二进制在网络通信过程中传输的都是二进制的比特位不管发送的内容是文本还是图片采用的语言是中文还是英文。举个例子客户端向服务端发送你好。客户端 --- 你好 --- 服务端这中间包含了两个关键步骤分别对应编码、解码编码客户端将你好这个字符串编码成计算机网络需要的二进制比特位。解码服务端将接收到的二进制比特位解码成你好这个字符串。总结一下编码将需要传送的数据转成对应的二进制比特位。解码将二进制比特位转成原始的数据。上面有两个关键的技术细节尚未回答答案就在下一小节客户端怎么知道你好这个字符对应的比特位是多少服务端收到二进制比特位之后怎么知道对应的字符串是什么关于字符集和字符编码乱码的根源所在既然字符与二进制之间可以互相转换就说明存在明确的转换规则可以实现字符 - 二进制的相互转换。这里提到的转换规则其实就是我们经常听到的字符集与字符编码。字符集Character Set字符集是一系列字符文字、标点符号等的集合。字符集有很多常见的有 ASCII、Unicode、GBK 等。不同字符集主要的区别在于包含字符个数的不同。字符编码Character Encoding字符集告诉我们支持哪些字符但具体字符怎么编码是由字符编码决定的。比如 Unicode 字符集支持的字符编码有 UTF-8常用、UTF-16、UTF-32。概括一下字符集字符的集合不同字符集包含的字符数不同。字符编码字符集中字符的实际编码方式。一个字符集可能有多种字符编码方式。可以把字符编码看成一张映射表客户端、服务端就是根据这张映射表来实现字符跟二进制的编解码转换。举个例子你这个字符在 UTF-8 编码中占据三个字节0xe4 0xbd 0xa0而在 GBK 编码中占据两个字节0xc4 0xe3。乱码的根源当发送端用映射表 A如 GBK编码出二进制而接收端却用映射表 B如 UTF-8去解码时得到的字符自然与原始数据不符于是出现乱码。仓库示例 examples/2017.09.03-charset-enc-dec/test.js 中也对比了同一字符你在 UTF-8 与 GBK 两种编码下的字节差异可以直接运行验证。字符编解码入门iconv-lite 实战上面已经介绍了字符编解码所需的基础知识下面看一个简单例子。这里借助iconv-lite这个库来帮助我们实现编解码操作Node.js 原生并不直接支持 GBK 编码因此需要这类第三方库。完整的可运行代码见 examples/2017.09.03-charset-enc-dec/encode-decode.jsvar iconv require(iconv-lite); var oriText 你; var encodedBuff iconv.encode(oriText, gbk); console.log(encodedBuff); // Buffer c4 e3 var decodedText iconv.decode(encodedBuff, gbk); console.log(decodedText); // 你 var wrongText iconv.decode(encodedBuff, utf8); console.log(wrongText); // 可以看到字符编码时采用了gbk得到两个字节的 BufferBuffer c4 e3与上文你在 GBK 中占两字节0xc4 0xe3的结论完全吻合解码时如果同样采用gbk可以得到原始的字符你而解码时采用utf8时则出现了乱码——这正是编解码映射表不一致的典型后果。iconv-lite的核心 API 就两个iconv.encode(text, encoding)将字符串按指定编码转成 Buffericonv.decode(buffer, encoding)将 Buffer 按指定编码转回字符串。encoding参数支持utf8、gbk、gb2312、big5、utf16等常见编码名使用前请先通过npm install iconv-lite安装依赖。实际例子HTTP 服务端编解码与乱码处理通常我们需要处理编解码的场景有文件读写、网络请求处理。这里举网络请求的例子介绍如何在服务端进行编解码。假设我们运行着如下 HTTP 服务监听来自客户端的请求。客户端传输数据时采用了gbk编码而服务端默认采用的是utf8编码。如果此时采用默认的utf8对请求进行解码就会出现乱码因此需要特殊处理。服务端代码服务端代码如下为简化代码这里跳过了请求方法、请求编码的判断完整文件见 examples/2017.09.03-charset-enc-dec/server.jsvar http require(http); var iconv require(iconv-lite); // 假设客户端采用post方法编码为gbk var server http.createServer(function (req, res) { var chunks []; req.on(data, function (chunk) { chunks.push(chunk) }); req.on(end, function () { chunks Buffer.concat(chunks); // 对二进制进行解码 var body iconv.decode(chunks, gbk); console.log(body); res.end(HELLO FROM SERVER); }); }); server.listen(3000);客户端代码对应的客户端代码如下完整文件见 examples/2017.09.03-charset-enc-dec/client.jsvar http require(http); var iconv require(iconv-lite); var charset gbk; // 对字符你进行编码 var reqBuff iconv.encode(你, charset); var options { hostname: 127.0.0.1, port: 3000, path: /, method: POST, headers: { Content-Type: text/plain, Content-Encoding: identity, Charset: charset // 设置请求字符集编码 } }; var client http.request(options, function(res) { res.pipe(process.stdout); }); client.end(reqBuff);运行与验证先在仓库examples/2017.09.03-charset-enc-dec目录下安装依赖npm install iconv-lite然后启动服务端node server.js目录内 package.json 也提供了npm start快捷方式默认执行node server.js再另开一个终端运行客户端node client.js服务端控制台会打印解码后的你客户端收到响应HELLO FROM SERVER。关键点解读客户端在发送前先用iconv.encode(你, gbk)得到 GBK 编码的字节流并通过请求头Charset: gbk告知服务端编码方式服务端通过req.on(data)累积请求体二进制 chunk在req.on(end)后用Buffer.concat(chunks)拼成完整的 Buffer再调用iconv.decode(chunks, gbk)按相同编码解码若服务端忽略编码信息、直接用utf8解码输出必然是乱码——这正是生产环境中最常见的问题场景。生产实践从 Content-Type 中动态识别请求编码上面的示例把解码编码写死为gbk。在实际项目中请求编码往往随客户端变化更稳妥的做法是从请求头Content-Type的charset参数中动态解析编码。仓库中 examples/2017.05.20-express-body-parser/parser-with-encoding/server.js 给出了参考实现var http require(http); var contentType require(content-type); var iconv require(iconv-lite); var parsePostBody function (req, done) { var length req.headers[content-length] - 0; var obj contentType.parse(req.headers[content-type]); var charset obj.parameters.charset; // request body 编码 var arr []; var chunks; req.on(data, buff { arr.push(buff); }); req.on(end, () { chunks Buffer.concat(arr); var body iconv.decode(chunks, charset); done(body); }); }; var server http.createServer(function (req, res) { parsePostBody(req, (body) { res.end(Your nick is ${body}) }); }); server.listen(3000);配套客户端 examples/2017.05.20-express-body-parser/parser-with-encoding/client.js 在请求头中显式声明编码Content-Type: text/plain; charset encoding并同样用iconv.encode(程序猿小卡, gbk)先行编码再发送。由此可以看出完整的编码声明 - 编码传输 - 按声明解码闭环是避免乱码的通用范式。相关中间件解析思路可进一步参考进阶/body-parser.md。补充Node 内置的 string_decoder 与多字节字符边界问题除了第三方iconv-liteNode 还内置了string_decoder模块用于将 Buffer 转成对应的字符串详见模块/string_decoder.md。它的特殊之处在于当传入的 Buffer 不完整比如 UTF-8 中三个字节的字符只传入两个字节时内部会维护一个 internal buffer 将不完整的字节缓存住等再次调用decoder.write(buffer)传入剩余字节后拼成完整字符。这在网络请求的包体解析场景中非常有用const StringDecoder require(string_decoder).StringDecoder; const decoder new StringDecoder(utf8); // Buffer.from(你好) Buffer e4 bd a0 e5 a5 bd let str decoder.write(Buffer.from([0xe4, 0xbd, 0xa0, 0xe5, 0xa5])); console.log(str); // 你好还差1个字节被缓存 str decoder.write(Buffer.from([0xbd])); console.log(str); // 好补齐剩余字节后成功解码这提醒我们多字节字符如 UTF-8 中文占 3 字节在分块传输时可能被拆散直接对单个 chunk 做解码容易出错正确的做法是先累积、合并 Buffer如服务端示例中的Buffer.concat或借助string_decoder处理不完整字节再统一解码。小结本文围绕 nodejs-learning-guide 进阶篇的字符编解码与乱码处理展开梳理了以下要点原理层网络传输本质是二进制字符与二进制之间的转换规则由字符集与字符编码决定同一个字符在不同编码下字节数可能不同如你在 UTF-8 中占 3 字节、GBK 中占 2 字节工具层Node 原生不支持 GBK 等编码可借助iconv-lite的encode/decode完成双向转换完整示例见 examples/2017.09.03-charset-enc-dec实战层服务端处理网络请求时先累积请求体字节再按客户端声明的编码Content-Type的charset或自定义头解码即可避免乱码对多字节字符的边界问题可用Buffer.concat合并或借助内置string_decoder处理。掌握声明编码、按编码编码、按编码解码的一致性闭环乱码问题就不再是玄学。赞分享文档教程后端【免费下载链接】nodejs-learning-guideNodejs学习笔记以及经验总结公众号程序猿小卡项目地址https://gitcode.com/gh_mirrors/no/nodejs-learning-guide点击查看免费下载相关推荐Nodejs-learning-guide字符编码与乱码问题终极解决方案Nodejs learning guide字符编码与乱码问题终极解决方案 在处理Node.js服务端开发时字符编码与乱码问题是一个让很多开发者头疼的难题。本文档教程后端LunaTranslator字符编码处理解决特殊字符乱码问题LunaTranslator字符编码处理解决特殊字符乱码问题 在Galgame翻译过程中特殊字符乱码是影响翻译体验的常见问题。本文将详细介绍LunaTran桌面应用OCR人工智能cJSON字符串处理技巧ANSI C环境下的UTF-8编码详解cJSON字符串处理技巧ANSI C环境下的UTF 8编码详解 引言嵌入式JSON开发的隐形陷阱 在资源受限的嵌入式系统开发中开发者常面临 JSON字符串序列化上一篇OpenDesign 设计系统 2.0 包使用指南BMW 品牌包契约、Token 体系与 Agent 集成规范下一篇碧蓝航线Alas自动化脚本24/7全自动游戏管理终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表