用java语言读取和写人c语音的结构体数据

来源:互联网 发布:js调用摄像头拍照 编辑:程序博客网 时间:2024/06/05 18:06

最近因为要把excel文件的表格数据保存成一个用结构体格式写成的二进制文件,于是研究了一下如何用java来访问二进制数据。

原先的结构体是用c语言来访问的,因为c语言支持结构体指针,因此要访问结构体数据只需要用结构体指针指向数据的入口地址,就可以用->符号把结构体的元素逐一取出来,同样,写入结构体的元素也很方便。

我原先以为在java里面也会有同样的操作方式,结果有点失望,java下面是不能进行这样的操作的。那么如果有一个用c语言代码写的程序保存起来的这样的结构体数据文件,在java里面应该如何访问呢?

假设有一个二进制文件,里面存放了一个这样的结构体:

typedef struct tagSingerType{    U08            recordFlag;    U08            recordLen;    U16            TypeSum;    char        singerType[STRING_MAX];}SingerType_s;

那么我们首先把文件读进来,存放到一个byte型的数组里,

<span style="white-space:pre"></span>in = new FileInputStream(file);<span style="white-space:pre"></span>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);
接下来就是分析数据:

<span style="white-space:pre"></span>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);
其中调用的几个基本方法,是把数组里的字节一个一个取出来:

<span style="white-space:pre"></span>获取整型,就相当于取4个字节,short型为2个字节,byte是一个字节,字符串是根据具体的长度来取。<span style="white-space:pre"></span>
<span style="white-space:pre"></span>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 );  //        nR = nR + ( b[s+2]<<16 & 0x00ff0000 );  //        nR = nR + ( b[s+3]<<24 & 0xff000000 );                  }        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保存一个结构体模样的二进制文件,就需要反过来操作。

首先定义几个基本的操作方法:

<span style="white-space:pre"></span>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数据我就直接赋值,没有专门写一个方法。

接下来的做法是:

<span style="white-space:pre"></span>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[]里面,然后再把数据写入文件,就相当于保存了一个结构体了。














0 0
原创粉丝点击