乐趣区

关于abap:ABAP-调用第三方-API遇到乱码该怎么办

这是 Jerry 2022 年第二篇原创文章,也是本公众号第 370 篇原创文章。

之前有一个敌人在知乎上向我征询过这个问题,我觉得很有代表性,所以专门用一篇文章来讲述一些相干知识点。

先看这位敌人遇到的具体问题。

用 Postman 调用第三方接口,外面的中文字符可能失常显示。

然而当用 ABAP 的 HTTP 工具类 CL_HTTP_CLIENT 的 response->get_data() 读取响应之后,发现外面的中文字符,例如 “ 拜访胜利 ” 是乱码:

首先明确一点,既然 Postman 能正确显示响应数据中的中文内容,阐明 API provider 是不存在问题的,这个乱码问题呈现在接管方,即 ABAP 代码的编程实现须要调整。

咱们只有弄清楚呈现乱码的起因,就能对症下药进行修复了。

上个世纪 60 年代,美国制订了一套字符编码,定义了英文字符与二进制位之间的一一映射关系,称为 ASCII 码。将一个符号的图形显示,关联到其二进制存储位的这种行为,就称之为字符编码。ASCII 就是一种最简略的字符集和字符编码方式。

一个字节有 8 位,2 的 8 次方为 256,因而 1 个字节只能示意 256 种符号,而汉字的总数超过了 10 万个,显然无奈用 1 个字节来存储。

除了大家相熟的英文字符和汉字外,还有很多历史更悠久的文字,比方埃及象形文字:

以及周杰伦《爱在西元前》里提到的楔形文字:

有没有这样一种计算机编码方式,可能将这些稀奇古怪的符号都纳入其中呢?有,这就是 Unicode,正如其命名暗示的,Unicode 将世界各种语言的每个字符都调配了一个惟一的编码,以满足跨语言、跨平台的文本信息转换。

咱们依据 Unicode 编码表,就能查到一个字符对应的 Unicode 编码,比方汉字 “ 汪 ” 对应的 Unicode 编码为 00006C6A.

6C6A 的二进制示意为 0110 1100 0110 1010,须要两个字节进行存储。示意其余的符号,可能须要三个甚至四个字节存储。

另一方面,对于本来就存在于 ASCII 编码表中的英文字符,仅需 1 个字节就能存储。如果 Unicode 强制要求每个字符依照最大须要的存储空间,即 4 字节进行存储,显然对于英文字符来说,意味着极大的空间节约。

因而,Unicode 仅仅定义字符到其编码的映射关系。而这些编码到底采取多少个字节进行存储,由 Unicode 具体的实现形式,比方 UTF-8,UTF16 等来决定。

UTF-8 是一种变长的编码方式,应用 1 到 4 个字节示意一个字符,符号不同,用于存储的字节长度也不同。比方 “ 汪 ” 的 UTF-8 码值为 E6B1AA,须要三个字节存储。

依据 SAP 帮忙文档,ABAP 采纳 UCS-2 编码方式,能够看成 UTF-16 的子集,因为 UCS-2 不反对 UTF-16 的 surrogates 区间内定义的一些特殊符号。

所谓 UTF-16,就是所有字符固定都用两个字节示意。

从上面这张表格可能看出,UTF-16 又分 UTF-16BE 和 UTF-16LE 两种实现形式。以汉字 “ 汪 ” 的 Unicode 编码值 6C6A 为例,如果 6C 存储在内存低位地址,6A 存储在内存高位地址,这就是 Big Endian 即大尾序 (有时也译作大头,大端) 存储形式,反之则为 Little Endian 即小尾序存储形式。

这两个名称来自英国讥刺寓言作家斯威夫特的《格列佛游记》。书中的小人国暴发了内战,和平起因居然是人们争执吃鸡蛋时到底应该从大头 (Big Endian) 一端敲开,还是从小头 (Little Endian) 敲开。

那么 ABAP 的 UCS-2(UTF-16 的子集), 到底是 BE 存储还是 LE 存储?一试便知。

在我的零碎里,答案是 UTF-16LE.

