在很多ABAP開發中,我們使用CSV文件,有時候,關於CSV文件本身的一些問題使人迷惑。它僅僅是一種被逗號分割的文本文檔嗎?
讓我們先來看看接下來可能要處理的幾個相關組件的詞匯的語義。
Separator:兩個字段之間的界線,在CSV文件中即是“,”。
Delimiter:這種符號的開端和結束,代表了某種東西的界限。舉個例子“測試字符串”有兩個delimiters,即兩個雙引號。在文本中包含很多逗號的情形下,CSV文件會使用雙引號作為Delimiter.
Terminator : 代表片段的結束。在CSV文件中,我們可以把換行看成terminator.
如果我們不確定逗號或者雙引號是否被允許在數據內出現,請看CSV的說明書:
假如你想看CSV的全部標准的話,這里是CSV的實際標准。
http://tools.ietf.org/html/rfc4180
CSV格式的定義
1, 每條記錄位於單獨的行上,由換行符分隔。
2, 最后一條記錄的換行符可有可無。
3, 文件的第一行可以有一個可選的頭部,其格式與普通行相同。
4, 在頭部和每條記錄中,可以存在一個或多個字段,由逗號分割。整個文件中的每行應當包含同樣數量的字段。空格被視為字段的一部分,不會被忽略。記錄的最后一個字段的后面不可以存在逗號。
5, 每個字段可以被雙引號包圍,也可以不這樣做。(然而在某些程序中,比如Microsoft Excel, 完全不使用雙引號)。如果字段沒有被雙引號包圍,那么雙引號不會在字段內部出現。
6, 字段在包含換行符、雙引號和逗號的情況下應當被雙引號包圍。
7, 如果雙引號被用作包圍字段,而字段內部出現的雙引號需要通過使用另一對雙引號將其包圍的方式轉義處理。
在我的經驗中,第七點是最容易被坑的地方。CSV作為由逗號分隔的值,給人帶來了一種印象即逗號是separator並且給出的excel中不含逗號,這樣容易造成混淆。
那么看幾個例子:
基本例子:
10, Vikas , Sydney
數據內部有separator / delimiter的:
"11", "Vikas", "Sydney, AU" <-- 數據中包含逗號
"12", "Vikas", "Sydney, "NSW" AU" <-- 數據包含逗號和雙引號
ABAP中的相關操作
假設我們讀取一個文件,這個文件可以從用戶的桌面上傳或者從服務器端讀取。
1) 寫下你的代碼
這個在一開始很簡單,但隨着時間的進行,它可能變得復雜。
以字符串格式獲取數據,使用逗號分割他們:
split lv_data at ',' into lw_struct-test1 lw_struct-test2 lw_struct-test3.
缺點:
a) 如果我們的數據中有separator, terminator 或者delimiter,這個就不管用了。(也就是說需要數據中不存在逗號、雙引號或者換行符)
b) 一旦格式改變,代碼必須隨之更新——意思是如果我們增加了一個新的字段test4,那么代碼就要變為:
split lv_data at ',' into lw_struct-test1 lw_struct-test2 lw_struct-test3 lw_struct-test4.
2) 使用KCD_CSV_FILE_TO_INTERN_CONVERT讀取文件
CALL FUNCTION 'KCD_CSV_FILE_TO_INTERN_CONVERT' EXPORTING i_filename = 'C:\Temp\Upload.csv' i_separator = ',' TABLES e_intern = gt_intern EXCEPTIONS upload_csv = 1 upload_filetype = 2.
缺點:
a) 文件只能從表示服務器/桌面中讀取。注:有關表示服務器(Presentation Server)的內容,請參考SAP系統架構的相關內容。
b) 如果CSV文件中存在雙引號,最后一個字段會保留雙引號。(待驗證)
c) 在文件從服務端讀取的情況下,我們需要閱讀這個函數的內部代碼,並且寫一些自定義的邏輯。
3) 通過函數模塊 RSDS_CONVERT_CSV使用RTTI和動態編程
這是一個有效的辦法,但是包含了大量的代碼。你可以看看這個GIST中的代碼:
總的來說步驟是這樣的:
——使用RTTI獲得目的表的結構
——使創建field catalog
——根據field catalog創建動態內表
——使處理原始CSV數據
——使將CSV數據存儲在動態內表中
缺點:
a) 長代碼所具有的缺點,特別是在你打算從零開始編寫它的情況下。
優點:
a) 代碼從目標表的格式中解放了。如果一個新的字段被添加,只需要從z_data_tty中更新表類型。
4) 使用類CL_RSDA_CSV_CONVERTER
可以很直接地調用它——使用separator 和delimiter初始化類。對於一個普通的CSV文件,使用默認參數。
* Instantiate the CSV object call method cl_rsda_csv_converter=>create * EXPORTING * i_delimiter = C_DEFAULT_DELIMITER * i_separator = C_DEFAULT_SEPARATOR receiving r_r_conv = lo_csv * Process records loop at lt_upload_data into lv_data. CALL METHOD lo_csv->csv_to_structure EXPORTING i_data = lv_data IMPORTING e_s_data = lw_struct.
endloop.
就是這樣!
優點:
a) 代碼量很小——相比上面的第三種方案,減少了我們犯錯的機會。
b) 代碼與文件結構無關——我們保持了上面方案的優點。
c) 無論是應用服務器,還是表示服務器,它都適用——當然在這之前我們必須讀取文件。
d) 開發者已經在方法CSV_TO_STRUCTURE中為例子寫下了詳盡的文檔。要大大地感謝他/她!
e) 它是RSDA包的一部分,RSDA包目前在ABAP實驗環境中同樣存在,比如NSP。
如果你懶得鍵入全部程序,這里有全部源代碼:
本文鏈接:http://www.cnblogs.com/hhelibeb/p/5793215.html
原文鏈接:Understanding CSV files and their handling in ABAP
轉載請注明