1. 程式人生 > >Spark踩坑系列4--spark 中文編碼處理

Spark踩坑系列4--spark 中文編碼處理

日誌的格式是GBK編碼的,而hadoop上的編碼是用UTF-8寫死的,導致最終輸出亂碼。

研究了下Java的編碼問題。

網上其實對spark輸入檔案是GBK編碼有現成的解決方案,具體程式碼如下

import org.apache.hadoop.io.LongWritable
import org.apache.hadoop.io.Text
import org.apache.hadoop.mapred.TextInputFormat

rdd = ctx.hadoopFile(file_list, classOf[TextInputFormat],
            classOf[LongWritable], classOf[Text]).map(
            pair 
=> new String(pair._2.getBytes, 0, pair._2.getLength, "GBK"))

這種想法的來源是基於

public static Text transformTextToUTF8(Text text, String encoding) {
    String value = null;
    try {
    value = new String(text.getBytes(), 0, text.getLength(), encoding);
    } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    }
    
return new Text(value); }

但這種方法還有一個問題,

大家都知道gbk是2~3個位元組編碼的。如果日誌中按照直接截斷,導致按照gbk讀取檔案的時候,將後面的分隔符\t一併讀取了 ,導致按照\t split的時候,欄位的個數不對(或者說順序錯位了)。

這個時候,需要找到一種單位元組的解析方案,即 ISO-8859-1編碼。程式碼如下

rdd = ctx.hadoopFile(file_list, classOf[TextInputFormat],
            classOf[LongWritable], classOf[Text]).map(
            pair 
=> new String(pair._2.getBytes, 0, pair._2.getLength, "ISO-8859-1"))

但這又帶來了一個問題,即輸出的結果(按照UTF-8儲存)是亂碼,不可用。

如果我們換一種思路來考慮這個問題,Java或scala中如何將一個gbk檔案轉換為UTF8?網上有很多的現成的程式碼,具體到我們的場景,以行為單位處理的話,示例程式碼如下

public class Encoding {
    private static String kISOEncoding = "ISO-8859-1";
    private static String kGBKEncoding = "GBK";
    private static String kUTF8Encoding = "UTF-8";
    
