SAP ABAP转换特殊字符乱码

来源:互联网 发布:java加密软件 编辑:程序博客网 时间:2024/05/21 07:00

问题的起因是通过txt使用ABAP向SAP导数时,某些文字会转换为乱码。

嫌长不看版:codepage使用8402

有问题的文字为下表中未画删除线的文字:

GBK举例表 来自:GBK编码
FE 0 1 2 3 4 5 6 7 8 9 A B C D E F
4 兀 嗀 﨎 﨏 﨑 﨓 﨔 礼 﨟 蘒 﨡 﨣 﨤 﨧 﨨 﨩
5                
6                
7               
8                
9                
A                

GBK的基本姿势

首先GBK是对GB2312的扩展,采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,除去所有7F结尾的编码(xx7F,如上图中FE7F)。
上图左上角的”FE”指的该表格中的文字的编码都是以”FE”开头,第三位要看左边的数字,第四位要看上面的数字,例如“兀”的编码为”FE40”,“”的编码为”FE50”。

GBK的全部编码分为三大部分:
1. 汉字区。
2. 图形符号区。
3. 用户自定义区。
每个部分具体包括哪些请看GBK编码,写的非常清楚。在这里只需要说一下,用户自定义区的范围是:
(1) AAA1-AFFE,码位 564 个。
(2) F8A1-FEFE,码位 658 个。
(3) A140-A7A0,码位 672 个。

GBK编码范围表:wiki-GBK
GBK编码范围表

SAP端的基本姿势

1.WebDynpro中的上传特点

WebDynpro中使用FileUpload控件进行文件的上传,控件的data属性要绑定给一个xstring类型的Attribute(具体如何实现附件上传本文不具体论述)。我们可以读取这个Attribute值,来查看文件传到SAP后端之后的情况。
现在我们先新建一个文本文档,里面只写一个字:“﨩”,没有回车。然后通过WebDynpro的FileUpload控件上传此文件,可以看到后端获取到的值为:”FE4F”。
debug查看上传控件的data属性
我们再查看前面的GBK举例表,在GBK编码中“﨩”的编码也是“FE4F”,这代表着SAP把txt文档的内容直接传到了后台。[注:1]

2.将xstring转为string

我们获取到的xstring是GBK的编码,需要转换为string类型,方法有很多[附:1],但都不是SAP Release的,其中一个方法如下:

  CALL FUNCTION 'HR_KR_XSTRING_TO_STRING'    EXPORTING      from_codepage = lv_encoding      in_xstring    = lv_upload_file    IMPORTING      out_string    = lv_out_string.

其中from_codepage为Frontend codepage,可使用下面的方法进行获取:

  DATA lv_codepage_numc TYPE cpcodepage.  CALL FUNCTION 'NLS_GET_FRONTEND_CP'    EXPORTING      langu                 = sy-langu      fetype                = 'MS'    IMPORTING      frontend_codepage     = lv_codepage_numc    EXCEPTIONS      illegal_syst_codepage = 1      no_frontend_cp_found  = 2      internal_or_db_error  = 3      OTHERS                = 4.  IF sy-subrc <> 0.    RETURN.  ENDIF.

最终获得的codepage为’8404’,传入’HR_KR_XSTRING_TO_STRING’,此时转换正确。
xstring to string

出问题的字符

新建一个文本文档,里面只写一个字:“”,没有回车。然后通过WebDynpro的FileUpload控件上传此文件,可以看到后端获取到的值为:”FE50”。通过查表,可以确定这个“”这个字的GBK编码就是”FE50”。但是使用’HR_KR_XSTRING_TO_STRING’进行转换,得到的string为:”#P”。
做了一个小程序,来查看用到的值
此时我们可以看到转换失败。接下来codepage还用8404,将“”转为xstring,查看一下对应的值为:”AAA2”。

  CALL FUNCTION 'SCMS_STRING_TO_XSTRING'    EXPORTING      text     = lv_string_content      encoding = lv_encoding    IMPORTING      buffer   = lv_xstring    EXCEPTIONS      failed   = 1      OTHERS   = 2.

