java与C#用protobuf通信--java如何转换protobuf-net中的bcl.Decimal对象
公司内部有些C#服务使用proto-net,引入了bcl.proto中的bcl.Decimal、bcl.DateTime等。对于java的proto生成代码需要对bcl.Decimal、bcl.DateTime转换成本地支持的数据类型。
bcl.Decimal结构为32位int保存高位、64位long保存低位,signScale 保存符号(正负)及模数。转换过程如下:
bcl.Decimal --> BigDecimal
1. 将高32位的int以高位在前格式转换为4个长度的byte数组;
2. 将低64位的long以高位在前的格式转换为8个长度的byte数组;
3. 将两个数组组合为12长度的byte数组bigIntBytes,获取signScale的符号值sgin = (signScale & 1) == 1 ? -1 : 1; (参考bcl.Decimal 注释:the number of decimal digits (bits 1-16), and the sign (bit 0))
4. 根据bigIntBytes和sgin获取BigInteger对象bInt,new BigInteger(sgin,bigIntBytes);
5. 获取signScale的模数值scale = (signScale & 0b1111_1111_1111_1110) >> 1; (参考bcl.Decimal 注释:the number of decimal digits (bits 1-16), and the sign (bit 0))
6.根据bInt和scale获取BigDecimal对象,new BigDecimal(bint, scale);
BigDecimal --> bcl.Decimal
上述过程反之即可
代码如下:
/*JDK1.7*/
public class BclUtil {
/**
*
*/
private static final long TICKS_PER_MILLISECOND = 10000; private static final int SIGNSCALE_FLAG = 0b1111_1111_1111_1110; private BclUtil() { } /**
* 转换 bcl.Decimal,返回BigDecimal<br>
* 高位在前<br>
*
* @param bclDecimal
* @return
*/
public final static BigDecimal bclDecimalToBigDecimal(Bcl.Decimal bclDecimal) {
if (bclDecimal == null) {
return BigDecimal.ZERO;
}
byte[] deBytes = new byte[12];
int2byte(deBytes, 0, bclDecimal.getHi());
long2byte(deBytes, 4, bclDecimal.getLo());
int signScale = bclDecimal.getSignScale();
BigInteger bint = new BigInteger(getSign(signScale), deBytes);
return new BigDecimal(bint, getScale(signScale));
} /**
* 转换BigDecimal,返回bcl.Decimal<br>
* 高位在前<br>
*
* @param bigDecimal
* @return
*/
public final static Bcl.Decimal bigDecimalToBclDecimal(BigDecimal bigDecimal) {
if (bigDecimal == null) {
return null;
}
Bcl.Decimal.Builder b = Bcl.Decimal.newBuilder();
// 获取BigInteger,必须是unscaledValue
BigInteger bi = bigDecimal.unscaledValue();
byte[] deBytes = new byte[12];
byte[] bigIntegerBytes = bi.toByteArray();
System.arraycopy(bigIntegerBytes, 0, deBytes, 12 - bigIntegerBytes.length, bigIntegerBytes.length);
// 取高4位int
int hi = Eutil.bytes2int(deBytes, 0);
b.setHi(hi);
// 取低8位long
long lo = Eutil.bytes2long(deBytes, 4);
b.setLo(lo);
int signScale = getSignScale(bi.signum(), bigDecimal.scale());
b.setSignScale(signScale);
return b.build();
} private static int getSignScale(int signum, int scale) {
// 从BigInteger获取取标志位放在bit 0/从BigDecimal获取取标志位放在bit 1-16
return getSignInSignScale(signum) | (scale << 1);
} public final static Bcl.Decimal zeroOfBclDecimal() {
Bcl.Decimal.Builder b = Bcl.Decimal.newBuilder();
b.setHi(0);
b.setLo(0);
b.setSignScale(0);
return b.build();
} /**
* 填充值符号<br>
*
* @param sign
* @return
*/
public final static byte getSignInSignScale(int sign) {
byte signTemp = 0;
if (sign < 0) {
signTemp = 1;
}
return signTemp;
} /**
* 获取值符号<br>
*
* @param signScale
* @return
*/
public final static int getSign(int signScale) {
// the number of decimal digits (bits 1-16), and the sign (bit 0)
boolean isNegative = (signScale & 1) == 1;
return isNegative ? -1 : 1;
} /**
* 获取模数
*
* @param signScale
* @return
*/
public final static int getScale(int signScale) {
// the number of decimal digits (bits 1-16), and the sign (bit 0)
return (signScale & SIGNSCALE_FLAG) >> 1;
} /**
* 获取int的byte数组,高位在前
*
* @param dst
* @param pos
* @param src
*/
public final static void int2byte(byte[] dst, int pos, int src) {
int2byte(dst, pos, src, true);
} public final static byte[] int2byte(byte[] dst, int pos, int src, boolean big_endian) {
if (big_endian) {
dst[pos + 3] = (byte) ((src >>> 0) & 0xff);
dst[pos + 2] = (byte) ((src >>> 8) & 0xff);
dst[pos + 1] = (byte) ((src >>> 16) & 0xff);
dst[pos + 0] = (byte) ((src >>> 24) & 0xff);
} else {
dst[pos + 0] = (byte) ((src >>> 0) & 0xff);
dst[pos + 1] = (byte) ((src >>> 8) & 0xff);
dst[pos + 2] = (byte) ((src >>> 16) & 0xff);
dst[pos + 3] = (byte) ((src >>> 24) & 0xff);
} return dst;
} public final static byte[] int2unSignByte(byte[] dst, int pos, int src, boolean big_endian) {
if (big_endian) {
dst[pos + 3] = (byte) ((src >>> 0) & 0xff + 128);
dst[pos + 2] = (byte) ((src >>> 8) & 0xff + 128);
dst[pos + 1] = (byte) ((src >>> 16) & 0xff + 128);
dst[pos + 0] = (byte) ((src >>> 24) & 0xff + 128);
} else {
dst[pos + 0] = (byte) ((src >>> 0) & 0xff + 128);
dst[pos + 1] = (byte) ((src >>> 8) & 0xff + 128);
dst[pos + 2] = (byte) ((src >>> 16) & 0xff + 128);
dst[pos + 3] = (byte) ((src >>> 24) & 0xff + 128);
} return dst;
} /**
* 获取long的byte数组,高位在前
*
* @param dst
* @param pos
* @param src
*/
final static void long2byte(byte[] dst, int pos, long src) {
long2byte(dst, pos, src, true);
} final static void long2byte(byte[] dst, int pos, long src, boolean big_endian) {
if (big_endian) {
int2byte(dst, 4 + pos, (int) (src & 0xffffffff));
int2byte(dst, 0 + pos, (int) ((src >>> 32) & 0xffffffff));
} else {
int2byte(dst, 0 + pos, (int) (src & 0xffffffff));
int2byte(dst, 4 + pos, (int) ((src >>> 32) & 0xffffffff));
}
}
}
java与C#用protobuf通信--java如何转换protobuf-net中的bcl.Decimal对象的更多相关文章
- Java如何转换protobuf-net中的bcl.DateTime对象
一.定义DateTime Message 参考文档:https://github.com/mgravell/protobuf-net/blob/master/src/Tools/bcl.proto m ...
- 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?
这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...
- Java和C#的socket通信相关(转)
这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...
- java和c#使用hessian通信
介绍 hessian主页:http://hessian.caucho.com/ 一个简单的例子学习hessian服务:服务端为Java,客户端为C#. 先要准备好C#和Java的第三方类库:http: ...
- (一)Protobuf的Java使用
学习使用Protobuf,创建java文件 windows : 步骤一:两个文件:proto.exe, protobuf-Java-2.4.1.jar 步骤二:建立一个工程CreateProtoBu ...
- Java线程同步和线程通信
一.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步. 不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全. 1.同步 ...
- ProtoBuf 的java使用
碰巧用到Proto,算是笔记吧算是笔记吧, windows : 1,两个文件:proto.exe, protobuf-java-2.4.1.jar 2,建立一个工程TestPb,在下面建立一个pro ...
- java和C#之间SOCKET通信的问题
转自:http://www.cdtarena.com/javapx/201307/9170.html java和C#之间SOCKET通信的问题 一.服务器端(使用java编写) /** * 监听客户端 ...
- 关于Java和.NET之间的通信问题(JSON)
前言: 最近项目在某XX领导的所谓指引下,非要转型Java,转就转吧,在转的过程前期是个痛苦期,特别.NET旧有项目和Java新项目需要通信时. 进入主题,Java和.NET之间需要通信,这时媒介很多 ...
随机推荐
- 你所不知到的C++ 系列
http://blog.csdn.net/doon/article/category/2926337
- gradle的maven plugin使用
在分布式系统开发中,基于gradle的项目,要共享jar一般是借助maven私服.那么gradle的maven插件如何做到上传binary jar,source jar, javadoc jar到私服 ...
- mysql常用备注
一:One Table have only one Auto_Increment that column is must to be Primary key. (自增加的字段必须是主键且是数字类型) ...
- Graylog2+mongdb+rsyslog中央日志服务器对syslog的web管理--转载
原文地址:http://blog.sina.com.cn/s/blog_49be4d570100yvv1.html 1.下载mongodb,可以通过下面2中方法安装. (1)官网下载yum源后直接安装 ...
- Mybank
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 用JDBC查询数据库
JDBC API的核心组件:1.DriverManager类:用语跟踪可用的JDBC驱动程序并产生数据库连接. 2.Connection接口:用于取得数据库信息.生成数据库语句,并管理数据库事务. 3 ...
- How to make remote key fob for 2002 BMW 3 series
Here share with you on how to make remote key fob for 2002 BMW 3 series: Method 1: 1. Working within ...
- MVC+jquery+AJAX的几种方式
// 传过去一个简单值,获取一个简单值 $.ajax({ type: "GET", url: '<%= Url.Action("xx", "Co ...
- 【HTML5 3】《html5 开发精要与实例讲解》 step2 -- 结构元素 (待续)
主要内容:通过 一个博客网站和一个企业网站的制作 展示如何运用HTML5中的各种 结构元素,构建出一个语义清晰,结构分明的Web3.0时代的网站. 案例1:用HTML5中的结构元素构建一个博客网站 疑 ...
- CSS3实战手册(第3版)(影印版)
<CSS3实战手册(第3版)(影印版)> 基本信息 原书名:CSS3: The Missing Manual, 3E 作者: David Sawyer McFarland 出版社:东南大学 ...