如果只指定文件名而沒有指定文件路徑,則默認會使用系統屬性參數DIR_HOME:
跨平台的文件路徑
如果想要指定跨平台的文件名,則使用FILE_GET_NAME函數,該函數會將邏輯文件名與邏輯文件路徑轉換成服務器所運行的平台下的物理文件名與路徑,但邏輯文件名與路徑需要使用FILE事務碼先來定義。
FILE_GET_NAME:能將SAP中通過FILE事務碼定義的與操作系統無關(platform-independent)邏輯文件名轉換成與平台相關的物理文件名。邏輯文件名通過下面的FILE事務碼來配置。
列出服務器上的目錄:al11
配置邏輯文件
第一步.建立操作系統的分類:如下面SAP系統已經建立了常用的操作系統分類,如DOS、UNIX、MAC、WIN幾類操作系統。
第二步.創建操作系統名。此過程需要費用第一步所創建的操作系統分類
第三步.創建邏輯文件路徑。在創建的過程中,引用了第一步創建的操作系統分類(Syntax group),而不是第二步創建的操作系統,這里有怪,而且到目前止第二步創建出來的操作系名用在什么地方。
這一步定義邏輯文件路徑會間接(在運行時)使用到了第四步中定義的邏輯文件名(通過<FILENAME>參數在運行時動態的將第四步邏輯文件名轉換為實際的物理文件名,<FILENAME>就是在運行時第四步轉換過來的物理文件名)
在創建邏輯文件路徑時,需要填寫物理路徑 Physical path,這個物理路徑並不是我們平時講的單純文件路徑,其實它除了前半部分單純的文件路徑外(這里為<P=DIR_GLOBAL>),還是后半部分的文件名(這里為<FILENAME>),所以邏輯文件路徑並不只是定義了單純的文件路徑信息,而是某個文件的完整路徑信息(路徑+文件名)。
在這里Physical path字段可以使用一些預定義的占位符(如這里的<P=DIR_GLOBAL>、<FILENAME>),可以按F1查看所允許的預定符:
Reserved Word Replacement Text
<OPSYS> |
Operating system in call |
<INSTANCE> |
R/3 application instance |
<SYSID> |
R/3 application name in SY-SYSID |
<DBSYS> |
Database system in SY-DBSYS |
<SAPRL> |
R/3 release in SY-SAPRL |
<HOST> |
Host name in SY-HOST |
<CLIENT> |
Client in SY-MANDT |
<LANGUAGE> |
Log on language in SY-LANGU |
<DATE> |
Date in SY-DATUM |
<YEAR> |
Year in SY-DATUM, 4-character |
<SYEAR> |
Year in SY-DATUM, 2-character |
<MONTH> |
Month in SY-DATUM |
<DAY> |
Day in SY-DATUM |
<WEEKDAY> |
Day of the week in SY-FDAYW |
<TIME> |
Time in SY-UZEIT |
<STIME> |
Hour and minute in SY-UZEIT |
<HOUR> |
Hour in SY-UZEIT |
<MINUTE> |
Minute in SY-UZEIT |
<SECOND> |
Seconds in SY-UZEIT |
<PARAM_1> |
External parameter 1這個以及下面兩個會使用FILE_GET_NAME函數的PARAMETER_1/2/3參數值來替換 |
<PARAM_2> |
External parameter 2 |
<PARAM_3> |
External parameter 3 |
<P=name> |
Name of a profile parameter這個使用的是RZ11事務碼定義的全局參數名 |
(see Report RSPARAM for valid values) |
|
<V=name> |
|
(stored in variable table) |
|
<F=name> |
Return value of a function module這個會使用“FILENAME_EXIT_”+ name 所組成的函數的返回 |
Naming convention for this function module:值來替換這個占位符。以“FILENAME_EXIT_”打頭的函數為 |
|
FILENAME_EXIT_name系統提供的,所以如果要使用自定義函數,則要使用以下兩個占位 |
|
<Y=name> |
Return value of a function module以下兩個占位符的用意是為了上述所預定義的占位不滿我們要求 |
Naming convention for this function module:時,我們可以自定義這些占位符,並且這些占位符的取值來自於我 |
|
Y_FILENAME_EXIT_name們自定義的函數,這樣可以滿足根據自定義業務邏輯來生成文件名 |
|
<Z=name> |
Return value of a function module |
Naming convention for this function module:EXIT單詞在SAP里表示出口的意義,出口在很多地方都是這樣表 |
|
Z_FILENAME_EXIT_name示的 |
第四步.創建邏輯文件名。該步創建的邏輯文件名與上一將創建出來的邏輯文件路徑關聯起來
FILE_GET_NAME
使用上面第四步創建的邏輯文件名,服務器所在的操作環境為UNIX。
DATA: encoding TYPE filename-fileformat.
DATA: physical_filename TYPE string.
CALL FUNCTION 'FILE_GET_NAME'
EXPORTING
* CLIENT = SY-MANDT
logical_filename = 'ARCHIVE_BI_PROTOCOL_DATA_FILE'
* OPERATING_SYSTEM = SY-OPSYS
parameter_1 = 'PARAMETER_1'
parameter_2 = 'PARAMETER_2'
parameter_3 = 'PARAMETER_3'
* USE_PRESENTATION_SERVER = ' '
* WITH_FILE_EXTENSION = ' '
* USE_BUFFER = ' '
* ELEMINATE_BLANKS = 'X'
* INCLUDING_DIR = ' '
IMPORTING
* EMERGENCY_FLAG =
file_format = encoding
file_name = physical_filename
* EXCEPTIONS
* FILE_NOT_FOUND = 1
* OTHERS = 2
.
WRITE: / physical_filename, ' ', encoding.
/usr/sap/D06/SYS/global/PARAMETER_1_PARAMETER_3_20111116_145730_PARAMETER_2.ARCHIV
打開文件OPEN DATASET
OPEN DATASET dset FOR access IN mode [position]
[os_addition]
[error_handling].
Dest:目標文件名
sy-subrc |
Description |
0 |
File was opened. |
8 |
Operating system could not open file. |
每個Session最多可以打開100個文件,但具體要看OS。
打開方式access
INPUT
以讀取方式打開文件,默認情況下打開時文件指針指向文件開始的地方,如果文件不存在,則sy-subrc為8。如果文件已經打開,文件指針復位到文件的起始位置。
OUTPUT
以寫的方式打開文件(但也允許讀),如果指定的文件已經存在,則內容會被刪除。如果指定的文件不存在,則會創建一個新的文件。
APPENDING
以追加寫的方式打開文件。如果文件已經存在,則文件指針會指向文件內容最后,如果文件不存在,則會創建。如果試着通過READ DATASET讀取使用FOR APPENDING 方式打開的文件,則sy-subrc為4
UPDATE
以更新的方式打開文件,默認情況下打開時文件指針指向文件開始的地方。如果文件不存在,則sy-subrc為8
文件指針位置position
... AT POSITION pos ...
位置是按照字節來算的,文件的開始位置為0,如果置為-1,則會定位到文件末尾。
請注意以下特殊情況:
1、 在讀取文件時,如果 pos 的值大於了文件的長度,將讀取不到數據。
2、 在寫文件時,如果文件指針指向了文件開始的后面的某個位置上,則從文件開始的地方到指定的 pos 止,都會使用0來填充。
3、 如果是在APPEND模式打開文件,則會忽略到 pos ,仍然從文件的最末開始附加。
4、 如果是修改文件,並且 pos 的值大於了文件的長度,則從文件末到 pos 位置都會設置成0,更新的的內容會從pos向后寫。
注,該選項不能與FILTER選項同時使用。
由於文件可以大於2GB,所以 pos 要使用 P 類型來定義,而不能再使用 I 類型。
文件指定位置可以使用SET DATASET來修改。
在對文本文件進行指針定位時,要考慮到文件頭部是否帶有BOM,以及end-of-line marking。
打開模式mode
... {BINARY MODE}
| {TEXT MODE encoding [linefeed] }...
二進制模式BINARY MODE
If you read from or write to a file that is open in binary mode, the data is transferred byte by byte.When writing to a binary file, the binary content of a data object is transferred in unchanged form(使用未轉換形式) into the file. When reading from a binary file, the binary content of the file is transferred in unchanged form into a data object.
字符模式TEXT MODE encoding [linefeed]
If the data type is character-type and flat(如果C類型), trailing blanks are cut off. In the data type string, trailing blanks are not cut off.
If you read from or write to a file that is open in text mode, the data is transferred line by line
如果沒有指定行結束尾符linefeed,則默認使用當前服務器所在平台的行結尾符。
讀取文件時,是以行為單位一行一行的讀取。
行結尾符可以通過linefeed專門指定。
在Unicode 系統中,只有character-type的數據對象才能用來傳輸Text文件。
在Unicode 系統中,必須指定encoding。
字符編碼encoding
... ENCODING { DEFAULT
| {UTF-8 [SKIPPING|WITH BYTE-ORDER MARK]} } ...
l DEFAULT
在Unicode 系統中,默認使用UTF-8編碼
l UTF-8
可以使用CL_ABAP_FILE_UTILITIES的CHECK_UTF8方法來文件是否是UTF-8編碼的文件
另外,CL_ABAP_FILE_UTILITIES的CHECK_FOR_BOM方法可以用來檢測文件頭部是否帶有字節序,而CREATE_UTF8_FILE_WITH_BOM方法可以創建一個帶有UTF-8字節序的文件。
注:在SAP中,A UTF-16 file can only be opened as a binary file.
byte order mark (BOM):字節序,UTF-8的BOM為EF BB BF。
l ... SKIPPING BYTE-ORDER MARK
只允許FOR INPUT or FOR UPDATE時使用,如果有BOM,則在讀取或更新時會忽略掉BOM,即在讀取時文件指針會設置在BOM的后面。如果省略掉該選項,則BOM會當作普通文件內容來處理。
l ... WITH BYTE-ORDER MARK
該選項只允許在FOR OUTPUT情況下使用,並且會向文件頭部插入BOM,如果沒有加上該選項,則不會插入。
注:BYTE-ORDER MARK 選項不能與AT POSITION pos同時使用。
當使用UTF-8讀取一個文件時,推薦使用SKIPPING BYTE-ORDER MARK選項,以防BOM被當作普通文件內容讀取出來;另外,為了使所有閱讀器都可以讀取SAP創建的UTF-8格式文件,推薦使用WITH BYTE-ORDER MARK選項。
換行符linefeed
... WITH { NATIVE
| UNIX
| WINDOWS } LINEFEED ...
line end marker:行結束標記
CRLF:Carriage-Return Line-Feed ,就是回車(CR, ASCII 13, \r) 換行(LF, ASCII 10, \n)。這兩個ACSII字符不會在屏幕有任何輸出,但在Windows中廣泛使用來標識一行的結束。而在Linux/UNIX系統中只有換行符。許多網絡協議,包括HTTP也使用CRLF來表示每一行的結束。CR和LF是在計算機終端還是電傳打印機的時候遺留下來的東西。電傳打字機就像普通打字機一樣工作。在每一行的末端,CR命令讓打印頭回到左邊。LF命令讓紙前進一行。雖然使用卷紙的終端時代已經過去了,但是,CR和LF命令依然存在,許多應用程序和網絡協議仍使用這些命令作為分隔符。
如果當指定了linefeed選項后,則全局參數abap/NTfmode(RZ11)會忽略,同時TYPE attr選項不能使用。
如果沒有指定該選項,則line end marker依賴於平台:
1、The line end marker for Unix is "LF".
2、 The line end marker for MS Windows is "CRLF".然而,如果是在MS Windows操作系統下,則全局屬性參數abap/NTfmode可以決定使用"LF"還是"CRLF",如果該參數的值為"b",則使用"LF";如果為"t"或者初始值,則使用"CRLF"。另外abap/NTfmode可以覆蓋TYPE attr選項。如果在沒有使用linefeed選項,又沒有使用TYPE attr選項時,打開一個文件時會搜索第一行的line end marker ("LF" or "CRLF"),並用作整個文件中,如果沒有找到,則會使用abap/NTfmode設置的值。
如果使用了WITH NATIVE|SMART|UNIX|WINDOWS LINEFEED選項,這些設置還可以使用SET DATASET語句來修改這些設置,如果沒有使用,則line end marker不能使用SET DATASET語句來修改line end marker。
可以通過GET DATASET語句獲取當前正在使用的line end marker。
l WITH NATIVE LINEFEED
根據當前服務器所在的操作系統來決定。i.e. "LF" for Unix OS390 or OS400, and "CRLF" for MS Windows.
l WITH UNIX LINEFEED
固定使用The line end marker is set to "LF",即文件的每行(一個TRANSFER ...TO ...語句就表示向文件寫一行)都會以“0A”結尾。
l WITH WINDOWS LINEFEED
固定使用The line end marker is set to "CRLF",即文件的每行(一個TRANSFER ...TO ...語句就表示向文件寫一行)都會以“0D0A”結尾。
操作系統選項os_addition
... [TYPE attr]
[FILTER opcom] ... .
TYPE
沒有實質上的用處
FILTER
將輸入輸出流過濾。opcom為服務器相應的所在操作系統的命令串。
通常情況下,我們是從標准的STDOUT、STDIN管道讀取或寫入數據,如果我要對數據進行壓縮之類的動作,則可以加上過濾器。
注:不能與AT POSITION 、 FOR UPDATE選項同時使用。
下面在Unix系統中,對數據輸入時進行壓縮,在輸出時進行解壓操作:
DATA file TYPE string VALUE `/usr/test.Z`.
OPEN DATASET file FOR OUTPUT IN BINARY MODE
FILTER 'compress'.
...
CLOSE DATASET file.
OPEN DATASET file FOR INPUT IN BINARY MODE
FILTER 'uncompress'.
...
CLOSE DATASET file.
出錯處理error_handling
... [MESSAGE msg]
[IGNORING CONVERSION ERRORS]
[REPLACEMENT CHARACTER rc] ... .
該選項允許你接收操作系統的消息,壓制異常信息,以及定義出錯時未知字符的替換字符。不能轉換的字符會默認會使用“#”替換,除非使用REPLACEMENT CHARACTER指定。
DATA mess TYPE string.
OPEN DATASET `` FOR INPUT IN BINARY MODE MESSAGE mess.
IF sy-subrc = 8.
WRITE: / mess.
ENDIF.
No such file or directory
寫文件TRANSFER
TRANSFER dobj TO dset [LENGTH len]
[NO END OF LINE].
DATA: file TYPE string VALUE `flights.dat`,
wa TYPE spfli.
FIELD-SYMBOLS <fs_hex> TYPE x.
OPEN DATASET file FOR OUTPUT IN BINARY MODE.
SELECT *
FROM spfli
INTO wa.
ASSIGN wa TO <fs_hex> CASTING.
"寫進去的是二進制,打開文件看到的會是亂碼
TRANSFER <fs_hex> TO file.
ENDSELECT.
CLOSE DATASET file.
LENGTH選項:
決定了多少個字符或多少個字節將被寫入到文件中。如果len的值大於了dobj數據對象所存儲的字符或字節數時,則使用十六進制0或者空格來替換缺失的字節或字符(至於是字節還是字符則依賴於文件打開模式)
NO END OF LINE選項:
用來控制是否在以文本模式寫入文件時,在每次傳輸完后是否加上換行符。
如果是使用文本模式打開並寫入文件時,默認就會在每次傳輸完成后加上換行符。
讀取READ DATASET
READ DATASET dset INTO dobj [MAXIMUMLENGTH mlen][[ACTUAL] LENGTH alen]
如果沒有指定MAXIMUM LENGTH或者指定的為負數,則每次讀取多少數據依賴於OPEN DATASET語句所采用的打開模式:如果是以文本模式打開,則每次讀取一行數據,如果是以BIN模式打開,則盡可能多的數據並能填滿dobj,如果指定了MAXIMUM LENGTH則每次讀取mlen個字符(或字節)。
sy-subrc |
Meaning |
0 |
Data was read without reaching end of file.讀到了數據並且沒有達到文件尾 |
4 |
Data was read and the end of the file was reached or there was an attempt to read after the end of the file.讀到了數據且到達了文件尾,或者達到文件尾后再試着讀取 |
DATA: file TYPE string VALUE `flights.dat`,
wa TYPE spfli.
FIELD-SYMBOLS <hex_container> TYPE x.
OPEN DATASET file FOR INPUT IN BINARY MODE.
ASSIGN wa TO <hex_container> CASTING.
DO.
"由於沒有使用MAXIMUM LENGTH選項,所以每次讀取的最大字節數
"由<hex_container>所占字節數決定
READ DATASET file INTO <hex_container>.
IF sy-subrc = 0.
WRITE: / wa-carrid,
wa-connid,
wa-countryfr,
wa-cityfrom,
wa-cityto,
wa-fltime,
wa-distance.
ELSE.
EXIT.
ENDIF.
ENDDO.
CLOSE DATASET file.
修改上面程序,每次讀取時指定所讀取的最大字節數:
DATA: file TYPE string VALUE `flights.dat`,
"緩沖器,用來每次讀取的碼流
hex_container TYPE x LENGTH 1000,
len TYPE i.
FIELD-SYMBOLS <spfli> TYPE spfli.
"獲取<spfli>所占內存的字節數,即為spfli結構類型所占內存大小
DESCRIBE FIELD <spfli> LENGTH len IN BYTE MODE.
OPEN DATASET file FOR INPUT IN BINARY MODE.
"以spfli類型的視圖來看待(操作)緩沖器
ASSIGN hex_container TO <spfli> CASTING.
DO.
"每次讀取指定的長度:len
READ DATASET file INTO hex_container MAXIMUM LENGTH len.
IF sy-subrc = 0.
"將讀取的二進數據以spfli結構類型的視圖展示
WRITE: / <spfli>-carrid,
<spfli>-connid,
<spfli>-countryfr,
<spfli>-cityfrom,
<spfli>-cityto,
<spfli>-fltime,
<spfli>-distance.
ELSE.
EXIT.
ENDIF.
ENDDO.
CLOSE DATASET file.
關閉文件 CLOSE DATASET
CLOSE DATASET dset.
刪除文件 DELETE DATASET
DELETE DATASET dset.