使用CL_ABAP_GZIP_TEXT_STREAM的并发压缩流

2020-09-09 17:00发布

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


嗨,

使用CL_ABAP_GZIP_TEXT_STREAM时,它需要一个缓冲接口if_abap_gzip_text_handler〜use_out_buf,该接口被定义为静态接口。

当我需要单个压缩流时,这很好用。 例如。 遍历单个表,使用单个gzip流将数据写出。

但是,当我需要多个独立的并发压缩流(将记录并发写入多个文件)时,这将不起作用,因为user_outbuf类具有静态变量/方法,这意味着缓冲区值将混合在一起。 例如。 遍历一个表将其记录写出,并查询另一张表以获取相关记录并写出相同类型user_outbuf的不同压缩流。

是否有更干净的方法来解决此问题,而不是一遍又一遍地重新定义具有不同名称的相同类以获得并发支持? 例如 (复制类定义/实现),然后引用:
uref1 TYPE REF to user_outbuf1,
uref2 TYPE REF TO user_outbuf2,
etc

谢谢,
周杰伦:)

示例代码:

报告测试。

 "定义一个缓冲区处理程序类
 CLASS user_outbuf定义。
   公共部分。
     接口if_abap_gzip_text_handler。
     类别数据:
          缓冲区类型x长度1000,"缓冲区的预定义大小
          buffer_len TYPE I VALUE -1。  " -1表示缓冲区的总长度
 ENDCLASS。

 类别user_outbuf IMPLEMENTATION。
   方法if_abap_gzip_text_handler〜use_out_buf。
    写:/缓冲区。
   终结法。
 ENDCLASS。

 选择开始。

 数据:
       uref TYPE REF to user_outbuf,
       uref2 TYPE USER_OUTBUF,
       csref TYPE REF TO CL_ABAP_GZIP_TEXT_STREAM。

 "创建缓冲区的副本
 创建对象uref。
 "创建gzip压缩类的副本
 创建对象csref
    导出转换='默认'
               OUTPUT_HANDLER =尿素。
 "设置缓冲区
 csref-> set_out_buf(
   输入
       out_buf = uref->缓冲
       out_buf_len = uref-> buffer_len
 )。
 压缩一些数据
 调用方法csref-> compress_text_stream
     出口
       TEXT_IN ='一些文字'
       TEXT_IN_LEN = -1。
 调用方法csref-> compress_text_stream_end
     EXPORTING TEXT_IN ='最后一个文本'
                TEXT_IN_LEN = -1。
 "创建一个新的缓冲区,
 ",因为if_abap_gzip_text_handler〜use_out_buf是静态的
 "缓冲区变量也必须是静态的,因此,
 "不能在另一个压缩实例中同时重用
 创建对象uref2。
 写:/uref2->缓冲区。
 

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


嗨,

使用CL_ABAP_GZIP_TEXT_STREAM时,它需要一个缓冲接口if_abap_gzip_text_handler〜use_out_buf,该接口被定义为静态接口。

当我需要单个压缩流时,这很好用。 例如。 遍历单个表,使用单个gzip流将数据写出。

但是,当我需要多个独立的并发压缩流(将记录并发写入多个文件)时,这将不起作用,因为user_outbuf类具有静态变量/方法,这意味着缓冲区值将混合在一起。 例如。 遍历一个表将其记录写出,并查询另一张表以获取相关记录并写出相同类型user_outbuf的不同压缩流。

是否有更干净的方法来解决此问题,而不是一遍又一遍地重新定义具有不同名称的相同类以获得并发支持? 例如 (复制类定义/实现),然后引用:
uref1 TYPE REF to user_outbuf1,
uref2 TYPE REF TO user_outbuf2,
etc

谢谢,
周杰伦:)

示例代码:

报告测试。

 "定义一个缓冲区处理程序类
 CLASS user_outbuf定义。
   公共部分。
     接口if_abap_gzip_text_handler。
     类别数据:
          缓冲区类型x长度1000,"缓冲区的预定义大小
          buffer_len TYPE I VALUE -1。  " -1表示缓冲区的总长度
 ENDCLASS。

 类别user_outbuf IMPLEMENTATION。
   方法if_abap_gzip_text_handler〜use_out_buf。
    写:/缓冲区。
   终结法。
 ENDCLASS。

 选择开始。

 数据:
       uref TYPE REF to user_outbuf,
       uref2 TYPE USER_OUTBUF,
       csref TYPE REF TO CL_ABAP_GZIP_TEXT_STREAM。

 "创建缓冲区的副本
 创建对象uref。
 "创建gzip压缩类的副本
 创建对象csref
    导出转换='默认'
               OUTPUT_HANDLER =尿素。
 "设置缓冲区
 csref-> set_out_buf(
   输入
       out_buf = uref->缓冲
       out_buf_len = uref-> buffer_len
 )。
 压缩一些数据
 调用方法csref-> compress_text_stream
     出口
       TEXT_IN ='一些文字'
       TEXT_IN_LEN = -1。
 调用方法csref-> compress_text_stream_end
     EXPORTING TEXT_IN ='最后一个文本'
                TEXT_IN_LEN = -1。
 "创建一个新的缓冲区,
 ",因为if_abap_gzip_text_handler〜use_out_buf是静态的
 "缓冲区变量也必须是静态的,因此,
 "不能在另一个压缩实例中同时重用
 创建对象uref2。
 写:/uref2->缓冲区。
 
