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的原创文章,尽在:“汪子熙”:
ABAP 调用第三方 API,遇到乱码该怎么办?相关推荐
- 简单介绍如何调用第三方API
大家好,我是IT修真院武汉分院第15期学员,一枚正直善良的JAVA程序员. 今天给大家分享一下,java学习中需要使用的第三方API的调用 1.背景介绍 API(Application Program ...
- 解决调用第三方API报sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provid
1.最近在调用第三方API遇到证书验证问题 postman调用和用RestTemplate分别报错如下: 2.经过查询资料 是https,需要安装证书,但是自定义的证书貌似得不到信任,所以报PK ...
- 调用第三方api在线生成二维码
我写过一篇文章是java代码后端自己传入链接由本地代码生成二维码图片并保存在本地,今天我们实现调用第三方在线生成二维码 首先我们找到一个在线生成二维码的api接口,因为这样的api接口有许多,这里我提 ...
- Android之调用第三方API导航(高德,百度,google)
一:效果图(点击路线调用API) 二:实现步骤: 1.判断是否安装各个地图软件 /*** 判断是否安装目标应用** @param packageName 目标应用安装后的包名* @return 是否已 ...
- 多线程调用第三方API接口
public void ThreadDemo() {//集合 相当于请求内容List<String> list = new ArrayList<String>();list.a ...
- PHP 调用第三方API接口 、带参数跳转PHP
前排说重点:关键方法在context.php文件里,有关于第三方接口调用的方法 function api_execute. 主要是在传递参数时,如果选择json格式传递,需要做相关处理: 然后在ap ...
- 通过调用第三方API,查询身份证信息
//界面XML文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns ...
- 【PHP】循环 调用第三方API (curl ),性能优化
前面说到:shell 脚本获取设备多网口IPv4或IPv6地址,并且推送到pushgateway PHP 应用中获取IP地址多个网口循环,请求prometheus API 成了问题,很耗性能,为了优化 ...
- 调用第三方API ,实现手机号码归属地及运营商查询
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 运行结果: 中国电信 西双版纳 西双版纳,中国电信 代码: import java.io.Buffe ...
最新文章
- 机器学习简单代码示例
- 开源自己写的Library到github,让别人或自己的项目依赖
- 配置思路ensp_配置OSPF的Stub区域示例
- dazhilu网站代码【完整篇】
- 有点牛论坛小程序v3.0.16源码
- Hadoop入门基础教程 Hadoop之单机模式搭建
- Eclipse中 Project facet jst.web.jstl has not been defined.解决方案
- 苹果Mac 3D 数字绘画工具:Substance 3D Painter
- 手机linux服务器控制,手机上如何远程控制Linux服务器?
- 基于WEB的本科毕业设计管理系统
- 75.【JavaWeb-03】
- linux 内核配置otg,Linux 4.9.11 测试USB OTG功能
- 刻录DVD9光盘内容至DVD5 DVD-R盘指南
- Java写入磁盘阵列_磁盘阵列方案
- 分布式一致性算法——Paxos 和 Raft 算法
- 抖音小程序创建广告位
- 基于灰狼算法优化的lssvm回归预测-附代码
- 好神奇:衣服也能存储数据啦
- 读《卓有成效的管理者》笔记
- 李清照词全集,共49首,有百家评说,附 txt 文本下载,就在本帖的附件中。