欢迎使用CSDN-markdown编辑器
来源:互联网 发布:淘宝流量充值如何退款 编辑:程序博客网 时间:2024/05/17 22:03
Java解析C语言那些事
本本人从事Android开发工作,最近由于工作需要,需要与C++语言服务器进行TCP交互。在java中Socket编程已经为我们封装了很多好用的Api,今天我们讨论的是和C++交互过程中的一些心得。首先要明确几个概念
:
- 什么是内存对齐
- 为什么要内存对齐
-内存对齐:
内存对齐,或者说字节对齐,是一个数据类型所能存放的内存地址的属性(Alignment is a property of a memory address)。
这个属性是一个无符号整数,并且这个整数必须是2的N次方(1、2、4、8、……、1024、……)。
当我们说,一个数据类型的内存对齐为8时,意思就是指这个数据类型所定义出来的所有变量,其内存地址都是8的倍数。
当一个基本数据类型(fundamental types)的对齐属性,和这个数据类型的大小相等时,这种对齐方式称作自然对齐(naturally aligned)。
比如,一个4字节大小的int型数据,默认情况下它的字节对齐也是4。
-为什么要内存对齐:
这是因为,并不是每一个硬件平台都能够随便访问任意位置的内存的。我个人的理解可能在不同的平台上面内存的分配情况是不一样的。这个也是导致java中没有结构体这个数据结构的原因。
我们都知道,在结构体内部可能有多个基本类型,那么子阿布同平台他所占的内存大小也是不一样的的使用。那么问题来了,java中如何实现C或C++中的结构体类型。
-Javolution
这是一个第三方资源库。 [ Javolution ]
javolution的使用:
1 javolution支持maven方式引入
<dependency> <groupId>org.javolution</groupId> <artifactId>javolution-core-java</artifactId> <version>6.0.0</version> </dependency>
2 可以下载相应的Jar加入到你的工程中。(注意:我开始下载的是5.X版本,有些问题。下载6.x就好了)。
开始使用Javolution:
在java中若要定义结构体形式的数据结构。你的类首先应该继承Javolution的Struct类。而且java中的基本类型也不能直接使用。要使用Struct类中的基本类型,如下:
public final Signed32 version = new Signed32(); public final Signed32 eMainType = new Signed32(); public final Bool hasSubtype = new Bool(); public final Signed32 nLen = new Signed32(); public final UTF8String HeadEnding = new UTF8String(2); public final Signed32 eSubType = new Signed32();
值得注意的是:在你自己定义的“结构体”中,ByteOrder方法返回的小端对齐的。
另外在附加两个工具方法。分别是Struct转成byte[]和byte[]转成Struct:
/** * 把类型转化成byte数组 * @param struct 实体类型 * @return */ public static byte[] GetBytesFromStruct( javolution.io.Struct struct) { int sz = struct.size(); ByteBuffer bb = struct.getByteBuffer(); if( bb == null)return null; byte[] buffer = new byte[sz]; bb.position(0); // 设置位置 bb.get(buffer);// System.out.println(bb); return buffer; }
/** * 把byte数组转换成类型 * * @param struct 实体类型 * @param bytes 原始数据流 * @param offset 开始位置 * @param length 取长度 * @return */ public static Struct GetStructFromByte(Struct struct, byte[] bytes,int offset,int length) { ByteBuffer bb = ByteBuffer.wrap(bytes, offset, length); bb.position(0); bb.order(ByteOrder.LITTLE_ENDIAN); struct.setByteBuffer(bb, 0); return struct; }
值得注意的是: 1 关于如何为结构体赋值或是获取其中某个属性的值可以通过Struct.XXX.set()和 Struct.XXX.get()方法实现。 2 在你自己定义的结构体中,每个参数的顺序要按照协议约定的顺序,否则返回的结构将不是你期待的结果。 3 获取你自己定义的结构的内存大小使用的Struct.Size()方法。
网上有对这种方式的问题做出了总结,目前本人还没有遇到:
一 对齐方式改变了:结构体在遇到64位的数据类型的时候,就自动把前面的数据按8字节对齐了,这样子的话coin数据本应该是由数据流的第12字节的位置开始解析变成了第16个字节开始解析,后面的数据就必然会跟着移位
二 在C中char content[0]content数据存储的是可变数据的开始地址,在c的结构体里是不占用大小的,所以这个结构体的大小应该为2.在java里就定义不出来的
详细问题与解决方式的请参考。 [ Javolution的坑 ]
以上就是在这次工作中的一点心得,另外网上还有一种实现方式是通过JNI来实现的。个人还没有尝试。
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- Java 8 Lambda
- 静态链表单向实现
- ImageView剖析二—(示例详解ImageView属性的使用)
- C++基础知识复习--字符串
- 欧拉函数
- 欢迎使用CSDN-markdown编辑器
- 共享密钥与公开密钥
- STM32
- 从百度统计看到的一些有意思的事情
- 深度学习(6):Deep Belief Networks
- ubuntu16.04下matlab2015b的安装
- 4.3-4-2a 输出对应字母的ASCII值
- try catch 异常 代码执行问题
- APP测试checklist模板