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之间需要通信,这时媒介很多 ...
随机推荐
- except ShortInputException,x中逗号
class ShortInputException(Exception): def __init__(self, length, atleast): Exception.__init__(self) ...
- The Kernel Newbie Corner: Kernel Debugging with proc "Sequence" Files--Part 3
转载:https://www.linux.com/learn/linux-career-center/44184-the-kernel-newbie-corner-kernel-debugging-w ...
- .NET多线程执行函数
前面几篇文章一直在写LINQ,这里为什么会出现多线程?原因是DebugLZQ在写一个LINQ综合Demo的时候遇到了多线程,便停下手来整理一下.关于多线程的文章,园子里很多很多,因此关于多线程理论性的 ...
- C# unix时间戳转换
场景:由于业务需要和java 开发的xxx系统对接日志,xxx系统中用“1465195479100” 来表示时间,C# 里面需要转换做一下逻辑处理,见代码段. C#获取的unix时间戳是10位,原因是 ...
- B. Om Nom and Dark Park
B. Om Nom and Dark Park 在满二叉树上的某些边上添加一些值.使得根节点到叶子节点的路径上的权值和都相等.求最少需要添加多少. 我们利用性质解题. 考察兄弟节点.由于他们从跟节 ...
- jquery datatable[表格处理]
最近在公司实习发现一个额功能强大的表格解决方案,了解了一下,先总结如下: 1.官网:http://www.datatables.net/ 2.需要特别注意:被dataTable处理的table对象,必 ...
- UITableView 折叠效果
1:创建一个model数据模型 #import <Foundation/Foundation.h> @interface DataModel : NSObject //保存section中 ...
- 【Shell脚本学习14】Shell echo命令
echo是Shell的一个内部指令,用于在屏幕上打印出指定的字符串.命令格式: echo arg 您可以使用echo实现更复杂的输出格式控制. 显示转义字符 echo "\"It ...
- 【Android 界面效果32】ImageView中XML属性src和background的区别
background会根据ImageView组件给定的长宽进行拉伸,而src就存放的是原图的大小,不会进行拉伸. src是图片内容(前景),bg是背景,可以同时使用. 此外:scaleType只对sr ...
- Jqeury获取table当前行与指定列
今天遇到了一个Jqeury获取table当前行与指定列的问题: 大概的实现要求是一个页面中,上面有几个input输入框,下面有一个table,当在输入框中输入内容的时候,点击添加按钮的时候,在下面ta ...