另一种形式,间接查看零碎类 CL_ABAP_CHAR_UTILITIES 的属性 ENDIAN. 在 Jerry 的零碎里,该属性的值为 L,代表 Little Endian:

咱们理解了这些常识,再来修复文章结尾形容的乱码问题。

仔细观察 Postman 调用 API 的返回后果,发现还有一条重要信息:charset=GB18030,意思是 API 响应数据采取 GB18030 字符集编码。

汉字 “ 访 ” 的 GB18030 编码值为 B7C3,齐全不等同于 UTF-16LE 中的编码值 BF8B.

如果咱们在 ABAP 代码里,依照默认的 UTF-16LE 的形式去读取一个依据 GB18030 编码的符号,当然不会失去冀望的后果。这种张冠李戴的解码形式见下图第 55 行的 get_cdata 办法,最初就会呈现乱码。

正确的形式,采取第 57 行 get_data,返回一个 16 进制数据流,类型为 xstring:

在这个 16 进制数据流里,咱们曾经看到了汉字 “ 访 ” 和 “ 问 ” 对应的 GB18030 编码值。

剩下的事件就容易了,应用字符集 GB18030 对这段数据流进行解码。

咱们首先关上数据库表 TCP00, 依据关键词 18030 查问表字段 CPCOMMENT:

失去 GB18030 对应的 SAP Code Page 为 8401:

在上面这段代码中,传入 8401,变量 lv_binary 存储的是 16 进制数据流,变量 lv_text 寄存的就是基于 GB18030 的 API 响应内容:

能够看到乱码曾经隐没了,在 ABAP 程序里显示的内容曾经和 Postman 里察看到的完全一致了。

心愿本文介绍的这个例子,能对大家在 ABAP 里解决中文乱码问题有所启发,感激浏览。

