以前写Android程序解析的数据大多是xml和json数据,但最近因为项目需要以及老师的强制要求,开始解析C++发送过来.dat的数据。网上搜索了很久也没有相关的api可供使用,所以我采用的是根据.dat的数据所占用多少字节进行解码的方法。
c++的结构体:
{
#define POINT_NUM 90
#define FILE_NAME_LEN 260
unsigned short usFileHeaderLen; //文件头长度
char arrFileName[FILE_NAME_LEN]; //完整的数据文件名
unsigned short usWidth; //图像(矩阵)宽度
unsigned short usHeight; //图像(矩阵)高度
unsigned short usBPP; //每个像素所占的字节数
unsigned short usFitType; //拟合类型,0:双指数,1:二阶多项式,2:三阶多项式
int nGain; //相机增益
int nExposureTime; //相机曝光时间
float fC0; //拟合系数,下同
float fC1;
float fC2;
float fC3;
float fC4;
float fC5;
float fC6;
unsigned short usTempOffset; //温度偏移量
unsigned short usMaxHighTemp[LINE_NUM]; //最高温度
unsigned short usMinLowTemp[LINE_NUM]; //最低温度
unsigned short usMeanTemp[LINE_NUM]; //平均温度
unsigned short usLineNum; //= 3; //划线数目(另外两条保留)
unsigned short usPointNum; //= 10; //每条线上虚拟热电偶数目
};
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import com.ht.masteel.domain.DatDomain;
import android.content.Context;
import android.widget.Toast;
/***
* .dat文件的解析类,用于解析从服务器段下载下来的.dat文件
*
* @author htao
*
*/
public class DatParserUtils {
List<DatDomain> datLists = new ArrayList<DatDomain>();
DatDomain datDomain = new DatDomain();
// 读取.dat文件,并将之保存到集合中
ArrayList<Byte> byteLists = (ArrayList<Byte>) readDatFiles(path,
fileName, context);
if(byteLists!=null){
// if(byteLists!=null&&byteLists.size()!=0){
// 获取文件头长度 unsigned short usFileHeaderLen
try {
// 获取文件头的长度
usFileHeaderLen = AsciiToUnsignedShort(byteLists.get(0),
byteLists.get(1));
// 将文件头保存到javabean对象中
datDomain.setUsFileHeaderLen(usFileHeaderLen);// 将文件头的长度添加到JavaBean对象
// 获取完整的数据文件名 char arrFileName[FILE_NAME_LEN]
String arrFileName = "";
for (int i = 2; i < 262; i++) {
arrFileName += byteToAscii(byteToBinary(byteLists.get(i)));
arrFileName = arrFileName.trim();// 去掉数据文件名数组多余的空格
}
datDomain.setArrFileName(arrFileName);// 将数据文件名添加到JavaBean中
// 获取图像矩阵的宽度 unsigned short usWidth
usWidth = AsciiToUnsignedShort(byteLists.get(262),
byteLists.get(263));
datDomain.setUsWidth(usWidth);
// 获取图像矩阵的高度 unsigned short usHeight
usHeight = AsciiToUnsignedShort(byteLists.get(264),
byteLists.get(265));
datDomain.setUsHeight(usHeight);// 将图像矩阵的高度添加到JavaBean中
// usBPP获取每个像素所占的字节数 unsigned short usBPP
usBPP = AsciiToUnsignedShort(byteLists.get(266), byteLists.get(267));
datDomain.setUsBPP(usBPP);
// 相机增益 int nGain
nGain = asciiToInteger(byteLists.get(272), byteLists.get(273),
byteLists.get(274), byteLists.get(275));
datDomain.setnGain(nGain);
// nExposureTime 相机曝光时间 int nExposureTime
nExposureTime = asciiToInteger(byteLists.get(276),
byteLists.get(277), byteLists.get(278), byteLists.get(279));
datDomain.setnExposureTime(nExposureTime);
// 拟合系数fC0,fC1,fC2,fC3,fC4,fC5,fC6 (float)
fC0 = asciiToFloat(byteLists.get(280), byteLists.get(281),
byteLists.get(282), byteLists.get(283));
datDomain.setfC0(fC0);
fC1 = asciiToFloat(byteLists.get(284), byteLists.get(285),
byteLists.get(286), byteLists.get(287));
datDomain.setfC1(fC1);
fC2 = asciiToFloat(byteLists.get(288), byteLists.get(289),
byteLists.get(290), byteLists.get(291));
datDomain.setfC2(fC2);
fC3 = asciiToFloat(byteLists.get(292), byteLists.get(293),
byteLists.get(294), byteLists.get(295));
datDomain.setfC3(fC3);
fC4 = asciiToFloat(byteLists.get(296), byteLists.get(297),
byteLists.get(298), byteLists.get(299));
datDomain.setfC4(fC4);
fC5 = asciiToFloat(byteLists.get(300), byteLists.get(301),
byteLists.get(302), byteLists.get(303));
datDomain.setfC5(fC5);
fC6 = asciiToFloat(byteLists.get(304), byteLists.get(305),
byteLists.get(306), byteLists.get(307));
datDomain.setfC6(fC6);
// 温度偏移量 unsigned short usTempOffset;
usTempOffset = AsciiToUnsignedShort(byteLists.get(308),
byteLists.get(309));
datDomain.setUsTempOffset(usTempOffset);
// 最高温度 unsigned short usMaxHighTemp[LINE_NUM]=unsigned short
// usMaxHighTemp[3]
usMaxHighTemp1 = AsciiToUnsignedShort(byteLists.get(310),
byteLists.get(311));
usMaxHighTemp2 = AsciiToUnsignedShort(byteLists.get(312),
byteLists.get(313));
usMaxHighTemp3 = AsciiToUnsignedShort(byteLists.get(314),
byteLists.get(315));
datDomain.setUsMaxHighTemp1(usMaxHighTemp1);
datDomain.setUsMaxHighTemp2(usMaxHighTemp2);
datDomain.setUsMaxHighTemp3(usMaxHighTemp3);
// 最低温度unsigned short usMinLowTemp[LINE_NUM]=unsigned short
// usMinLowTemp[3]
usMinLowTemp1 = AsciiToUnsignedShort(byteLists.get(316),
byteLists.get(317));
usMinLowTemp2 = AsciiToUnsignedShort(byteLists.get(318),
byteLists.get(319));
usMinLowTemp3 = AsciiToUnsignedShort(byteLists.get(320),
byteLists.get(321));
datDomain.setUsMinLowTemp1(usMinLowTemp1);
datDomain.setUsMinLowTemp2(usMinLowTemp2);
datDomain.setUsMinLowTemp3(usMinLowTemp3);
// 平均温度 unsigned short usMeanTemp[LINE_NUM]=unsigned short
// usMeanTemp[3]
usMeanTemp1 = AsciiToUnsignedShort(byteLists.get(322),
byteLists.get(323));
usMeanTemp2 = AsciiToUnsignedShort(byteLists.get(324),
byteLists.get(325));
usMeanTemp3 = AsciiToUnsignedShort(byteLists.get(326),
byteLists.get(327));
datDomain.setUsMeanTemp1(usMeanTemp1);
datDomain.setUsMeanTemp2(usMeanTemp2);
datDomain.setUsMeanTemp3(usMeanTemp3);
// 划线数目(另外两条保留)unsigned short usLineNum; //= 3;
usLineNum = AsciiToUnsignedShort(byteLists.get(328),
byteLists.get(329));
datDomain.setUsLineNum(usLineNum);
// 每条线上虚拟热电偶数目 unsigned short usPointNum; //= 10
usPointNum = AsciiToUnsignedShort(byteLists.get(330),
byteLists.get(331));
datDomain.setUsPointNum(usPointNum);
bLineExist1 = asciiToBool(byteLists.get(332), byteLists.get(333),
byteLists.get(334), byteLists.get(335));
datDomain.setbLineExist1(bLineExist1);
bLineExist2 = asciiToBool(byteLists.get(336), byteLists.get(337),
byteLists.get(338), byteLists.get(339));
datDomain.setbLineExist2(bLineExist2);
bLineExist3 = asciiToBool(byteLists.get(340), byteLists.get(341),
byteLists.get(342), byteLists.get(343));
datDomain.setbLineExist3(bLineExist3);
datLists.add(datDomain);// 将JavaBean添加到集合中
return datLists;
} catch (Exception e) {
e.printStackTrace();// 抛出异常
}
}
return null;
}
/***
* 该方法将byte类型的数值转换成二进制的字符串
*
* @param b
* byte类型的数字
* @return 转换后的二进制字符串
*/
public static String byteToBinary(byte b) {
String binary = Integer.toBinaryString(b & 0xff);
String str = binary;// "10"
// 8-binary.length()是需要前位补0的0的个数
for (int i = 0; i < 8 - binary.length(); i++) {// 2需要补六个0 i<6
str = "0" + str;
}
// String codeFormat="%0"+(8-binary.length())+"s";
// binary=String.format(codeFormat, binary);
return str;
}
/****
* 将8位字节转换成ASCII码值
*
* @param binary
* @return
*/
public static char byteToAscii(String binary) {
char[] chs = binary.toCharArray();
int sum = 0;
int k = 0;
for (int i = chs.length - 1; i >= 0; i--) {
// System.out.print(chs[i]+" ");
sum += Integer.parseInt(chs[i] + "") * Math.pow(2, k);
k++;
}
// System.out.println("sum="+sum);
return (char) sum;
}
/***
* 通过读取两个8bit的Ascii码,将他转换成c++类型的unsigned short类型,并以java 中的int类型返回
*
* @param byte1
* 第一个字节的二进制
* @param byte2
* 第二个字节的二进制
* @return 返回合并后的目标数字
*/
public static int AsciiToUnsignedShort(byte byte1, byte byte2) {
// 将二进制数转换成字符串类型并合并,获取合并后的字符串
String addByte = byteToBinary(byte2) + byteToBinary(byte1);
// 将合并后的字符串转换成int类型
// 将String转换成char[]数组
char[] byteChs = addByte.toCharArray();
// 将char[]数组转换成int类型
int sum = 0;
int k = 0;
for (int i = byteChs.length - 1; i >= 0; i--) {
// System.out.print(chs[i]+" ");
sum += Integer.parseInt(byteChs[i] + "") * Math.pow(2, k);
k++;
}
return sum;
}
/****
* 通过读取4个byte,将之转换成c++中的int类型,并返回Java中的int类型的数值
*
* @param byte1
* 第一个字节
* @param byte2
* 第二个字节
* @param byte3
* 第三个字节
* @param byte4
* 第四个字节
* @return 转换后的Integer类型的数据
*/
public static int asciiToInteger(byte byte1, byte byte2, byte byte3,
byte byte4) {
// 将二进制数转换成字符串类型并合并,获取合并后的字符串
String addByte = byteToBinary(byte4) + byteToBinary(byte3)
+ byteToBinary(byte2) + byteToBinary(byte1);
// 将String转换成char[]数组
char[] byteChs = addByte.toCharArray();
// 将char[]数组转换成int类型
int sum = 0;
int k = 0;
for (int i = byteChs.length - 1; i >= 0; i--) {
sum += Integer.parseInt(byteChs[i] + "") * Math.pow(2, k);
k++;
}
return sum;
}
/****
* 将 二进制的ascii转换成c++的float数据类型,并返回Java中的float类型的数据
*
* @param byte1
* 第一个字节
* @param byte2
* 第二个字节
* @param byte3
* 第三个字节
* @param byte4
* 第四个字节
* @return java中的float数据类型的数值
*/
public static float asciiToFloat(byte byte1, byte byte2, byte byte3,
byte byte4) {
// 将ascii转换成int类型的数据
int i = asciiToInteger(byte1, byte2, byte3, byte4);
return Float.intBitsToFloat(i);
}
/****
* 将数据输入流转换成字符串
* @param in 数据输入流
* @return 返回转换后的字符串
*/
public static String inputstream2String(InputStream in){
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];//每次读取1024kb个字节
int temp=-1;
try{
while((temp=in.read(buffer))!=-1){
baos.write(buffer,0,temp);
}
return baos.toString();
}catch(Exception e){
e.printStackTrace();
}finally{
try {
in.close();
baos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
其中DatDomain是JavaBean对象,用来存储解析后的数据。
解析结果如下:
usFileHeaderLen=740
arrFileName=/Video0/Data/2018/05/16/2018-05-1612-52-04.dat
usWidth=1600
usHeight=1200
usBpp=1
usFitType=0
nGain=24
nExposureTime=20000
fC0=0.0
fC1=0.0
fC2=0.0
fC3=0.0
fC4=0.0
fC5=0.0
fC6=0.0
usTempOffset=0
usMaxHighTemp1=1500
usMaxHighTemp2=1500
usMeanTemp1=5
usMeanTemp2=5
usMeanTemp3=5
usMaxHighTemp3=1500
usMinLowTemp1=100
usMinLowTemp2=100
usMinLowTemp3=100
usLineNum=3
usPointNum=10