服务器端文件处理

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4293548.html

跨平台的文件路径... 364

配置逻辑文件... 365

FILE_GET_NAME. 367

打开文件OPEN DATASET. 367

打开方式access. 368

INPUT. 368

OUTPUT. 368

APPENDING.. 368

UPDATE. 368

文件指针位置position. 368

打开模式mode. 368

二进制模式BINARY MODE. 368

字符模式TEXT MODE encoding [linefeed]369

字符编码encoding. 369

换行符linefeed. 369

操作系统选项os_addition. 370

TYPE. 370

FILTER. 370

出错处理error_handling. 370

写文件TRANSFER. 371

读取READ DATASET. 371

关闭文件 CLOSE DATASET. 372

删除文件 DELETE DATASET. 372

获取打开文件属性GET DATASET

如果只指定文件名而没有指定文件路径,则默认会使用系统属性参数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>


Name of a variable这个使用的是就是FILE事务码中选项里所定义的变量

 
(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]} } ...

DEFAULT

在Unicode 系统中,默认使用UTF-8编码

UTF-8

可以使用CL_ABAP_FILE_UTILITIESCHECK_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。

... SKIPPING BYTE-ORDER MARK

只允许FOR INPUT or FOR UPDATE时使用,如果有BOM,则在读取或更新时会忽略掉BOM,即在读取时文件指针会设置在BOM的后面。如果省略掉该选项,则BOM会当作普通文件内容来处理。

... 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。

WITH NATIVE LINEFEED

根据当前服务器所在的操作系统来决定。i.e. "LF" for Unix OS390 or OS400, and "CRLF" for MS Windows.

WITH UNIX LINEFEED

固定使用The line end marker is set to "LF",即文件的每行(一个TRANSFER ...TO ...语句就表示向文件写一行)都会以“0A”结尾。

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.

获取打开文件属性GET DATASET

时间: 2024-12-09 23:04:32

服务器端文件处理的相关文章

服务器端文件分片合并的思考和实践

笔者在项目中处理大文件上传的需求,仿照七牛云存储的接口设计.然而,在服务器端文件合并时遇到了很大的问题:合并太慢.本文记录了当时的思路和解决的方案 大文件的需求 文件上传是个很常见的需求.尽管HTTP是基于TCP上层的协议,但是HTTP协议本身并不适合处理超大的请求体,文件上传有很大的稳定性问题,如果中途断开了,将前功尽弃.为了改善用户体验或者缓解服务器压力,通常会考虑将文件分成小片,将小片一个个上传,如果中途断开了也能从某个失败的小片开始继续上传. 在前端的处理上,对于Web页面,可以采用pl

libcurl以get方式请求服务器端文件

static size_t callbackfunction(void *ptr, size_t size, size_t nmemb, void* userdata){    FILE* stream = (FILE*)userdata;    if (!stream) {        printf("!!! No stream\n");        return 0;    } size_t written = fwrite((FILE*)ptr, size, nmemb, s

上传图片或文件到服务器端

新建一个线程: new Thread(uploadImageRunnable).start(); Runnable uploadImageRunnable = new Runnable() { @Override public void run() { if(TextUtils.isEmpty(imgUrl)){ Toast.makeText(mContext, "还没有设置上传服务器的路径!", Toast.LENGTH_SHORT).show(); return; } Map<

flask服务器端接收文件上传

# 从request里面取出客户端传过来的文件,# 在服务器端打开一个文件# 读request里面的文件内容# 将读取的文件内容写入服务器端打开的文件# 关闭服务器端文件@app.route('/upload',methods=['POST'])def upload(): file_obj = request.files.get('pic') if file_obj: f = open('./demo.jpg','wb') data = file_obj.read() f.write(data)

任意文件上传漏洞

漏洞产生原因:①代码层:开发者在编写代码的时候不严谨,未对文件上传的合法性进行检验: ②应用层:web容器漏洞,cgi,配置不当: 有网站到服务器上传文件的常用检测手段:①js(一般是检测文件后缀名)-可修改本地js代码或通过浏览器自带功能"No-script"进行绕过: ②服务器端MIME检测-对contenttype的额检测:   ③服务端目录路径检测,一般是检测目录路径是否合理,漏洞原因是对目录路径的检测不够严谨,可以用0x00截断进行攻击 ④服务器端文件拓展名检测绕过,分为白名

谢烟客---------Linux之文件系统管理创建与挂载

文件系统在哪实现? 内核 内核级文件系统的组成?模块.用户空间中的程序 哪些是内核级文件系统?除了分布式文件系统 模块的定义 中间层定义 文件如何按名存取 查找文件.创建文件.存储文件文件系统.格式化 swap,虚拟内存 日志型文件系统和非日志型文件系统工作原理 超级块 文件按名存取的实现 文件系统实现按名存取将分区后的存储空间划分为数据区和元数据区. 数据区:   存储大小相同的数据块    元数据区:有多个inode块,每个inode块中存储:filename,perm,owner,grou

[PHP学习教程 - 文件]002.修改上传文件大小限制(File Upload Limit)

引言:通常大家直装xampp之后,默认的文件上传大小应该被设定成2M左右,这个时候如果上传超过2M的东西,就会报错,让人非常尴尬.如何修改呢? 导航索引: 概念 FTP常用API FTP封装类 其他 大家请看下文. 概念 百科定义: FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”.用于Internet上的控制文件的双向传输.同时,它也是一个应用程序(Application). 基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序

java文件批量上传、zip方式批量下载

WEB项目: 后台代码: 1 package com.achong.controller; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedOutputStream; 5 import java.io.File; 6 import java.io.FileInputStream; 7 import java.io.FileOutputStream; 8 import java.io.IOException; 9 i

文件上传(带有预览模式)

这里所讲的预览是将文件上传至后台之后,代码调用服务器端文件,在网页中显示出来 第一:网页显示部分 和  显示区域css样式表 <body> <h1>文件上传</h1> <form action="chuli.php" method="post" enctype="multipart/form-data" id="sc" target="hidden_frame"&g