首頁 > 軟體

Spark 處理中文亂碼問題(UTF-8編碼)

2020-06-16 17:35:35

問題場景

要用spark處理一大堆微信紀錄檔資料,紀錄檔存放在HDFS上,是xml格式,裡面有大量的中文。用scala + java實現了xml的處理邏輯,其中有一步是要獲取xml中的一個title欄位,中文。不管怎麼抓取,最終得到的中文都會變成一堆“?????”,亂碼了。從xml中獲取非中文欄位,沒有任何問題。也就是說,程式碼的邏輯是沒什麼問題的。

問題解析

直接用Hadoop fs -text或者hadoop fs -cat檢視HDFS上的檔案,是可以正常顯示的,也就是說HDFS上存放的原資料是好的。那麼就肯定是讀取資料或者處理資料的過程中出了問題。spark on yarn的資料處理,同時涉及了HDFS,App driver, App excutor之間的互動,所以還真沒法一下就判斷出是哪一步傳輸中出了問題。抽絲剝繭,先梳理一遍spark的處理邏輯:

(1) 從HDFS把xml讀取到每個NM上的executor中(spark on yarn環境)

(2) 在executor中對xml進行處理,獲取中文欄位。這裡我實現了一個java方法,呼叫dom來解析xml。

(3) 把解析後的欄位collect到driver中,做儲存或者輸出列印等。

(4) 或者把解析後的欄位重新存入HDFS

進入Spark-shell,依次驗證這幾個步驟。讀入HDFS上的xml檔案,然後直接寫入HDFS,檢查發現字元顯示正常,排除步驟(1)(4)。讀入HDFS上的xml檔案,collect到driver中,然後println,字元顯示正常,排除步驟(3)。說明問題出在executor對欄位的解析處理過程中。

 

無論漢字還是英文字元,本質上還是一組位元組流,所以出現亂碼,只能是編碼解析出了問題。檢視發現,程式碼中只有一個地方對xml檔案中的字元做了解析,就是這裡: 

		DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
		InputStream strm =  new ByteArrayInputStream(xmlStream.getBytes());
		Document doc = dbBuilder.parse(strm);

把string轉為inputStream的過程。 找到了出問題的位置,下一步就是檢測。 

登入到executor所在的hadoop節點,進入spark-shell, 輸入System.getProperty("file.encoding"),返回”ISO-8859-1“,說明它的預設編碼方式是ISO-8859-1。另一種檢測方法,是定義一個String變數等於一個漢字,然後a.getBytes().length。檢查它的位元組數,並推斷對應的字元編碼。UTF8漢字占3個位元組,GBK漢字占2個位元組。 

ISO-8895-1占1位元組,用ISO-8895-1的方式把漢字轉成位元組流,然後轉回的過程中,肯定會損失一部分資料,所以會亂碼。

問題定位到後,解決就很簡單了。 在所有涉及到位元組轉換時,一定要指定編碼方式。類似這樣:

String -> Byte: 

string.getBytes("UTF-8")

Byte -> String:

new String(bytes, "UTF-8")

更多Spark相關教學見以下內容

CentOS 7.0下安裝並設定Spark  http://www.linuxidc.com/Linux/2015-08/122284.htm

Spark1.0.0部署指南 http://www.linuxidc.com/Linux/2014-07/104304.htm

Spark官方文件 - 中文翻譯  http://www.linuxidc.com/Linux/2016-04/130621.htm

CentOS 6.2(64位元)下安裝Spark0.8.0詳細記錄 http://www.linuxidc.com/Linux/2014-06/102583.htm

Spark簡介及其在Ubuntu下的安裝使用 http://www.linuxidc.com/Linux/2013-08/88606.htm

安裝Spark叢集(在CentOS上) http://www.linuxidc.com/Linux/2013-08/88599.htm

Hadoop vs Spark效能對比 http://www.linuxidc.com/Linux/2013-08/88597.htm

Spark安裝與學習 http://www.linuxidc.com/Linux/2013-08/88596.htm

Spark 平行計算模型 http://www.linuxidc.com/Linux/2012-12/76490.htm

Ubuntu 14.04 LTS 安裝 Spark 1.6.0 (偽分散式) http://www.linuxidc.com/Linux/2016-03/129068.htm


IT145.com E-mail:sddin#qq.com