付费偷看设置
发送
5条回答
Aaron 3364
1楼 · 2020-09-09 17:30.采纳回答
  1. 您的代码没有并行压缩,因此无法反映您的问题。
  2. 您会收到GZIP实例(参数GZIP_STREAM),因此,如果保留了与该GZIP实例相对应的输出处理程序 ,您将能够确定正确的输出处理程序(我承认SAP设计很奇怪)。
  3. 为什么需要并行压缩?
Alawn_Xu
2楼-- · 2020-09-09 17:39
< p>一种有趣的方法,在其间使用" shim"层来选择正确的流/缓冲区,这似乎确实有效! 感谢您的示例:D

浮生未央
3楼-- · 2020-09-09 17:38

我不确定我是否理解您的问题,但是我认为这段代码可以帮助您解决。

报告zzzjc_test01。

 "定义一个缓冲区处理程序类
 类user_outbuf定义。
   公共部分。
     接口if_abap_gzip_text_handler。
     类数据:
       缓冲区类型x长度1000,"缓冲区的预定义大小
       buffer_len类型i值为-1。  " -1表示缓冲区的总长度
 结束类。

 类user_outbuf实现。
   方法if_abap_gzip_text_handler〜use_out_buf。
     写:/缓冲区。
   方法。
 结束类。

 选择开始。

   类型以lty_list_buffers开头。
   类型uref类型ref到user_outbuf。
   类型csref类型ref到cl_abap_gzip_text_stream。
   输入lty_list_buffers的结尾。

   类型lty_list_buffers_tt类型为lty_list_buffers的标准表,带有空键。

   数据lt_list_buffers类型为lty_list_buffers_tt。

   您输入的文本作为一个行程表
   数据lt_input_text类型带空键的字符串标准表。

   循环在lt_input_text分配字段符号()。

     将初始行附加到分配field-symbol()的lt_list_buffers。

      -uref =新的user_outbuf()。

      -csref
         =新的cl_abap_gzip_text_stream(
             conversion ='DEFAULT'
             output_handler =  -uref)。

      -csref-> set_out_buf(
         输入
         out_buf =  -uref->缓冲区
         out_buf_len =  -uref-> buffer_len
     )。

      -csref-> compress_text_stream(
       出口
         text_in = 
         text_in_len = -1
     )。

      -csref-> compress_text_stream_end(
       出口
         text_in = 
         text_in_len = -1
     )。

   结束循环。

   在lt_list_buffers分配处循环。
     写入/ -uref->缓冲区。
   结束循环。
 
葫芦娃快救爷爷
4楼-- · 2020-09-09 17:43

嗨,桑德拉,胡安,

非常感谢您的回复。 :)

>>第1点-代码无法反映问题

该代码旨在演示使用uref之后创建的新缓冲区引用uref2(请注意名称末尾的2)为缓冲区值提供了相同的值,从而表明它们无法使用 同时由于静态变量缓冲区。 如果同时创建两个或更多压缩流,则它们的数据将交织并损坏。

>>第3点-为什么需要并行压缩

说我需要从BKPF(日记标题)和BSEG(日记条目)中提取特定记录,我首先查询BKPF并遍历每条记录,但是对于覆盖率记录,我从BSEG查询给定的相关日记帐行 BKPF标头。 这两个表同时(并行)流式传输到不同的文件中,分别命名为BKPF.csv.gz和BSEG.csv.gz ...

>>胡安的例子

是的,您的示例在串行写入独立文件时有效,但如果我们需要同时写入不同文件,则它们将无效,因为它们都使用同一类user_outbuf,该类使用静态类数据缓冲区,这意味着所有实例都共享 相同的缓冲区变量值(如我的示例所示-后两行)。

>> Sandra的观点2-SAP设计很奇怪

是的,我同意。 看起来它被设计为可在同一缓冲区类中随时使用一次。

>>到目前为止的想法/选择:

1)为我们打算同时使用的每个实例(bkpf_outbuf,bseg_outbuf等)定义一个缓冲区类。 这听起来不像是一个好的OO设计,尤其是如果我们不知道在运行时需要多少级(类)的话。

2)获取SAP软件包CL_ABAP_GZIP_TEXT_STREAM的本地副本,并调整接口,使其不是静态的,那么这个问题应该消失(我希望)。

谢谢,
Jay:)

SKY徐
5楼-- · 2020-09-09 17:22

对此进行了快速更新,试图克隆CL_ABAP_GZIP_TEXT_STREAM程序包,但是它具有内核方法引用,需要对abkmeth.seg进行编辑。 文件( https://help.sap.com/doc/abapdocu_752_index_htm /7.52/zh-CN/abenkernel_methods.htm )(可以通过RSKMETH查看定义)在新软件包中启用。 不幸的是,这似乎并不适合运输。

相反,将尝试另一个建议的选项,为每个表名称定义一个缓冲区类。 :(

一周热门 更多>