用java语言读取和写人c语音的结构体数据
2016-03-25 22:41
302 查看
最近因为要把excel文件的表格数据保存成一个用结构体格式写成的二进制文件,于是研究了一下如何用java来访问二进制数据。
原先的结构体是用c语言来访问的,因为c语言支持结构体指针,因此要访问结构体数据只需要用结构体指针指向数据的入口地址,就可以用->符号把结构体的元素逐一取出来,同样,写入结构体的元素也很方便。
我原先以为在java里面也会有同样的操作方式,结果有点失望,java下面是不能进行这样的操作的。那么如果有一个用c语言代码写的程序保存起来的这样的结构体数据文件,在java里面应该如何访问呢?
假设有一个二进制文件,里面存放了一个这样的结构体:
那么我们首先把文件读进来,存放到一个byte型的数组里,
获取整型,就相当于取4个字节,short型为2个字节,byte是一个字节,字符串是根据具体的长度来取。
然后,如果想用java保存一个结构体模样的二进制文件,就需要反过来操作。
首先定义几个基本的操作方法:
由于java支持重载,所以方法名是一样的,只是参数不一样,为了省事一点,对于byte数据我就直接赋值,没有专门写一个方法。
接下来的做法是:
原先的结构体是用c语言来访问的,因为c语言支持结构体指针,因此要访问结构体数据只需要用结构体指针指向数据的入口地址,就可以用->符号把结构体的元素逐一取出来,同样,写入结构体的元素也很方便。
我原先以为在java里面也会有同样的操作方式,结果有点失望,java下面是不能进行这样的操作的。那么如果有一个用c语言代码写的程序保存起来的这样的结构体数据文件,在java里面应该如何访问呢?
假设有一个二进制文件,里面存放了一个这样的结构体:
typedef struct tagSingerType { U08 recordFlag; U08 recordLen; U16 TypeSum; char singerType[STRING_MAX]; }SingerType_s;
那么我们首先把文件读进来,存放到一个byte型的数组里,
in = new FileInputStream(file); DataInputStream dis=new DataInputStream(in); int fileSize = (int)file.length(); byte data[] = new byte[fileSize]; int i = 0; while(dis.available()>0){ i = dis.read(data); } parseBuffer(data);接下来就是分析数据:
singerType.recordFlag = ReadIdxFile.getByteValue(b, pos); singerType.recordLen = ReadIdxFile.getByteValue(b, pos + 1); singerType.TypeSum = ReadIdxFile.getShortValue(b, pos+2, pos+4); int stringLen = singerType.recordLen - SINGER_FIX_LEN; singerType.singerTpye = ReadIdxFile.getStrValue(b, pos+4, pos+SINGER_FIX_LEN+stringLen);其中调用的几个基本方法,是把数组里的字节一个一个取出来:
获取整型,就相当于取4个字节,short型为2个字节,byte是一个字节,字符串是根据具体的长度来取。
public static int getIntValue(byte [] b,int s,int e) { int nR=0; if(s+3<e) { nR = b[s] & 0xff; nR = nR + ( b[s+1]<<8 & 0x0000ff00 ); nR = nR + ( b[s+2]<<16 & 0x00ff0000 ); nR = nR + ( b[s+3]<<24 & 0xff000000 ); } return nR; } public static int getShortValue(byte [] b,int s,int e) { int nR=0; if(s+1<e) { nR = b[s] & 0xff; nR = nR + ( b[s+1]<<8 & 0x0000ff00 ); } return nR; } public static int getByteValue(byte [] b,int s) { int nR=0; nR = b[s] & 0xff; return nR; } public static String getStrValue(byte[] b,int s,int e) { byte[] tb=new byte[e-s+1]; int i=0; for(byte ee:tb) { tb[i++]=0; } i=0; for(byte ee:b) { if(i>=s && i<e) { tb[i-s]= b[i]; } else if(i>=e) { break; } i++; } String r=new String(tb); return r; }
然后,如果想用java保存一个结构体模样的二进制文件,就需要反过来操作。
首先定义几个基本的操作方法:
public static void valuecpy(byte[] b,int s,int e,String msg){ byte cs[] = msg.getBytes(); for(byte c : cs){ b[s] = c; s++; if(s >= e){ System.out.println("reach end of array"); break; } } } public static void valuecpy(byte[] b,int start, int end,int nValue){ b[start] =(byte)(nValue&0x000000ff) ; b[start+1]=(byte)( (nValue&0x0000ff00) >> 8) ; b[start+2]=(byte)( (nValue&0x00ff0000) >> 16) ; b[start+3]=(byte)( (nValue&0xff000000) >> 24) ; } public static void valuecpy(byte[] b,int start, int end,short nValue){ b[start] =(byte)(nValue&0x000000ff) ; b[start+1]=(byte)( (nValue&0x0000ff00) >> 8) ; }
由于java支持重载,所以方法名是一样的,只是参数不一样,为了省事一点,对于byte数据我就直接赋值,没有专门写一个方法。
接下来的做法是:
public void copyToBuf(byte b[]){ b[0] = (byte) this.recordFlag; b[1] = (byte) this.recordLen; ReadIdxFile.valuecpy(b, 2, 3, this.TypeSum); ReadIdxFile.valuecpy(b, 4, this.recordLen, this.singerTpye); }通过这个方法,把数据赋值到byte b[]里面,然后再把数据写入文件,就相当于保存了一个结构体了。
相关文章推荐
- Java 运算符知识整理 学习笔记
- JAVAEE 框架 2016-3-25
- 五、初学SpringMVC+Mybatis之SpringMVC简介
- Java异常分类和统一处理
- Java 输出流中的flush方法
- Spring_Q_collect
- 【JAVA开发之IO流1-3】IO流之缓冲流
- Java内存分配
- super,this的区别和使用
- Java中普通代码块,构造代码块,静态代码块区别及代码示例
- 关于struts2中传入中文参数然后显示到页面出现乱码
- Java——URLEncoder和URLDecoder
- 《Java程序设计基础》 第6章手记
- Spring IoC — 基于注解的配置
- java 之 helloworld
- idea中使用scala运行spark出现Exception in thread "main" java.lang.NoClassDefFoundError: scala/collection/GenTraversableOnce$class
- Spring boot配置cache
- Spring boot配置cache
- Java基础 搭建环境 安装JDK 配置环境变量
- java布局学习(新)