    public static void main(String[] args) throws UnsupportedEncodingException {
        try {
            File out_file = new File(args[1]);
            Writer out = new BufferedWriter(new OutputStreamWriter(
                         new FileOutputStream(out_file), kUTF8Encoding));
            List<String> lines = Files.readAllLines(Paths.get(args[0]), Charset.forName(kGBKEncoding));
            for (String line : lines) {
                out.append(line).append("\n");
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

如上的程式碼給了我們一個啟示,即在寫入檔案的時候,系統自動進行了編碼的轉換,我們沒必要對進行單獨的直接轉換處理。

通過查詢資料,Java中字元編碼是內部編碼,即位元組流按照編碼轉化為String。

所謂結合以上兩點認識,我們模擬在spark上以ISO-8859-1

開啟檔案和以UTF-8寫入檔案的過程,發現只需要將其強制轉換為GBK的string即可,最終得到的檔案以UTF-8開啟不是亂碼,具體程式碼如下。

public class Encoding {
    private static String kISOEncoding = "ISO-8859-1";
    private static String kGBKEncoding = "GBK";
    private static String kUTF8Encoding = "UTF-8";
    
    public static void main(String[] args) throws UnsupportedEncodingException {
        try {
            File out_file = new File(args[1]);
            Writer out = new BufferedWriter(new OutputStreamWriter(
                         new FileOutputStream(out_file), kUTF8Encoding));
            List<String> lines = Files.readAllLines(Paths.get(args[0]), Charset.forName(kISOEncoding));
            for (String line : lines) {
                String gbk_str = new String(line.getBytes(kISOEncoding), kGBKEncoding);
                out.append(gbk_str).append("\n");
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

完美的解決了。。。花費了一個工作日解決才解決的問題,對Java還是不夠熟練啊。

總結出來,希望對大家有用。

相關推薦

Spark系列4--spark 中文編碼處理

日誌的格式是GBK編碼的,而hadoop上的編碼是用UTF-8寫死的,導致最終輸出亂碼。研究了下Java的編碼問題。網上其實對spark輸入檔案是GBK編碼有現成的解決方案,具體程式碼如下import org.apache.hadoop.io.LongWritable imp

Spark入門實戰系列--4.Spark執行架構

其中,ResourceManager負責將叢集的資源分配給各個應用使用,而資源分配和排程的基本單位是Container,其中封裝了機器資源,如記憶體、CPU、磁碟和網路等,每個任務會被分配一個Container,該任務只能在該Container中執行,並使用該Container封裝的資源。NodeManage

系列】使用long型別處理金額,科學計數法導致金額轉大寫異常

## 1. 踩坑經歷 上週,一個使用者反饋他建立的某個銷售單無法開啟,但其餘銷售單都可以正常開啟,當時查看了生產環境的ERROR日誌,發現拋了這樣的異常:`java.lang.NumberFormatException: For input string: "E"`。 相信大家對這個異常都不陌生,很顯然,

spark記共享變量

park oid and 共享變量 roi syn out his andro %E5%9C%A8android%E4%B8%AD%E6%80%8E%E4%B9%88%E7%94%A8this removeviewinlayout?к????? repo????л???

[轉]Spark 記:數據庫(Hbase+Mysql)

cep 直接 策略 https rds 但是 更新 base ID https://cloud.tencent.com/developer/article/1004820 Spark 踩坑記:數據庫(Hbase+Mysql) 前言 在使用Spark Streaming的過程

使用ABP框架過的系列4

oop dbcontext SM 插入代碼 系列 一個 ID Go right 數據庫連接和事務管理,是數據庫應用中的最重要概念之一。做過的人,都會頭疼:何時Open一個連接?何時Start一個事務?何時Dispose這個連接?... ABP框架試圖用一個叫做Unit

spark——dataframe寫入hbase連接異常

查找 inux ron user ora nat 文件 cor 1.8 最近測試環境基於shc[https://github.com/hortonworks-spark/shc]的hbase-connector總是異常連接不到zookeeper,看下報錯日誌: 18/06/

Spark系列(三)Spark操作Hive的

跟著教學試著用Idea程式設計,實現Spark查詢Hive中的表。結果上來就涼了。 搗鼓好久都不行,在網上查有說將hive-site.xml放到resource目錄就行,還有什麼hadoop針對windows使用者的許可權問題,結果都是扯淡。 其實問題還是處在程式碼上,直接附上程式碼了

Spark系列(二)使用Scala編寫的工程Maven打包沒有Scala檔案

新增下面的maven Scala編譯支援 <plugin>     <groupId>net.alchim31.maven</groupId>    <artifactId>scala-maven-

Spark系列(一) 叢集環境讀取本地檔案的

Spark 採坑系列 今天在網上看了一個例子,Spark啟動後讀取檔案並計算的例子,自己在按照網上方法使用的時候意外菜了坑。 首先,我將3臺虛擬機器的Spark叢集以及Hadoop叢集啟動。 然後我在其中一個伺服器上編輯了一個文字,命名sparkFirst,內容如下: hello s

Spark記——Spark Streaming+Kafka

目錄     前言     Spark streaming接收Kafka資料         基於Receiver的方式         直接讀取方式     Spark向kafka中寫入資料     Spark streaming+Kafka應用     Spark str

Spark系列4- Spark Streaming

1 流計算 靜態資料和流資料 靜態資料類似儲存在水庫中的水,是相對靜止不動的,如資料倉庫中儲存的資料、關係型資料庫中儲存的資料等。流資料是指在時間分佈和數量上無限的一系列動態資料合體,資料記錄是流資料的最小組成單元。 靜態資料和流資料的處理,分別對應兩種不同的計

spark 中文編碼處理

日誌的格式是GBK編碼的,而hadoop上的編碼是用UTF-8寫死的,導致最終輸出亂碼。 研究了下Java的編碼問題。 網上其實對spark輸入檔案是GBK編碼有現成的解決方案,具體程式碼如下 import org.apache.hadoop.io.LongWrit

Spark記:共享變數

收錄待用,修改轉載已取得騰訊雲授權 前言 前面總結的幾篇spark踩坑博文中,我總結了自己在使用spark過程當中踩過的一些坑和經驗。我們知道Spark是多機器叢集部署的,分為Driver/Master/Worker,Master負責資源排程,Wor

ReactNative系列--構建失敗

pos hone dia install works 沒有 iphone 註意 module 初始化項目後執行react-native run-ios,構建失敗: ** BUILD FAILED ** The following commands produced a

Spark入門實戰系列--2.Spark編譯與部署(中)--Hadoop編譯安裝

二進制包 1.10 不能 mapr 修復 att 機器 mave end 【註】該系列文章以及使用到安裝包/測試數據 能夠在《[傾情大奉送–Spark入門實戰系列] (http://blog.csdn.net/yirenboy/article/deta

【Kafka系列之一】消費者拉不出數據

dex -c 通知 還得 gin div 消費 發現 拉取 一、Bug背景 因業務需要,我們部署了兩個Kafka集群。Kafka集群A的版本號為:0.11.0.1,Kafka集群B的版本號為0.9.0.1。 因兩個Kafka集群的版本號不一致,嘗試了

Vue系列

route fun 加載 關系 監聽 沒有 踩坑 eid ram 前言 前端開發對於vue的使用已經越來越多,它的優點就不做介紹了, 本篇是我對vue使用過程中遇到的問題中做的一些總結,幫助大家踩坑。如果喜歡的話可以點波贊,或者關註一下,希望本文可以幫到大家!!! 本篇介紹

Jenkins系列--你試過linux主機ssh登錄windows,啟動java進程嗎,來試試吧

是否 dmp .bat opts 在服務器 qq群 持續集成 version 啟動服務 一、問題概述 在一個多月前,組長讓我研究下持續集成。我很自然地選擇了jenkins。當時,(包括現在也是),部分服務器用的是windows主機。 我當時想了想,如果我把jenkins

Spark入門實戰系列--9.Spark圖計算GraphX介紹及例項

1、GraphX介紹 1.1 GraphX應用背景 Spark GraphX是一個分散式圖處理框架,它是基於Spark平臺提供對圖計算和圖挖掘簡潔易用的而豐富的介面,極大的方便了對分散式圖處理的需求。 眾所周知·,社交網路中人與人之間有很多關係鏈,例如Twitter、Faceb