公司内部有些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对象的更多相关文章

  1. Java如何转换protobuf-net中的bcl.DateTime对象

    一.定义DateTime Message 参考文档:https://github.com/mgravell/protobuf-net/blob/master/src/Tools/bcl.proto m ...

  2. 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  3. Java和C#的socket通信相关(转)

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  4. java和c#使用hessian通信

    介绍 hessian主页:http://hessian.caucho.com/ 一个简单的例子学习hessian服务:服务端为Java,客户端为C#. 先要准备好C#和Java的第三方类库:http: ...

  5. (一)Protobuf的Java使用

    学习使用Protobuf,创建java文件 windows : 步骤一:两个文件:proto.exe,  protobuf-Java-2.4.1.jar 步骤二:建立一个工程CreateProtoBu ...

  6. Java线程同步和线程通信

    一.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步. 不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全. 1.同步 ...

  7. ProtoBuf 的java使用

    碰巧用到Proto,算是笔记吧算是笔记吧, windows : 1,两个文件:proto.exe,  protobuf-java-2.4.1.jar 2,建立一个工程TestPb,在下面建立一个pro ...

  8. java和C#之间SOCKET通信的问题

    转自:http://www.cdtarena.com/javapx/201307/9170.html java和C#之间SOCKET通信的问题 一.服务器端(使用java编写) /** * 监听客户端 ...

  9. 关于Java和.NET之间的通信问题(JSON)

    前言: 最近项目在某XX领导的所谓指引下,非要转型Java,转就转吧,在转的过程前期是个痛苦期,特别.NET旧有项目和Java新项目需要通信时. 进入主题,Java和.NET之间需要通信,这时媒介很多 ...

随机推荐

  1. [Node.js] Level 7. Persisting Data

    Simple Redis Commands Let's start practicing using the redis key-value store from our node applicati ...

  2. CSS样式如何解决IE浏览器不同版本的兼容问题

    如果你想让浏览器是固定的IE6版本,那么你做网页的时候在<head>后面加上一句话: <meta http-equiv="X-UA-Compatible" con ...

  3. 用iDSDT制作声显卡DSDT

    已有 2299 次阅读2011-10-24 21:00 |个人分类:Mac| DSDT 快速增加积分秘笈! windows下!--------------------------------第一步.下 ...

  4. qobject_cast用法

    函数原型: T qobject_cast ( QObject * object ) 本方法返回object向下的转型T,如果转型不成功则返回0,如果传入的object本身就是0则返回0. 在使用时有两 ...

  5. mysql 历史记录查询

    SHOW SLAVE STATUS insert into jy510_admin set userid='123123' mysqlbinlog d:xampp\mysql\data\mysql-b ...

  6. Javascript Date原型方法

    // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 个占 ...

  7. seleniu IDE 点点滴滴

    在使用selenium webdriver +python 的过程中遇见了许多的问题,这些问题在网上都没有找到很好的答案,后来在看selenium IDE的时候发现这里面有很好的解决方法,写写.记记. ...

  8. ASP.NET MVC与WebForm区别

    [转贴一] 使用ASP.NET MVC框架,创建默认项目,第一直观感觉就是地址都是Rewrite过的.对源码和配置文件稍加分析不难看出,MVC使用了httpModules来拦截地址请求,具体用到了Sy ...

  9. EF——默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 02 (转)

    EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射   I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库 ...

  10. Find the Clones

    Find the Clones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6365   Accepted: 2375 D ...