java字节数组流操作

时间:2022-09-03 08:25:37

需求

先给一个需求,给一个字节数组,然后往这个数组中放入各种数据,比如整形,浮点型,字符串等。

java内置类

java提供了两个流来操作数组,ByteArrayOutputStream和ByteArrayInputStream。然后使用DataOutputStream和DataInputStream流封装一下,就可以写入不同类型的数据。看似满足需求,但是ByteArrayOutputStream这个类并没有传入一个数组的构造方法,只有一个传入一个长度,然后new出一个数组,如下:

 public ByteArrayOutputStream(int size) {
if (size < 0) {
throw new IllegalArgumentException("Negative initial size: " + size);
}
buf = new byte[size];
}

ByteArrayOutputStream写完数据之后,需要转化为数组,方法如下:

 public synchronized byte toByteArray()[] {
return Arrays.copyOf(buf, count);
}

copyOf方法会重新new一个新的数组,如下:

public static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}

不仅不满足我们的需求,而且还创建出来两个数组,如果数据比较大的话,还是比较消耗内存。而且一般项目中都有字节缓冲池,一般建议不要擅自创建比较大的数据,一方面是消耗内存,一方面是消耗性能。

我们不妨看一下,实现的方法:

ByteArrayOutputStream baos = new ByteArrayOutputStream(10000);//此处会创建一个数组
DataOutputStream dos = new DataOutputStream(baos);

dos.writeByte(10);
dos.writeShort(23);
dos.writeInt(1111);
dos.writeLong(3333333);
dos.writeBoolean(true);
dos.writeChar('a');
dos.writeFloat(0.123f);
dos.writeDouble(10.123d);
dos.writeUTF("hello world!");

byte[] byteArray = baos.toByteArray();//此处会创建第二个数组

ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
DataInputStream bis = new DataInputStream(bais);

System.out.println(bis.readByte());
System.out.println(bis .readShort());
System.out.println(bis.readInt());
System.out.println(bis.readLong());
System.out.println(bis.readBoolean());
System.out.println(bis.readChar());
System.out.println(bis.readFloat());
System.out.println(bis.readDouble());
System.out.println(bis.readUTF());

输出结果如下:

10
23
1111
3333333
true
a
0.123
10.123
hello world!

自定义实现

输出流

import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;

public class ByteArrayOutStream implements DataOutput {
/**
* 数组
*/

private byte [] buf;

/**
* 下标位置
*/

private int index;

public ByteArrayOutStream(byte[] array){
this.buf = array;
}


public ByteArrayOutStream(byte[] array,int offset){
this.buf = array;
this.index = offset;
}

@Override
public void write(int b) throws IOException {
intToBytes(b);
}

@Override
public void write(byte[] b) throws IOException {
if(b == null || b.length == 0){
return;
}

for(byte i : b){
writeByte(i);
}
}

@Override
public void write(byte[] b, int off, int len) throws IOException {
if(b == null || b.length == 0){
return;
}

if(off+len >= b.length){
throw new IOException("传入的数组长度不足");
}

for(int i=off;i<off+len;i++){
writeByte(b[i]);
}

}

@Override
public void writeBoolean(boolean v) throws IOException {
if(v){
writeByte(1);
}else{
writeByte(0);
}
}


@Override
public void writeByte(int v) throws IOException {
this.buf[index] = (byte)v;
indexInc(1);
}

@Override
public void writeShort(int v) throws IOException {
shortToBytes(v);
}

@Override
public void writeChar(int v) throws IOException {
shortToBytes(v);
}

@Override
public void writeInt(int v) throws IOException {
write(v);
}

@Override
public void writeLong(long v) throws IOException {
longToBytes(v);
}

@Override
public void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}

@Override
public void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}

@Override
public void writeBytes(String s) throws IOException {
writeUTF(s);
}



@Override
public void writeChars(String s) throws IOException {
writeUTF(s);
}

@Override
public void writeUTF(String s) throws IOException {
strToBytes(s);
}


private void strToBytes(String s)throws IOException{
int len = s.length();
if(len > 65535){
throw new IOException("字符串长度太长");
}

writeShort(len);
for(int i=0;i<len;i++){
char charAt = s.charAt(i);
writeShort(charAt);
}

}


private void intToBytes(int v) {
for(int i = 0; i < 4; i++) {
buf[index + i] = (byte)(v >>> (24 - i * 8));
}

indexInc(4);
}


