java字节数组流操作

需求

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

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!

完美满足需求

展开阅读全文

没有更多推荐了,返回首页