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之间需要通信,这时媒介很多 ...
随机推荐
- DB2 重新设定表自增字段的当前值
转自:http://blog.csdn.net/jionghan3855/article/details/2709073 1.ALTER TABLE UKEY_INFO_TAB ALTER COLUM ...
- 自定义强大的C#网络操作基础类(NetHelper)
using System; using System.Text;using System.Net.Sockets;using System.Net.Mail;using System.Net; nam ...
- 每天一道面试题(2):实现strncpy
目录 0. 为何要写strncpy? 1. 源码及测试结果 2. 面试注意事项 3. 小结
- [Java] HashMap的用法
重点介绍HashMap.首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.在下文中会 ...
- Android 高级UI设计笔记16:ViewStub的应用
1. ViewStub 在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局. 那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为 ...
- 错误"Lc.exe 已退出,代码 -1 "
今天做项目的时候突然出现编译不通过,错误为Lc.exe已退出,代码为-1.这让我郁闷了至少30分钟,后来上网查了一下,才知道原因所在,我们项目中使用了第三方组件(Infragistics)造成的,至于 ...
- iOS 犄角旮旯的知识
1.全局变量 static NSInteger kImageHeight = 300; #define kImageHeight 300 2.通知中心 开始编辑 UITextViewTextDidBe ...
- [iOS Xcode8]上传AppStore无法添加构建版本
最近升级到xcode8了,也遇到了一些问题.最近产品需要更新版本,按照以前的流程,我觉得so easy啊,万万没想到啊,这次更新版本差点让我吐血,来来回回不下七次. 首先问题是版本通过xcode上传到 ...
- javaweb学习总结二十五(response对象的用法一)
一:Reponse对象的概念 当客户端发送http请求时,服务器端会对每一次请求,创建request对象和response对象. response对象包括三个部分:响应头.响应状态码以及响应体 二:r ...
- hdu-5698 瞬间移动(数论+快速幂)
题目链接: 瞬间移动 Problem Description 有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝 ...