公司内部有些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. ztree使用系列四(ztree实现同级拖拽排序并将排序结果保存数据库)

    ztree这个系列的最后一篇,也是ztree功能强大的体现之中的一个--排序功能. ztree能够实现全部节点之间任意的拖拽排序功能.我这里依据须要实现了仅仅同意同级之间任意拖拽排序,事实上原理都一样 ...

  2. NSNotificationCenter通知中心

    概述 NSNotificationCenter通知中心,通常用于一对一或者一对多的消息传递,即当一个地方改变时,要求改变其他的一些地方,例如当网络请求回来了新的数据,需要刷新本地信息和本地内存里面的界 ...

  3. js获取非行间样式/定义样式

    <!--DOCTYPE html--> <html> <head> <meta charset="utf-8" /> <sty ...

  4. InAction-编译hadoop2.5.2

    1.环境 2.JDK ... 3.工具 1)下载maven解压加入环境变量 2)安装编译工具 yum install make cmake zlib-devel openssl-devel gcc g ...

  5. Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276

    Face The Right Way Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 2899   Accepted: 133 ...

  6. 【Android 界面效果29】研究一下Android滑屏的功能的原理,及scrollTo和scrollBy两个方法

    Android中的滑屏功能的原理是很值得我们去研究的,在知道这两个原理之前,有必要先说说View的两个重要方法,它们就是scrollTo 和scrollBy. Android View视图是没有边界的 ...

  7. iOS篇之有沙盒缓存

    内存指的就是主板上的存储部件,是CPU直接与之沟通,并用其存储数据的部件,存放当前正在使用的(即执行中)的数据和程序,它的物理实质就是一组或多组具备数据输入输出和数据存储功能的集成电路,内存只用于暂时 ...

  8. python 基础——运算符重载

    方法 重载 调用 __init__ 构造函数 x = Class() __del__ 析构函数 del x __str__ 打印 print x __call__ 调用函数 x(*args) __ge ...

  9. poj 1191 矩形块的划分

    思路:黑书的例题 #include<iostream> #include<cstring> #include<algorithm> #include<cmat ...

  10. 一步步搭建自己的轻量级MVCphp框架-(三)一个国产轻量级框架Amysql源码分析(2) 进程

    Amysql类 按照我的理解这就是框架的初始化 上代码 class Amysql { public $AmysqlProcess; public function Amysql() { global ...