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

網頁好讀版