服裝市場(chǎng)網(wǎng)站建設(shè)互聯(lián)網(wǎng)營(yíng)銷師報(bào)名費(fèi)
工作日志
日期:2024-11-15
標(biāo)題:HarmonyOS ArkTs 解決流式傳輸編碼問(wèn)題
問(wèn)題描述
- 問(wèn)題:在處理流式數(shù)據(jù)的 HTTP 請(qǐng)求時(shí),服務(wù)器返回的數(shù)據(jù)存在編碼問(wèn)題,導(dǎo)致數(shù)據(jù)無(wú)法正確地解碼為字符串。部分?jǐn)?shù)據(jù)在解碼后出現(xiàn)了亂碼,特別是 JSON 格式無(wú)法正確解析。
- 現(xiàn)象:接收到的響應(yīng)數(shù)據(jù)在轉(zhuǎn)換為字符串后包含亂碼,無(wú)法正確轉(zhuǎn)換為 JSON 格式,部分?jǐn)?shù)據(jù)內(nèi)容顯示為
\uXXXX
之類的亂碼字符。解析 JSON 時(shí)拋出異常,提示 “Unexpected token” 等錯(cuò)誤信息。
原因分析
- 原因:問(wèn)題的根本在于沒(méi)有正確處理流式傳輸中的數(shù)據(jù)拼接和編碼轉(zhuǎn)換。原始實(shí)現(xiàn)中使用
ArrayBuffer
和手動(dòng)逐字節(jié)轉(zhuǎn)換的方式,這種方式在處理多次接收的數(shù)據(jù)時(shí)比較繁瑣,且容易引發(fā)編碼不匹配的問(wèn)題。數(shù)據(jù)在拼接過(guò)程中也容易導(dǎo)致一些字符丟失或編碼錯(cuò)誤。
解決步驟
-
使用
Uint8Array
進(jìn)行數(shù)據(jù)拼接:- 設(shè)置
Uint8Array
類型用于維護(hù)流式響應(yīng)數(shù)據(jù),這樣可以方便地將每次接收到的數(shù)據(jù)進(jìn)行拼接。 - 代碼如下:
let resView = new Uint8Array(0); httpRequest.on('dataReceive', (data: ArrayBuffer) => {const newView = new Uint8Array(resView.length + data.byteLength);newView.set(resView, 0);newView.set(new Uint8Array(data), resView.length);resView = newView;console.info('Updated response length: ' + resView.length); });
- 設(shè)置
-
使用
TextDecoder
正確解碼Uint8Array
:- 使用
TextDecoder
來(lái)解碼Uint8Array
,以便正確地處理 UTF-8 編碼的字符,避免手動(dòng)逐字節(jié)轉(zhuǎn)換可能引起的亂碼。 - 代碼如下:
function uint8ArrayToString(buffer: Uint8Array): string {const decoder = new util.TextDecoder('utf-8');return decoder.decode(buffer); }
- 使用
-
處理數(shù)據(jù)結(jié)束并轉(zhuǎn)換為字符串或 JSON:
- 在接收到完整數(shù)據(jù)之后,使用
TextDecoder
解碼數(shù)據(jù)并嘗試解析為 JSON。如果解析失敗,則進(jìn)行格式清理(例如將單引號(hào)替換為雙引號(hào)),再嘗試解析。 - 代碼如下:
httpRequest.on('dataEnd', () => {console.info('No more data in response, data receive end');let resultString = uint8ArrayToString(resView);try {let jsonData: undefined | string;try {jsonData = JSON.parse(resultString);} catch (error) {console.warn("Response could not be parsed as JSON directly.");let cleanedString = resultString.replace(/'/g, '"');jsonData = JSON.parse(cleanedString);}console.info('Parsed response as JSON:', JSON.stringify(jsonData));callback(JSON.stringify(jsonData));} catch (e) {console.error('Failed to parse response:', e);console.info('Response as raw string:', resultString);callback(resultString);} });
- 在接收到完整數(shù)據(jù)之后,使用
-
驗(yàn)證問(wèn)題是否解決:
- 通過(guò)多次調(diào)用接口并觀察日志,確認(rèn)所有返回?cái)?shù)據(jù)均能正確解碼為 UTF-8 格式,且能正確解析為 JSON。亂碼問(wèn)題徹底解決。
經(jīng)驗(yàn)教訓(xùn)
- 總結(jié):
- 在處理流式數(shù)據(jù)時(shí),正確的編碼和拼接方法非常重要。
Uint8Array
提供了更高效的方式來(lái)拼接和操作二進(jìn)制數(shù)據(jù)。 - 使用
TextDecoder
代替手動(dòng)字節(jié)解析是處理流式數(shù)據(jù)解碼的最佳方式,可以有效避免編碼錯(cuò)誤和亂碼問(wèn)題。 - 遇到解析失敗的情況時(shí),嘗試對(duì)數(shù)據(jù)格式進(jìn)行清理是個(gè)有效的補(bǔ)救措施,尤其在數(shù)據(jù)格式不完全符合標(biāo)準(zhǔn)時(shí),這種處理方式可以大大提高解析的成功率。
- 最終解決方案結(jié)合了數(shù)據(jù)的高效拼接和編碼轉(zhuǎn)換的正確方法,可以作為今后處理流式傳輸數(shù)據(jù)的最佳實(shí)踐。
- 在處理流式數(shù)據(jù)時(shí),正確的編碼和拼接方法非常重要。