此时出现了不一致的地方:GBK中原本处于FE50-FEA0的字符在SAP系统中没有对应的问文字,而SAP把本身处于FE50-FEA0的字符挪到了AAA2-AAF1(该段处于用户自定义区)。这就导致了GBK中处于FE50-FEA0的字符无法在codepage=8404的情况下正确转换。

Frontend codepage

T-code:SCP 查看系统内的Frontend codepage
我们可以看到8402是属于GB18030-2005,他是对GBK编码的扩充。8404是GB2312,还是GBK。所以SAP使用的8404是GB2312的标准,为了显示GB2312中没有的字,将这些文字放到了用户自定义区。

scp

如何解决转换乱码

使用’HR_KR_XSTRING_TO_STRING’时,codepage使用’8402’,不要使用’NLS_GET_FRONTEND_CP’去获取了。


注释:
1.上传控件其实只是把文本的内容上传。windows下txt文件默认的编码为ANSI,ANSI在Windows下就是根据系统的地区来进行选择编码,简体中文环境下为GBK(梁海在知乎中的回答)。

附录:
1.xstring to string 的方法

**  solution 1  CALL FUNCTION 'HR_KR_XSTRING_TO_STRING'    EXPORTING      from_codepage = lv_encoding      in_xstring    = lv_upload_file    IMPORTING      out_string    = lv_out_string.**  solution 2*  CALL FUNCTION 'LXE_COMMON_XSTRING_TO_STRING'*    EXPORTING*      IN_CODEPAGE = lv_codepage*      in_xstring    = lv_upload_file*    IMPORTING*      EX_STRING    = lv_out_string.**  solution 3*  DATA: lv_filesize TYPE i,*        lt_bin_data TYPE STANDARD TABLE OF raw255.**  CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'*    EXPORTING*      buffer        = lv_upload_file*    IMPORTING*      output_length = lv_filesize*    TABLES*      binary_tab    = lt_bin_data.**  CALL FUNCTION 'SCMS_BINARY_TO_STRING'*    EXPORTING*      input_length = lv_filesize**     MIMETYPE     = ' '*     ENCODING     = lv_encoding*    IMPORTING*      text_buffer  = lv_out_string**     OUTPUT_LENGTH       =*    TABLES*      binary_tab   = lt_bin_data*    EXCEPTIONS*      failed       = 1*      OTHERS       = 2.*  IF sy-subrc <> 0.** Implement suitable error handling here*  ENDIF.**  solution 4*lv_out_string =  CL_BCS_CONVERT=>XSTRING_TO_STRING(*      IV_XSTR = lv_upload_file*      IV_CP = lv_codepage ).** solution 5*  CALL FUNCTION 'ECATT_CONV_XSTRING_TO_STRING'*    EXPORTING*      im_xstring        = lv_upload_file*     IM_ENCODING       = lv_encoding*   IMPORTING*     EX_STRING         = lv_out_string   .

2.SAP的编码和GBK编码区别的地方

文字 SAP-8404 GBK 獱 AAA0 AAA0  AAA1 D7FE  AAA2 FE50  AAA3 FE51  AAA4 FE52  AAA5 FE53  AAA6 FE54  AAA7 FE55  AAA8 FE56  AAA9 FE57  AAAA FE58  AAAB FE59  AAAC FE5A  AAAD FE5B  AAAE FE5C  AAAF FE5D  AAB0 FE5E  AAB1 FE5F  AAB2 FE60  AAB3 FE61  AAB4 FE62  AAB5 FE63  AAB6 FE64  AAB7 FE65  AAB8 FE66  AAB9 FE67  AABA FE68  AABB FE69  AAC1 FE6F  AAD0 FE7E  AAD1 FE80  AAD2 FE81  AAD3 FE82  AAD4 FE83  AAE0 FE8F  AAE1 FE90  AAE2 FE91  AAE3 FE92  AAE4 FE93  AAE5 FE94  AAE6 FE95  AAE7 FE96  AAE8 FE97  AAE9 FE98  AAEA FE99  AAEB FE9A  AAEC FE9B  AAED FE9C  AAEE FE9D  AAEF FE9E  AAF0 FE9F  AAF1 FEA0

3.相关表
TCP0C
TCP00
TCP00A
TCP0F

4.sap Release的FM
GUI_UPLOAD