Jerry 的 ABAP 专集

  • Jerry 的 ABAP, Java 和 JavaScript 乱炖
  • ABAP 开发人员将来应该学些什么
  • Jerry 2017 年的五一小长假:8 种经典排序算法的 ABAP 实现
  • Jerry 的 ABAP 原创技术文章合集
  • 300 行 ABAP 代码实现一个最简略的区块链原型
  • 应用 Java+SAP 云平台 +SAP Cloud Connector 调用 ABAP On-Premise 零碎里的函数
  • 在 SAP 云平台的 CloudFoundry 环境下生产 ABAP On-Premise OData 服务
  • ABAP vs Java,蛙泳 vs 自由泳
  • 聊聊 C 语言和 ABAP
  • 入手应用 ABAP Channel 开发一些小工具,晋升日常工作效率
  • 我用 ABAP 做过的那些无聊的事件
  • 不喜爱 SAP GUI?那试试用 Eclipse 进行 ABAP 开发吧
  • 应用 Visual Studio Code 编写和激活 ABAP 代码
  • 你的 ABAP 程序给佛祖开过光么?来试试 Jerry 这个小技巧
  • 在 SAP 云平台 ABAP 编程环境上编写第一段 ABAP 程序
  • SAP 官网公布的 ABAP 编程标准
  • ABAP Code Inspector 那些暗藏的性能,您都晓得吗?
  • 还在用 ABAP 进行 SAP 产品的二次开发?来理解下这种全新的二次开发理念吧
  • ABAP Netweaver 体内的那些寄生式编程语言
  • 从 SAP 社区上的一篇博客开始,聊聊 SAP 产品命名背地的那份情怀
  • 云端的 ABAP Restful 服务开发
  • 如何在 SAP 云平台 ABAP 编程环境里把 CDS view 裸露成 OData 服务
  • 应用 abapGit 在 ABAP On-Premises 零碎和 SAP 云平台 ABAP 环境之间进行代码传输
  • 30 分钟用 Restful ABAP Programming 模型开发一个反对增删改查的 Fiori 利用
  • Jerry 带您理解 Restful ABAP Programming 模型系列之二:Action 和 Validation 的实现
  • Jerry 带您理解 Restful ABAP Programming 模型系列之三:云端 ABAP 利用调试
  • SAP 云平台上的 ABAP 编程环境里如何生产第三方服务
  • ABAP 开发者上云的时候到了 – 当初大家能够收费应用 SAP 云平台 ABAP 环境的试用版了
  • 学而不思则罔 – SAP 云平台 ABAP 编程环境的由来和实用场景
  • SAP 云平台里的三叉戟利用
  • 如何基于 Restful ABAP Programming 模型开发并部署一个反对增删改查的 Fiori 利用
  • SAP 2019 TechEd Key Note 解读:云时代下 SAP 从业人员如何做二次开发?
  • 有哪些 ABAP 关键字和语法,到了 ABAP 云环境上就没方法用了?
  • ABAP 开发环境终于反对以驼峰命名法主动格式化 ABAP 变量名了
  • 利用 ABAP 740 的新关键字 REDUCE 实现一个理论工作工作
  • 一段让人瑟瑟发抖的 ABAP 代码
  • 昨日万圣节 ABAP 怪兽级代码谜团,颁布答案啦
  • 介绍一种在 ABAP 内核态进行内表高效拷贝的办法
  • 应用 SAP Cloud Application Programming 模型开发 OData 的一个理论例子
  • 当 ABAP 遇见普罗米修斯
  • 应用 ABAP 绘制可伸缩矢量图
  • ABAP 开发环境语法高亮的那些事儿
  • SAP 谬误音讯调试之七种武器:让所有的谬误音讯都能被定位
  • 应用 ABAP 操作 Excel 的几种办法
  • SAP GUI 里的收藏夹事务码管理工具
  • SAP GUI 和 Windows 注册表
  • 有了 Debug 权限就能干坏事?小心了,你的一举一动尽在系统监控中
  • ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX 这些东东是什么鬼
  • 实现 ABAP 条件断点的三种形式
  • 应用 SAT 跟踪监控从浏览器关上的 SAP 利用的性能和调用栈
  • 一个 13 年 ABAP 老兵的倡议:理解这些基础知识,对 ABAP 开发有百利而无一害
  • SAP ABAP Netweaver 容器化, 不可能实现的工作吗?
  • SAP 产品加强技术回顾
  • SAP API 开发方法大全
  • 浅谈 Java 和 SAP ABAP 的动态代理和动静代理,以及 ABAP 面向切面编程的尝试
  • SAP ABAP 应用服务器的 HTTP 响应状态码(Status Code)
  • SAP ABAP 里存在 Java List 这种汇合工具类么?CL_OBJECT_COLLECTION 理解一下
  • ABAP 面试题系列:写一组会呈现死锁 (Deadlock) 的 ABAP 程序
  • SAP ABAP Netweaver 服务器的规范登录形式解说
  • SAP ABAP 关键字语法图和 ABAP 代码主动生成工具 Code Composer
  • SAP ABAP SM50 的另类用处 – ABAP 工作过程对数据库表读取操作的检测
  • 对于 SAP ABAP 字符变量和字符串变量字符个数的一个知识点,和一个血案
  • SAP ABAP 一组关键字 IS BOUND, IS NOT INITIAL 和 IS ASSIGNED 的用法辨析
  • SAP ABAP 和 Java 里的弱援用 (WeakReference) 和软援用(SoftReference)
  • SAP AMDP 介绍 – ABAP 托管的 HANA 数据库过程
  • 给你的 ABAP 对象打上标签(Tag)
  • 历史上的明天:编程语言中 null 援用的十亿美元谬误
  • ABAP Development Tool 代码模板和其余一些实用技巧汇总
  • SAP ABAP Development Tool 进步开发效率的十个小技巧
  • 如何在 SAP BTP 平台 ABAP 编程环境里生产基于 SOAP 的 Web Service
  • ABAP 真的会过期吗?聊聊 ABAP 的过来,当初和将来
  • 基于 abapGit 和 abaplint 的 ABAP 继续集成的一个例子
  • 不应用任何框架,手写纯 JavaScript 实现上传本地文件到 ABAP 服务器
  • 应用 JavaScript 上传 PDF 和 Excel 等二进制文件到 ABAP 服务器并进行解析
  • 从 ABAP Netweaver 到 ABAP Platform,咱们始终在致力

更多 Jerry 的原创文章,尽在:” 汪子熙 ”:

退出移动版