仿C# BinaryReader 读取二进制文件的Java实现代码

时间:2022-02-13 03:59:50

最近手头的活儿暂告一段落,正好有时间整理一下前面做的一个项目,在某些时候,我们需要读取一个格式明确的二进制文件,由于格式确定,我们还需要按照位数来读取相对应的内容(例如,我们需要读取第44位到第56位的这12个字节),说到这儿,很多人大概都会说,这有什么难的,Java读取二进制的方法有一大堆,随便找一个都可以读取,的确,Java的读取方法有很多,但是似乎没有一个读取一个字节就会让当前字节位提升一位的方法,如果你需要按照某个字节来读取,就会出现问题(当然,如果利用复制数组来“曲线救国”,那就另当别论)。

由于C#里的 BinaryReader 其中包含的很多读取二进制的方法都不错,关键是都会自动提升位数,所以就仿着写了一个可以自动提升的工具类BinaryReaderJ,废话不多说,直接上代码:

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* 仿C#BinaryReader的java方法
* @author RKGG
* @version 1.0
* */
public class BinaryReaderJ {


private static File file;
private static InputStream in;
private static DataInputStream dStream;

public BinaryReaderJ(File file){
this.file = file;
try {
in = new FileInputStream(file);
dStream = new DataInputStream(in);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* 读取一个byte
* @author RKGG
* @param 返回int
* */
public static int read(){
int b = 0;
try {
b = dStream.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b;
}

/**
* 一次性读取 length长度
* 返回长度为length的byte[]
* @author RKGG
* @param length 长度
* @return 返回byte[]
* */
public static byte[] read(int length){
byte[] bs = new byte[length];
byte[] rs = new byte[length];
try {
dStream.read(bs,0,length);
System.arraycopy(bs, 0, rs, 0, length);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rs;
}

/**
* 读取2byte 返回1个int
* @author RKGG
* @return int
* */
public static int readInt16(){
byte[] bs = new byte[2];
int temp = 0;
try {
dStream.read(bs,0,2);
temp = HexUtil.byte2int(bs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return temp;
}

/**
* 读取4byte 返回1个int
* @author RKGG
* @return 返回int
* */
public static int readInt32(){
byte[] bs = new byte[4];
int temp = 0;
try {
dStream.read(bs,0,4);
temp = HexUtil.byteArrayToInt(bs, 0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return temp;
}

/**
* 将一个byte[] 按索引位置读取2byte 返回Int
* @author RKGG
* @param byte[]
* @param 起始位置
* @return int
* */
public static int ToInt16(byte[] b,int start){
byte[] bs = new byte[2];
int temp = 0;
System.arraycopy(b, start, bs, 0, 2);
temp = HexUtil.byte2int(bs);
return temp;
}

/**
* 将一个byte[] 按索引位置读取4byte 返回Int
* @author RKGG
* @param byte[]
* @param 起始位置
* @return int
* */
public static int ToInt32(byte[] b,int start){
byte[] bs = new byte[4];
int temp = 0;
System.arraycopy(b, start, bs, 0, 4);
temp = HexUtil.byteArrayToInt(bs, 0);
return temp;
}

/**
* 读取8byte 返回1个double
* @author RKGG
* @return double
* */
public static double readDouble(){
byte[] bs = new byte[8];
double b = 0;
try {
dStream.read(bs,0,8);
b = HexUtil.byteArrayToDouble(bs, 0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b;
}

/**
* 将一个byte[] 按索引位置读取8byte 返回Double
* @author RKGG
* @param byte[]
* @param 起始位置
* @return double
* */
public static double ToDouble(byte[] b,int start){
byte[] bs = new byte[8];
System.arraycopy(b, start, bs, 0, 8);
double d = HexUtil.byteArrayToDouble(bs, 0);
return d;
}

/**
* 读取一个长度为 length*8 的byte[]
* 返回一个长度为 length的double[]
* @author RKGG
* @param length 长度
* @param 返回double[]
* */
public static double[] readDoubles(int length){
byte[] bs = new byte[length*8];
double[] d = new double[length];
try {
dStream.read(bs,0,bs.length);
d = HexUtil.getData(bs, 0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return d;
}

/**
* 读取4byte 返回1个float
* @author RKGG
* @return 返回float
* */
public static float readFloat(){
byte[] bs = new byte[4];
float f = 0;
try {
dStream.read(bs,0,4);
f = HexUtil.byteArrayToFloat(bs, 0, 0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return f;
}

/**
* 将一个byte[] 按索引位置读取4byte返回 1个float
* @author RKGG
* @param byte[]
* @param 起始位置
* @return 返回float
* */
public static float ToFloat(byte[] b,int start){
byte[] bs = new byte[4];
System.arraycopy(b, start, bs, 0, 4);
float f = HexUtil.byteArrayToFloat(bs, 0, 0);
return f;
}

/**
* 读取一个长度为 length*4 的byte[]
* 返回一个长度为 length的float[]
* @author RKGG
* @param length
* @return float[]
* */
public static float[] readFloats(int length){
byte[] bs = new byte[length*4];
float[] fs = new float[length];
try {
dStream.read(bs,0,bs.length);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String s = new String(bs);
String[] ssr = s.split(",");
for (int i = 0; i < fs.length; i++) {
fs[i] = Float.parseFloat(ssr[i]);
}
return fs;
}

/**
* 读取1byte转1char
* @author RKGG
* @return char
* */
public static char readChar(){
byte[] bs = new byte[1];
char ch = 0;
try {
dStream.read(bs,0,1);
ch = HexUtil.byteArrayToChar(bs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ch;
}

/**
* 读取长度为length的byte[]
* 返回长度为length的char[]
* @author RKGG
* @param length
* @return char[]
* */
public static char[] readChars(int length){
byte[] bs = new byte[length];
char[] ch = new char[length];
try {
dStream.read(bs,0,bs.length);
ch = HexUtil.getChars(bs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ch;
}


/**
* 读取一定长度 l的byte[]
* 返回长度为 l的String
* @author RKGG
* @param length
* @return String
* */
public static String readString(int length){
byte[] bs = new byte[length];
String string = "";
try {
dStream.read(bs,0,bs.length);
string = new String(bs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return string;
}


/**
* 读取日期格式的double
* 返回日期格式
* @author RKGG
* @param format
* @return String
* */
public static String readDate(String format){
byte[] bs = new byte[8];
String time = "";
double time_d = 0;
try {
dStream.read(bs,0,8);
time_d = HexUtil.byteArrayToDouble(bs, 0);
time = HexUtil.doubleToDate(time_d, format);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return time;
}

/**
* 读取4byte转1boolean
* @author RKGG
* @param byte[]
* @param start
* @return boolean
* */
public static boolean ToBoolean(byte[] b,int start){
byte[] bs = new byte[4];
System.arraycopy(b, start, bs, 0, 4);
boolean tmp = HexUtil.byteArrayToBoolean(bs, 0);
return tmp;
}

/**
* 关流
* @author RKGG
* */
public static void close(){
try {
dStream.close();
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
HexUtil类如下:

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.xml.transform.Templates;

public class HexUtil {

/**
* 4byte 转 int
* */
public static int byteArrayToInt(byte[] b, int start) {
int value = 0;
byte[] temp = null;
temp = new byte[4];
System.arraycopy(b, start, temp, 0, 4);
value = byte2int(temp);
return value;
}

public static int byteToInt(byte[] b, int offset) {
int value = 0;
for (int i = 0; i < 4; i++) {
int shift = (4 - 1 - i) * 8;
value += (b[i + offset] & 0x000000FF) << shift;
}
return value;
}

/**
* 2byte 转int
* */
public static int byte2int(byte[] res) {
int targets = (res[0] & 0xff) | ((res[1] << 8) & 0xff00);
return targets;
}

/**
* byte[] 转 boolean
* */
public static boolean byteArrayToBoolean(byte[] data, int start) {
if (data == null || data.length < 4) {
return false;
}
byte[] bytes = new byte[4];
System.arraycopy(data, start, bytes, 0, 4);
int tmp = byteArrayToInt(bytes, 0);
return (tmp == 0) ? false : true;
}

/**
* get double[]
* */
public static double[] getData(byte[] bs, int start) {
byte[] data;
double[] yData = new double[bs.length / 8];
int counts = 0;
for (int i = start; i < bs.length - 1;) {
data = new byte[8];
System.arraycopy(bs, i, data, 0, 8);
yData[counts] = byteArrayToDouble(data, 0);
i += 8;
counts++;
}
return yData;
}

public static double byteArrayToDouble(byte[] b, int start) {
long l;
byte[] bytes = new byte[8];
System.arraycopy(b, start, bytes, 0, 8);
l = bytes[0];
l &= 0xff;
l |= ((long) bytes[1] << 8);
l &= 0xffff;
l |= ((long) bytes[2] << 16);
l &= 0xffffff;
l |= ((long) bytes[3] << 24);
l &= 0xffffffffl;
l |= ((long) bytes[4] << 32);
l &= 0xffffffffffl;
l |= ((long) bytes[5] << 40);
l &= 0xffffffffffffl;
l |= ((long) bytes[6] << 48);
l &= 0xffffffffffffffl;
l |= ((long) bytes[7] << 56);
return Double.longBitsToDouble(l);
}

/**
* byte[] 转string
*
* */
public static String byteTostring(byte[] bs) {
String s = "";
try {
s = new String(bs,"GB2312");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return s;
}

/**
* byte[] 转float
* */
public static float byteArrayToFloat(byte[] b, int index, int start) {
int l;
byte[] data = new byte[4];
System.arraycopy(b, start, data, 0, 4);
l = data[index + 0];
l &= 0xff;
l |= ((long) data[index + 1] << 8);
l &= 0xffff;
l |= ((long) data[index + 2] << 16);
l &= 0xffffff;
l |= ((long) data[index + 3] << 24);
return Float.intBitsToFloat(l);
}

/**
* byte[] 转 char
* */
public static char[] getChar(byte[] bytes, int start) {
byte[] data;
char[] data_char = new char[bytes.length / 2];
int counts = 0;
for (int i = start; i < bytes.length - 1;) {
data = new byte[2];
System.arraycopy(bytes, i, data, 0, 2);
data_char[counts] = byteArrayToChar(data);
i += 2;
counts++;
}
return data_char;
}

public static char byteArrayToChar(byte[] b) {
char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF));
return c;
}

public static char[] getChars(byte[] bytes) {
Charset cs = Charset.forName("UTF-8");
ByteBuffer bb = ByteBuffer.allocate(bytes.length);
bb.put(bytes);
bb.flip();
CharBuffer cb = cs.decode(bb);

return cb.array();
}

/**
* double 转 date
* */
public static String doubleToDate(Double d,String format) {
String t;
Calendar base = Calendar.getInstance();
SimpleDateFormat outFormat = new SimpleDateFormat(format);
// Delphi的日期类型从1899-12-30开始
base.set(1899, 11, 30, 0, 0, 0);
base.add(Calendar.DATE, d.intValue());
base.add(Calendar.MILLISECOND, (int) ((d % 1) * 24 * 60 * 60 * 1000));
t = outFormat.format(base.getTime());
return t;
}
}

以上就是仿BinaryReader的Java代码,欢迎大家提出问题与批评指正。