private void shortToBytes(int v){
for(int i = 0; i < 2; i++) {
buf[index + i] = (byte)(v >>> (8 - i * 8));
}

indexInc(2);
}

private void longToBytes(long v){
for(int i = 0; i < 8; i++) {
buf[index + i] = (byte)(v >>> (56 - i * 8));
}

indexInc(8);
}



private void indexInc(int inc){
this.index += inc;
}

public String toString(){
return Arrays.toString(buf);
}


public static void main(String ...args)throws Exception{
byte [] array = new byte[10];
ByteArrayOutStream out = new ByteArrayOutStream(array,0);
out.writeInt(2000);

System.out.println(out);
}

public int getIndex() {
return index;
}



}

输入流

import java.io.DataInput;
import java.io.IOException;

public class ByteArrayInStream implements DataInput{

private byte[] buf;
private int index;
private int offset;
private int length;


public ByteArrayInStream(byte[] array){
this.buf = array;
}


public ByteArrayInStream(byte[] array,int offset,int length){
this.buf = array;
this.offset = offset;
this.index = offset;
}


public boolean isAtEnd(){
return index - offset == length;
}

@Override
public void readFully(byte[] b) throws IOException {
}

@Override
public void readFully(byte[] b, int off, int len) throws IOException {
}

@Override
public int skipBytes(int n) throws IOException {
this.index += n;
return this.index;
}

@Override
public boolean readBoolean() throws IOException {
boolean result = false;
if(buf[index] == 1){
result = true;
}
indexInc(1);
return result;
}

@Override
public byte readByte() throws IOException {
byte result = buf[index];
indexInc(1);
return result;
}

@Override
public int readUnsignedByte() throws IOException {
int result = buf[index] & 0xFF;
indexInc(1);
return result;
}

public byte[] readBytes(int len){
byte [] result = new byte[len];
for(int i = index;i<index + len;i++){
result[i-index] = buf[i];
}
return result;
}

@Override
public short readShort() throws IOException {
return bytesToShort();
}

@Override
public int readUnsignedShort() throws IOException {
return bytesToUnsignShort();
}


@Override
public char readChar() throws IOException {
return (char)readShort();
}

@Override
public int readInt() throws IOException {
return bytesToInt();
}

@Override
public long readLong() throws IOException {
return bytesToLong();
}

@Override
public float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}

@Override
public double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}

@Override
public String readLine() throws IOException {
return readUTF();
}

@Override
public String readUTF() throws IOException {
return bytesToString();
}


private String bytesToString()throws IOException{
int len = readUnsignedShort();
char[] array = new char[len];
for(int i=0;i<len;i++){
array[i] = readChar();
}
return new String(array);
}

private long bytesToLong() {
long num = 0;
for(int i = index; i < index+8; i++) {
num <<= 8;
num |= (buf[i] & 0xff);
}
indexInc(8);
return num;
}

private int bytesToInt() {
int num = 0;
for(int i = index; i < index+4; i++) {
num <<= 8;
num |= (buf[i] & 0xff);
}
indexInc(4);
return num;
}

private short bytesToShort() {
short num = 0;
for(int i = index; i < index+2; i++) {
num <<= 8;
num |= (buf[i] & 0xff);
}
indexInc(2);
return num;
}


private int bytesToUnsignShort() {
int num = 0;
for(int i = index; i < index+2; i++) {
num <<= 8;
num |= (buf[i] & 0xff);
}
indexInc(2);
return num;
}


private void indexInc(int n){
this.index += n;
}

}

测试

byte [] array = new byte[10000];//创建一个数组

ByteArrayOutStream out = new ByteArrayOutStream(array);
out.writeByte(10);
out.writeShort(23);
out.writeInt(1111);
out.writeLong(3333333);
out.writeBoolean(true);
out.writeChar('a');
out.writeFloat(0.123f);
out.writeDouble(10.123d);
out.writeUTF("hello world!");


ByteArrayInStream in = new ByteArrayInStream(array);
System.out.println(in.readByte());
System.out.println(in.readShort());
System.out.println(in.readInt());
System.out.println(in.readLong());
System.out.println(in.readBoolean());
System.out.println(in.readChar());
System.out.println(in.readFloat());
System.out.println(in.readDouble());
System.out.println(in.readUTF());

输出结果如下:

10
23
1111
3333333
true
a
0.123
10.123
hello world!

完美满足需求