2020
Oct
30

网页好读版

big5 url encoded string to utf8 string

如何把 url encode 过的 big5 编码转换成 utf8 字串, "水泥"这两个字的 big5 编码,透过 urlencode 后会是 %A4%F4%AAd ,%A4%F4 代表"水",%AAd 代表泥, %AA 是泥的第一个 byte ,"d" 是泥的第二个 byte ,正常第二个 byte 应该要是 %64 但是这个编码刚好在 ASCII 是一个字元 d ,所以泥这字 urlencode 后才变成 "%AAd"

当我收到 big5 编码 %A4%F4%AAd 转回 "水泥" 程式如下:

Example
  1. var Iconv = require('iconv').Iconv;
  2. var iconvToUtf8 = new Iconv('Big5', 'UTF8');
  3. var encoded = "%A4%F4%AAd";
  4. var decoded = urlDecodeBytes(encoded);
  5. bufUtf8 = iconvToUtf8.convert(decoded);
  6. console.log(bufUtf8);
  7. console.log("bufUtf8 ", new String(bufUtf8, "UTF8"));
  8.  
  9. function urlDecodeBytes(encoded) {
  10. let decoded = Buffer.from('')
  11. for (let i = 0; i < encoded.length; i++) {
  12. if (encoded[i] === '%') {
  13. const charBuf = Buffer.from(`${encoded[i + 1]}${encoded[i + 2]}`, 'hex')
  14. decoded = Buffer.concat([decoded, charBuf])
  15. i += 2
  16. } else {
  17. const charBuf = Buffer.from(encoded[i])
  18. decoded = Buffer.concat([decoded, charBuf])
  19. }
  20. }
  21. return decoded
  22. }
  23.  
  24. function isUrlSafe(char) {
  25. return /[a-zA-Z0-9\-_~.]+/.test(char)
  26. }
Example
  1. // 执行结果
  2. node convert.js
  3. <Buffer e6 b0 b4 e6 b3 a5>
  4. bufUtf8 [String: '水泥']

Node.js iconv module 转换编码并没有什么问题,这段程式码主要是做 urldecode ,判断字串中是否有 "%" ,如果没有就帮它补上 (将 d 转成 %64) ,最后存到 node Buffer ,再利用 iconv 转换编码。

参考资料

- urldecode to bytes 方式参考 https://stackoverflow.com/questions/57873879/buffers-and-url-encoding-in-node-js

网页好读版