服裝市場網(wǎng)站建設(shè)互聯(lián)網(wǎng)營銷師報名費
工作日志
日期:2024-11-15
標題:HarmonyOS ArkTs 解決流式傳輸編碼問題
問題描述
- 問題:在處理流式數(shù)據(jù)的 HTTP 請求時,服務(wù)器返回的數(shù)據(jù)存在編碼問題,導(dǎo)致數(shù)據(jù)無法正確地解碼為字符串。部分數(shù)據(jù)在解碼后出現(xiàn)了亂碼,特別是 JSON 格式無法正確解析。
- 現(xiàn)象:接收到的響應(yīng)數(shù)據(jù)在轉(zhuǎn)換為字符串后包含亂碼,無法正確轉(zhuǎn)換為 JSON 格式,部分數(shù)據(jù)內(nèi)容顯示為
\uXXXX
之類的亂碼字符。解析 JSON 時拋出異常,提示 “Unexpected token” 等錯誤信息。
原因分析
- 原因:問題的根本在于沒有正確處理流式傳輸中的數(shù)據(jù)拼接和編碼轉(zhuǎn)換。原始實現(xiàn)中使用
ArrayBuffer
和手動逐字節(jié)轉(zhuǎn)換的方式,這種方式在處理多次接收的數(shù)據(jù)時比較繁瑣,且容易引發(fā)編碼不匹配的問題。數(shù)據(jù)在拼接過程中也容易導(dǎo)致一些字符丟失或編碼錯誤。
解決步驟
-
使用
Uint8Array
進行數(shù)據(jù)拼接:- 設(shè)置
Uint8Array
類型用于維護流式響應(yīng)數(shù)據(jù),這樣可以方便地將每次接收到的數(shù)據(jù)進行拼接。 - 代碼如下:
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
來解碼Uint8Array
,以便正確地處理 UTF-8 編碼的字符,避免手動逐字節(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。如果解析失敗,則進行格式清理(例如將單引號替換為雙引號),再嘗試解析。 - 代碼如下:
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ù)之后,使用
-
驗證問題是否解決:
- 通過多次調(diào)用接口并觀察日志,確認所有返回數(shù)據(jù)均能正確解碼為 UTF-8 格式,且能正確解析為 JSON。亂碼問題徹底解決。
經(jīng)驗教訓(xùn)
- 總結(jié):
- 在處理流式數(shù)據(jù)時,正確的編碼和拼接方法非常重要。
Uint8Array
提供了更高效的方式來拼接和操作二進制數(shù)據(jù)。 - 使用
TextDecoder
代替手動字節(jié)解析是處理流式數(shù)據(jù)解碼的最佳方式,可以有效避免編碼錯誤和亂碼問題。 - 遇到解析失敗的情況時,嘗試對數(shù)據(jù)格式進行清理是個有效的補救措施,尤其在數(shù)據(jù)格式不完全符合標準時,這種處理方式可以大大提高解析的成功率。
- 最終解決方案結(jié)合了數(shù)據(jù)的高效拼接和編碼轉(zhuǎn)換的正確方法,可以作為今后處理流式傳輸數(shù)據(jù)的最佳實踐。
- 在處理流式數(shù)據(jù)時,正確的編碼和拼接方法非常重要。