在創建CDM作業時,有些場景下源端、目的端的作業參數中需要選擇“文件格式”,這里分別介紹這幾種文件格式的使用場景、子參數、公共參數、使用示例等。
- CSV格式
- JSON格式
- 二進制格式
- 文件格式的公共參數
- 文件格式問題解決方法
CSV格式
如果想要讀取或寫入某個CSV文件,請在選擇“文件格式”的時候選擇“CSV格式”。CSV格式的主要有以下使用場景:
- 文件導入到數據庫、NoSQL。
- 數據庫、NoSQL導出到文件。
選擇了CSV格式后,通常還可以配置以下可選子參數:
1.換行符
2.字段分隔符
3.編碼類型
4.使用包圍符
5.使用正則表達式分隔字段
6.首行為標題行
7.寫入文件大小
1.換行符
用于分隔文件中的行的字符,支持單字符和多字符,也支持特殊字符。特殊字符可以使用URL編碼輸入,例如:
表 特殊字符對應的URL編碼
| 特殊字符 | URL編碼 |
|---|---|
| 空格 | %20 |
| Tab | %09 |
| % | %25 |
| 回車 | %0d |
| 換行 | %0a |
| 標題開頭\u0001 (SOH) | %01 |
2.字段分隔符
用于分隔CSV文件中的列的字符,支持單字符和多字符,也支持特殊字符,詳見上表。
3.編碼類型
文件的編碼類型,默認是UTF-8。
如果源端指定該參數,則使用指定的編碼類型去解析文件;目的端指定該參數,則寫入文件的時候,以指定的編碼類型寫入。
4.使用包圍符
- 數據庫、NoSQL導出到CSV文件(“使用包圍符”在目的端):當源端某列數據的字符串中出現字段分隔符時,目的端可以通過開啟“使用包圍符”,將該字符串括起來,作為一個整體寫入CSV文件。CDM目前只使用雙引號("")作為包圍符。如下圖所示,數據庫的name字段的值中包含了字段分隔符逗號:
圖 包含字段分隔符的字段值

