2018年12月31日 星期一

JavaScript : URIError: URI malformed

2018年12月31日 星期一
Facebook 的備份檔如果選用 JSON 格式來備份,所有的文字都會以 Unicode 編碼,例如:

"content": "\u00e9\u0099\u008d\u00e9\u009b\u00a8\u00e6\u00a9\u009f\u00e7\u008e\u008790%"

這個如果變成 JavaScript 的變數,內容會被直接解碼,不過,中文字通通變成亂碼。後來想到一招,將每個「\u00」通通換成「%」,就可以利用 JavaScript 的「decodeURIComponent」來解碼了。所以將上面的內容先變成:

"content":
"%e9%99%8d%e9%9b%a8%e6%a9%9f%e7%8e%8790%"

不過,大部份的內容都可以順利的轉換為中文字,遇到上面舉的例子就會出現底下的錯誤的訊息:

URIError: URI malformed

基本上,如果有 decodeURIComponent 不能解碼的字,就會出現前述的錯誤訊息。追了一下「%」編碼的東西,最後面多了一個「%」,導致解碼失敗。因為 URI 的編碼,每個字的前面會加上百分比的符號「%」,照說,如果要用「%」,應該要用「%25」才對,如果沒有將 % 編碼,在解碼時就會出現錯誤。

如果不想改原始內容怎麼辦?駝鳥心態的話,當然是直接跳過不解碼了。哈!我可不想當駝鳥,於是遇到錯誤時,就將錯誤修正過來再重新解碼即可!

底下的程式碼先試著解碼,如果有錯的話,就以 % 將字串分解,然後一一檢查後重組。判斷 % 到底是編碼時的前導符號,還是只是 % 這個字的關鍵如下:

  • 編碼後, % 後面接的字串字數必須為二的倍數

所以如果 % 後面接的字串字數不是二的倍數,甚至是空的,表示它只是一般的百分比符號而已,必須將它變成編碼後的「%25」。

底下是以土法煉鋼的方式寫的程式,先記錄下來 ,以後再進化:


uriDecode = function (str) {
var out = '';
try {
var out = decodeURIComponent(str);
} catch(e) {
if( typeof(console) != 'undefined' ) {
console.log(str);
console.log(e); }
var p = str.split('%'); //以 % 將字串分解
var len = p.length; var out = '';
for(var i=0; i<len; i++) {
//如果是分解完的內容是空的,表示為第一個或是 %
//檢查下一個是否為兩個字元, 如果不是, 表示為%
if(p[i] == '') { if(i<len-1) {
//如果下一個為空的或是字元數不是二的倍數, 則應為%
if( p[i+1]=='' || p[i+1].length % 2 == 1) {
p[i] = '%25'; //轉為 % 的編碼
}
} else { //出現在最後, 一定為 %
p[i] = '%25'; //轉為 % 的編碼
}
out += p[i];
} else {
//如果長度為二的倍數, 就在前面加上 %
if(p[i].length % 2 == 0) {
out += '%'
}
out += p[i];
}
}
try {
out = decodeURIComponent(out);
} catch(e) {
if( typeof(console) != 'undefined' ) {
console.log(str);
console.log(e); } } }
return out; }






沒有留言:

張貼留言

 
雄::gsyan © 2009. Design by Pocket