这是 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的原创文章,尽在:“汪子熙”:

ABAP 调用第三方 API,遇到乱码该怎么办?相关推荐

  1. 简单介绍如何调用第三方API

    大家好,我是IT修真院武汉分院第15期学员,一枚正直善良的JAVA程序员. 今天给大家分享一下,java学习中需要使用的第三方API的调用 1.背景介绍 API(Application Program ...

  2. 解决调用第三方API报sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provid

    1.最近在调用第三方API遇到证书验证问题   postman调用和用RestTemplate分别报错如下: 2.经过查询资料  是https,需要安装证书,但是自定义的证书貌似得不到信任,所以报PK ...

  3. 调用第三方api在线生成二维码

    我写过一篇文章是java代码后端自己传入链接由本地代码生成二维码图片并保存在本地,今天我们实现调用第三方在线生成二维码 首先我们找到一个在线生成二维码的api接口,因为这样的api接口有许多,这里我提 ...

  4. Android之调用第三方API导航(高德,百度,google)

    一:效果图(点击路线调用API) 二:实现步骤: 1.判断是否安装各个地图软件 /*** 判断是否安装目标应用** @param packageName 目标应用安装后的包名* @return 是否已 ...

  5. 多线程调用第三方API接口

    public void ThreadDemo() {//集合 相当于请求内容List<String> list = new ArrayList<String>();list.a ...

  6. PHP 调用第三方API接口 、带参数跳转PHP

    前排说重点:关键方法在context.php文件里,有关于第三方接口调用的方法 function  api_execute. 主要是在传递参数时,如果选择json格式传递,需要做相关处理: 然后在ap ...

  7. 通过调用第三方API,查询身份证信息

    //界面XML文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns ...

  8. 【PHP】循环 调用第三方API (curl ),性能优化

    前面说到:shell 脚本获取设备多网口IPv4或IPv6地址,并且推送到pushgateway PHP 应用中获取IP地址多个网口循环,请求prometheus API 成了问题,很耗性能,为了优化 ...

  9. 调用第三方API ,实现手机号码归属地及运营商查询

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 运行结果: 中国电信 西双版纳 西双版纳,中国电信 代码: import java.io.Buffe ...

最新文章

  1. 机器学习简单代码示例
  2. 开源自己写的Library到github,让别人或自己的项目依赖
  3. 配置思路ensp_配置OSPF的Stub区域示例
  4. dazhilu网站代码【完整篇】
  5. 有点牛论坛小程序v3.0.16源码
  6. Hadoop入门基础教程 Hadoop之单机模式搭建
  7. Eclipse中 Project facet jst.web.jstl has not been defined.解决方案
  8. 苹果Mac 3D 数字绘画工具:Substance 3D Painter
  9. 手机linux服务器控制,手机上如何远程控制Linux服务器?
  10. 基于WEB的本科毕业设计管理系统
  11. 75.【JavaWeb-03】
  12. linux 内核配置otg,Linux 4.9.11 测试USB OTG功能
  13. 刻录DVD9光盘内容至DVD5 DVD-R盘指南
  14. Java写入磁盘阵列_磁盘阵列方案
  15. 分布式一致性算法——Paxos 和 Raft 算法
  16. 抖音小程序创建广告位
  17. 基于灰狼算法优化的lssvm回归预测-附代码
  18. 好神奇:衣服也能存储数据啦
  19. 读《卓有成效的管理者》笔记
  20. 李清照词全集,共49首,有百家评说,附 txt 文本下载,就在本帖的附件中。

热门文章

  1. 自然语言处理工具pyhanlp分词与词性标注
  2. flask框架中勾子函数的使用
  3. 安全狗护航金砖厦门会晤 圆满完成任务
  4. 机器学习之sklearn——主题模型
  5. 新开了微博,小伙伴们可以关注下哦
  6. 在oracle下我们如何正确的执行数据库恢复
  7. 第二章:Java_基本语法_5 数组
  8. newcode wyh的吃鸡(优势队列+BFS)题解
  9. 全栈Python 必备库
  10. WPF Demo18 路由事件