不使用包圍符的時候,導出的CSV文件,數據會顯示為:
3.hello,world,abc
如果使用包圍符,導出的數據則為:
3,"hello,world",abc
如果數據庫中的數據已經包含了雙引號(""),那么使用包圍符后,導出的CSV文件的包圍符會是三個雙引號(""")。例如字段的值為:a"hello,world"c,使用包圍符后導出的數據為:
"""a"hello,world"c"""
- CSV文件導出到數據庫、NoSQL(“使用包圍符”在源端):CSV文件為源,并且其中數據是被包圍符括起來的時候,如果想把數據正確的導入到數據庫,就需要在源端開啟“使用包圍符”,這樣包圍符內的值的,會寫入一個字段內。
5.使用正則表達式分隔字段
這個功能是針對一些復雜的半結構化文本,例如日志文件的解析,詳見: 正則表達式分隔半結構化文本。
6.首行為標題行
這個參數是針對CSV文件導出到其它地方的場景,如果源端指定了該參數,CDM在抽取數據時將第一行作為標題行。在傳輸CSV文件的時候會跳過標題行,這時源端抽取的行數,會比目的端寫入的行數多一行,并在日志文件中進行說明跳過了標題行。
7.寫入文件大小
這個參數是針對數據庫導出到CSV文件的場景,如果一張表的數據量比較大,那么導出到CSV文件的時候,會生成一個很大的文件,有時會不方便下載或查看。這時可以在目的端指定該參數,這樣會生成多個指定大小的CSV文件,避免導出的文件過大。該參數的數據類型為整型,單位為MB。
JSON格式
這里主要介紹JSON文件格式的以下內容:
- CDM支持解析的JSON類型
- 記錄節點
- 從JSON文件復制數據
1.CDM支持解析的JSON類型:JSON對象、JSON數組。
- JSON對象:JSON文件包含單個對象,或者以行分隔/串連的多個對象。
i.單一對象JSON:
{ "took" : 190,
"timed_out" : false,
"total" : 1000001,
"max_score" : 1.0
ii.行分隔的JSON對象:
{"took" : 188, "timed_out" :false, "total" : 1000003, "max_score" : 1.0 }
{"took" : 189, "timed_out" : false, "total" :1000004, "max_score" : 1.0 }
iii. 串連的JSON對象:
{
"took": 190,
"timed_out": false,
"total": 1000001,
"max_score": 1.0
}
{
"took": 191,
"timed_out": false,
"total": 1000002,
"max_score": 1.0
}
JSON數組:JSON文件是包含多個JSON對象的數組。
[{ "took" : 190,
"timed_out" : false,
"total" : 1000001,
"max_score" : 1.0
},{ "took" : 191,
"timed_out" : false,
"total" : 1000001,
"max_score" : 1.0
}]
2.記錄節點
記錄數據的根節點。該節點對應的數據為JSON數組,CDM會以同一模式從該數組中提取數據。多層嵌套的JSON節點以字符“.”分割。
3.從JSON文件復制數據
a.示例一:從行分隔/串連的多個對象中提取數據。JSON文件包含了多個JSON對象,例如:
{"took": 190,
"timed_out": false,
"total": 1000001,
"max_score": 1.0
}{"took": 191,
"timed_out": false,
"total": 1000002,
"max_score": 1.0
}{"took": 192,
"timed_out": false,
"total": 1000003,
"max_score": 1.0
}
如果您想要從該JSON對象中提取數據,使用以下格式寫入到數據庫,只需要在作業第一步指定文件格式為“JSON格式”,指定JSON類型為“JSON對象”,然后在作業第二步進行字段匹配即可。
| took | timedOut | total | maxScore |
|---|---|---|---|
| 190 | false | 1000001 | 1.0 |
| 191 | false | 1000002 | 1.0 |
| 192 | false | 1000003 | 1.0 |
b.示例二:從記錄節點中提取數據。JSON文件包含了單個的JSON對象,但是其中有效的數據在一個數據節點下,例如:
{"took": 190,
"timed_out": false,
"hits": {
"total": 1000001,
"max_score": 1.0,
"hits":
[{
"_id":
"650612", "_source": {
"name":
"tom", "books":
["book1","book2","book3"] }
},
{
"_id":
"650616", "_source": {
"name":
"tom", "books":
["book1","book2","book3"] }
},
{
"_id":
"650618", "_source": {
"name":
"tom", "books":
["book1","book2","book3"] }
}]
}
}
如果想以如下格式寫入到數據庫,則需要在作業第一步指定文件格式為“JSON格式”,指定JSON類型為“JSON對象”,并且指定記錄節點為“hits.hits”,然后在作業第二步進行字段匹配。
| ID | SourceName | SourceBooks |
|---|---|---|
| 650612 | tom | ["book1","book2","book3"] |
| 650616 | tom | ["book1","book2","book3"] |
| 650618 | tom | ["book1","book2","book3"] |
c.示例三:從JSON數組中提取數據。JSON文件是包含了多個JSON對象的JSON數組,例如:
[{ "took" : 190,
"timed_out" : false,
"total" : 1000001,
"max_score" : 1.0
},{ "took" : 191,
"timed_out" : false,
"total" : 1000002,
"max_score" : 1.0
}]
如果想以如下格式寫入到數據庫,需要在作業第一步指定文件格式為“JSON格式”,指定JSON類型為“JSON數組”,然后在作業第二步進行字段匹配。
| took | timedOut | total | maxScore |
|---|---|---|---|
| 190 | false | 1000001 | 1.0 |
| 191 | false | 1000002 | 1.0 |
d.示例四:在解析JSON文件的時候搭配轉換器。在示例二前提下,想要把hits.max_score字段附加到所有記錄中,即以如下格式寫入到數據庫中:
| ID | SourceName | SourceBooks | MaxScore |
|---|---|---|---|
| 650612 | tom | ["book1","book2","book3"] | 1.0 |
| 650616 | tom | ["book1","book2","book3"] | 1.0 |
| 650618 | tom | ["book1","book2","book3"] | 1.0 |
則需要在作業第一步指定文件格式為“JSON格式”,指定JSON類型為“JSON對象”,并且指定記錄節點為“hits.hits”,然后在作業第二步添加轉換器,操作步驟如下:
i.單擊
添加字段,新增一個字段。
圖 添加字段

ii.在添加的新字段后面,單擊
添加字段轉換器。
圖 添加字段轉換器

iii.創建“表達式轉換”的轉換器,表達式輸入”1.0”,然后保存。
圖 配置字段轉換器

二進制格式
如果想要在文件系統間按原樣復制文件,則可以選擇二進制格式。二進制格式傳輸文件到文件的速率、性能都最優,且不需要在作業第二步進行字段匹配。
- 文件傳輸的目錄結構
CDM的文件傳輸,支持單文件,也支持一次傳輸目錄下所有的文件。傳輸到目的端后,目錄結構會保持原樣。
- 增量遷移文件
使用CDM進行二進制傳輸文件時,目的端有一個參數“重復文件處理方式”,可以用作文件的增量遷移,具體請參見 文件增量遷移。
增量遷移文件的時候,選擇“重復文件處理方式”為“跳過重復文件”,這樣如果源端有新增的文件,或者是遷移過程中出現了失敗,只需要再次運行任務,已經遷移過的文件就不會再次遷移。
- 寫入到臨時文件
二進制遷移文件時候,可以在目的端指定是否寫入到臨時文件。如果指定了該參數,在文件復制過程中,會將文件先寫入到一個臨時文件中,遷移成功后,再進行rename或move操作,在目的端恢復文件。
- 生成文件MD5值
對每個傳輸的文件都生成一個MD5值,并將該值記錄在一個新文件中,新文件以“.md5”作為后綴,并且可以指定MD5值生成的目錄。
文件格式的公共參數
- 源文件處理方式
CDM在文件復制成功后,可以對源端文件進行操作,包括:不處理、重命名源文件或者刪除源文件。
- 啟動作業標識文件
這個主要用于自動化場景中,CDM配置了定時任務,周期去讀取源端文件,但此時源端的文件正在生成中,CDM此時讀取會造成重復寫入或者是讀取失敗。所以,可以在源端作業參數中指定啟動作業標識文件為“ok.txt”,在源端生成文件成功后,再在文件目錄下生成“ok.txt”,這樣CDM就能讀取到完整的文件。
另外,可以設置超時時間,在超時時間內,CDM會周期去查詢標識文件是否存在,超時后標識文件還不存在的話,則作業任務失敗。
啟動作業標識文件本身不會被遷移。
- 作業成功標識文件
文件系統為目的端的時候,當任務成功時,在目的端的目錄下,生成一個空的文件,標識文件名由用戶來指定。一般和“啟動作業標識文件”搭配使用。
這里需要注意的是,不要和傳輸的文件混淆,例如傳輸文件為finish.txt,但如果作業成功標識文件也設置為finish.txt,這樣會造成這兩個文件相互覆蓋。
- 過濾器
使用CDM遷移文件的時候,可以使用過濾器來過濾文件。支持通過通配符或時間過濾器來過濾文件。
?選擇通配符時,CDM只遷移滿足過濾條件的目錄或文件。
?選擇時間過濾器時,只有文件的修改時間晚于輸入的時間才會被傳輸。
例如:用戶的“/table/”目錄下存儲了很多數據表的目錄,并且按天進行了劃分:DRIVING_BEHAVIOR_20180101~DRIVING_BEHAVIOR_20180630,保存了DRIVING_BEHAVIOR從1月到6月的所有數據。如果只想遷移DRIVING_BEHAVIOR的3月份的表數據。那么需要在作業第一步指定源目錄為“/table”,過濾類型選擇“通配符”,然后指定“路徑過濾器”為“DRIVING_BEHAVIOR_201803*”。
文件格式問題解決方法
1.數據庫的數據導出到CSV文件,由于數據中含有分隔符逗號,造成導出的CSV文件中數據混亂。
CDM提供了以下幾種解決方法:
a.指定字段分隔符
使用數據庫中不存在的字符,或者是極少見的不可打印字符來作為字段分隔符。例如:可以在目的端指定“字段分隔符”為“%01”,這樣導出的字段分隔符就是“\u0001”,詳情可見表上表 特殊字符對應的 URL 編碼。
b.使用包圍符
在目的端作業參數中開啟“使用包圍符”,這樣數據庫中如果字段包含了字段分隔符,在導出到CSV文件的時候,CDM會使用包圍符將該字段括起來,使之作為一個字段的值寫入CSV文件。
2.數據庫的數據包含換行符
場景:使用CDM先將MySQL中的某張表(表的某個字段值中包含了換行符\n)導出到CSV格式的文件中,然后再使用CDM將導出的CSV文件導入到MRS HBase,發現導出的CSV文件中出現了數據被截斷的情況。
解決方法:指定換行符。
在使用CDM將MySQL的表數據導出到CSV文件時,指定目的端的換行符為“%01”(確保這個值不會出現在字段值中),這樣導出的CSV文件中換行符就是“%01”。然后再使用CDM將CSV文件導入到MRS HBase時,指定源端的換行符為“%01”,這樣就避免了數據被截斷的問題。