一、实践目的
- 先用java写一个tcp服务器,接收来自客户端的数据,解析入库mysql,为后续查库做准备。
二、步骤
在上一笔记中,开了tcp服务器将数据解析然后保存到txt文档,在这个基础上添加上mysql,库tcpdb1是由人手动创建,表由程序中检测自动创建个weathertable表,客户端发送数据后先检查帧尾和CRC校验,避免一些错误数据的输入,然后将未解析的数据按日、小时分文档保存到本地日志txt,将解析的数据自动入库,客户端发送的数据帧是自定了一个简单的数据格式。
写了4个class文件:
TCPService.class : 程序的入口,开启tcp服务器
Parameter.class : 解析的参数
jdbc.class : 与数据库之间的操作
CRC16.class : crc16的数据校验
工程环境
1、需要添加jdbc,就是添加一个包(mysql-connector-java-5.1.37-bin.jar),类似库文件,能够使用java语句开发数据库,和mysql连接起来。
2、首先开个tcp服务器端口,使用ServiceSocke中accept一直监听,有客户端连接就开启一个线程,获取客户端发送的数据,检查数据帧尾和校验;
3、校验成功说明来的数据没问题,将数据做txt日志保存一下,按日份文件夹,按小时分文件,日志中记录数据接收时的时间;
4、保存完日志可以将整条数据分块解析了,创建个对象Para存起来,供入库时的参数输入;
5、参数值已经有了,现在可以入库,但这个库需要人工提前创建出来,一条创建库的语句就OK,这里起个库名叫tcpdb1,然后注册驱动(不注册也没关系,因为添加的jar包中已经注册过),获取数据库连接对象,定义sql语句,检查表是否已经创建过,不存在则创建,然后将解析的各个参数入库,释放资源。
三、结果
1、按日分文档,按小时分文件保存为txt日志
2、客户端发送数据,服务器解析数据,入库
四、代码
(1)TCPService.class(程序的入口,开启tcp服务器)
package com.ta.tcpsevice;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.lang.String;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.jar.JarOutputStream;
import java.util.zip.CRC32;
/*
实现步骤:
1.创建一个服务器ServerSocket对象,和系统要指定的端口号
2.使用ServerSocket对象中的方法accept,获取到请求的客户端Socket对象
3.使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
4.判断d:\\upload文件夹是否存在,不存在则创建
5.创建一个本地字节输出流FileOutputStream对象,构造方法中绑定要输出的目的地
6.使用网络字节输入流InputStream对象中的方法read,读取客户端上传的文件
7.使用本地字节输出流FileOutputStream对象中的方法write,把读取到的文件保存到服务器的硬盘上
8.使用Socket对象中的方法getOutputStream,获取到网络字节输出流OutputStream对象
9.使用网络字节输出流OutputStream对象中的方法write,给客户端回写"上传成功"
10.释放资源(FileOutputStream,Socket,ServerSocket)
*/
//#DATATIME=2019/7/10 13:26:46:123,SN=TG00001,TEMP=025.6C,RH=78%,PA=101.32kpa,WS=02.1m/s,WD=268,LO=121.9590627E,LA=036.9576059N,CRC=1C7F\r\n 发送过来的数据结尾\r\n是0d0a,测试校验时需要注意,校验到=
//程序中意外情况没有处理,数据末尾应该加个校验可减少意外数据
public class TCPService {
public static void main(String[] args) throws IOException {
System.out.println("服务端启动 , 等待连接 .... ");
//1.创建一个服务器ServerSocket对象,和系统要指定的端口号
ServerSocket server = new ServerSocket(6665);
//2.使用ServerSocket对象中的方法accept,获取到请求的客户端Socket对象
/*
让服务器一直处于监听状态(死循环accept方法)
有一个客户端上传文件,就保存一个文件
*/
while(true){
Socket socket = server.accept();
/*
使用多线程技术,提高程序的效率
有一个客户端上传文件,就开启一个线程,完成文件的上传
*/
new Thread(new Runnable() {
//完成文件的上传
@Override
public void run() {
try {
System.out.println("客户端已连接");
//3.使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//4.使用网络字节输入流InputStream对象中的方法read,读取客户端上传的文件或数据
int len =0;
byte[] bytes = new byte[1024];
while((len = is.read(bytes))!=-1){ //只要还存在数据或者来了新的数据
String GetStr=new String(bytes); //收到的字符串
CRC16 crcClass=new CRC16();
int crcValue=crcClass.calcCrc16(bytes,0,len-6);//需注意这里的len,不要用bytes.length,去掉crc字符1c7f的4个字节,0d0a回车换行2个字节
int indexOfCRC=GetStr.indexOf("CRC="); //获得第一个"DATETIME="的首地址位置 即“D”位置
String CRCStr=GetStr.substring(indexOfCRC+4,indexOfCRC+8); //根据第"D"后的位置,截取 字符串。
int CRC16StrValue= Integer.parseInt(CRCStr,16);//将字符串转换为16进制的数
if(bytes[len-2]==0x0D&&bytes[len-1]==0x0A&&len>20&&CRC16StrValue==crcValue)
{
System.out.println("接收到帧尾且数据校验通过");
/***存日志***/
SimpleDateFormat dfFolder = new SimpleDateFormat("yyyyMMdd");//设置日期格式
String folderName=dfFolder.format(new Date()).toString();
SimpleDateFormat dfFile = new SimpleDateFormat("yyyyMMddHH");//设置日期格式
String fileName=dfFile.format(new Date()).toString();
//5.判断文件夹是否存在,不存在则创建
File file = new File("d:\\upload"+"\\"+folderName);
if(!file.exists()){
file.mkdirs();
}
//6.创建一个本地字节输出流FileOutputStream对象,构造方法中绑定要输出的目的地
FileOutputStream fos = new FileOutputStream(file+"\\"+fileName+".txt",true); //true追加数据
SimpleDateFormat dfDataCome = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"); //设置日期格式毫秒
String dataComeTime=dfDataCome.format(new Date()).toString()+" ";
//7.使用本地字节输出流FileOutputStream对象中的方法write,把读取到的文件保存到服务器的硬盘上
fos.write(dataComeTime.getBytes(),0,dataComeTime.length());
fos.write(GetStr.getBytes(),0,len); //将接收到的数据存储日志文件,按年月日分文件夹,按日小时分文件存储
//fos.write("\r\n".getBytes());//写个换行
fos.close();
System.out.println("该条日志存储完毕");
/***解析入库***/
Parameter Para= new Parameter();
int indexOfDataTime=GetStr.indexOf("DATATIME="); //获得第一个"DATETIME="的首地址位置 即“D”位置
String DataTimeStr=GetStr.substring(indexOfDataTime+9,indexOfDataTime+31); //根据第"D"后的位置,截取 字符串。
Para.setDatatime(DataTimeStr);
int indexOfSN=GetStr.indexOf("SN="); //获得第一个"SN="的首地址位置 即“S”位置
String SNStr=GetStr.substring(indexOfSN+3,indexOfSN+10); //根据第"SN="后的位置,截取 字符串。
//index=bytes.toString().indexOf(",", index+1);//根据第一个"SN="的位置 获得第二个","的位置
Para.setSn(SNStr);
int indexOfTEMP=GetStr.indexOf("TEMP="); //获得第一个""的首地址位置 即“”位置
String TEMPStr=GetStr.substring(indexOfTEMP+5,indexOfTEMP+10); //根据第""后的位置,截取 字符串。
Para.setAirtemperature(Double.parseDouble(TEMPStr));
int indexOfRH=GetStr.indexOf("RH="); //获得第一个""的首地址位置 即“”位置
String RHStr=GetStr.substring(indexOfRH+3,indexOfRH+5); //根据第""后的位置,截取 字符串。
Para.setAirhumidity(Double.parseDouble(RHStr));
int indexOfPA=GetStr.indexOf("PA="); //获得第一个""的首地址位置 即“”位置
String PAStr=GetStr.substring(indexOfPA+3,indexOfPA+9); //根据第""后的位置,截取 字符串。
Para.setAirpressure(Double.parseDouble(PAStr));
int indexOfWS=GetStr.indexOf("WS="); //获得第一个""的首地址位置 即“”位置
String WSStr=GetStr.substring(indexOfWS+3,indexOfWS+7); //根据第""后的位置,截取 字符串。
Para.setWindspeed(Double.parseDouble(WSStr));
int indexOfWD=GetStr.indexOf("WD="); //获得第一个""的首地址位置 即“”位置
String WDStr=GetStr.substring(indexOfWD+3,indexOfWD+6); //根据第""后的位置,截取 字符串。
Para.setWinddirection(Double.parseDouble(WDStr));
int indexOfLO=GetStr.indexOf("LO="); //获得第一个""的首地址位置 即“”位置
String LOStr=GetStr.substring(indexOfLO+3,indexOfLO+15); //根据第""后的位置,截取 字符串。
Para.setLongitude(LOStr);
int indexOfLA=GetStr.indexOf("LA="); //获得第一个""的首地址位置 即“”位置
String LAStr=GetStr.substring(indexOfLA+3,indexOfLA+15); //根据第""后的位置,截取 字符串。
Para.setLatitude(LAStr);
jdbc.InsertDataToMySql(Para);//入库
System.out.println("数据写入完毕");
//8.使用Socket对象中的方法getOutputStream,获取到网络字节输出流OutputStream对象
//9.使用网络字节输出流OutputStream对象中的方法write,给客户端回写"上传成功"
socket.getOutputStream().write("Data upload successful!".getBytes());
//break;//既然数据都已经保存完毕,那就结束这次连接吧,如果想保持长连接就注释掉吧
}
}
System.out.println("断开连接");
//10.释放资源(FileOutputStream,Socket,ServerSocket)
socket.close();
}catch (IOException e){
System.out.println(e);
}
}
}).start();
}
//服务器就不用关闭
//server.close();
}
}
(2)jdbc.class(与数据库之间的操作)
package com.ta.tcpsevice;
import java.sql.*;
/**
* JDBC快速入门
*/
public static class jdbc {
//需要先手动创建一个数据库tcpdb1,库中的表及数据在程序中添加
public void InsertDataToMySql(Parameter paravalue) {
Connection conn = null;
Statement stmt = null;
try {
//1. 导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//3.获取数据库连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/tcpdb1", "root", "root");
DatabaseMetaData meta = (DatabaseMetaData) conn.getMetaData();
ResultSet set = meta.getTables(null, null, "weathertable", null);//weathertable为表名,看表是否存在
if (set.next()) {
System.out.println("表已存在");
} else {
System.out.println("创建表");
//4.定义sql语句
String sql = "CREATE TABLE weathertable " +
"(id INT PRIMARY KEY AUTO_INCREMENT," +
"datatime VARCHAR (30)," +
"sn VARCHAR (20)," +
"airtemperature DOUBLE," +
"airhumidity DOUBLE," +
"airpressure DOUBLE," +
"windspeed DOUBLE," +
"winddirection DOUBLE," +
"longitude VARCHAR (20),"+
"latitude VARCHAR (20)) ";
//5.获取执行sql的对象 Statement
stmt = conn.createStatement();
//6.执行sql
int count = stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
}
set.close();//释放paravalue.getDatetime()
String sql = "INSERT INTO weathertable " +
"(datatime," +
"sn," +
"airtemperature," +
"airhumidity," +
"airpressure," +
"windspeed," +
"winddirection," +
"longitude," +
"latitude" +
")" +
"VALUES"+
"('"+paravalue.getDatatime()+"',"+
"'"+paravalue.getSn()+"',"+
paravalue.getAirtemperature()+","+
paravalue.getAirhumidity()+","+
paravalue.getAirpressure()+","+
paravalue.getWindspeed()+","+
paravalue.getWinddirection()+","+
"'"+paravalue.getLongitude()+"',"+
"'"+paravalue.getLatitude()+"');";
//5.获取执行sql的对象 Statement
stmt = conn.createStatement();
//6.执行sql
int count = stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
System.out.println("数据插入完成");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//7.释放资源
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
(3)Parameter.class(解析的参数)
package com.ta.tcpsevice;
/**
* 封装参数列表
*/
public class Parameter {
private String datatime;
private String sn;
private double airtemperature;
private double airhumidity;
private double airpressure;
private double windspeed;
private double winddirection;
private String longitude;
private String latitude;
public String getDatatime() {
return datatime;
}
public void setDatatime(String datatime) {
this.datatime = datatime;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public double getAirtemperature() {
return airtemperature;
}
public void setAirtemperature(double airtemperature) {
this.airtemperature = airtemperature;
}
public double getAirhumidity() {
return airhumidity;
}
public void setAirhumidity(double airhumidity) {
this.airhumidity = airhumidity;
}
public double getAirpressure() {
return airpressure;
}
public void setAirpressure(double airpressure) {
this.airpressure = airpressure;
}
public double getWindspeed() {
return windspeed;
}
public void setWindspeed(double windspeed) {
this.windspeed = windspeed;
}
public double getWinddirection() {
return winddirection;
}
public void setWinddirection(double winddirection) {
this.winddirection = winddirection;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
}
(4)CRC16.class(crc16的数据校验)
package com.ta.tcpsevice;
public class CRC16 {
static byte[] crc16_tab_h = { (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0,
(byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1,
(byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
(byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0,
(byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40 };
static byte[] crc16_tab_l = { (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04, (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8, (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC, (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12,
(byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10, (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4, (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38, (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C, (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7,
(byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0, (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4, (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68, (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C, (byte) 0xB4, (byte) 0x74,
(byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0, (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54, (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98, (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D,
(byte) 0x4C, (byte) 0x8C, (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40 };
/**
* 计算CRC16校验
*
* @param data
* 需要计算的数组
* @return CRC16校验值
*/
public static int calcCrc16(byte[] data) {
return calcCrc16(data, 0, data.length);
}
/**
* 计算CRC16校验
*
* @param data
* 需要计算的数组
* @param offset
* 起始位置
* @param len
* 长度
* @return CRC16校验值
*/
public static int calcCrc16(byte[] data, int offset, int len) {
return calcCrc16(data, offset, len, 0xffff);
}
/**
* 计算CRC16校验
*
* @param data
* 需要计算的数组
* @param offset
* 起始位置
* @param len
* 长度
* @param preval
* 之前的校验值
* @return CRC16校验值
*/
public static int calcCrc16(byte[] data, int offset, int len, int preval) {
int ucCRCHi = (preval & 0xff00) >> 8;
int ucCRCLo = preval & 0x00ff;
int iIndex;
for (int i = 0; i < len; ++i) {
iIndex = (ucCRCLo ^ data[offset + i]) & 0x00ff;
ucCRCLo = ucCRCHi ^ crc16_tab_h[iIndex];
ucCRCHi = crc16_tab_l[iIndex];
}
return ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;
}
// 测试
public static void main(String[] args) {
// 0x02 05 00 03 FF 00 , crc16=7C 09
int crc = CRC16.calcCrc16(new byte[] { 0x02, 0x05, 0x00, 0x03, (byte) 0xff, 0x00 });
System.out.println(String.format("0x%04x", crc));
}
}