给你的流添加缓冲装置——字节块ByteChunk

简介: 这是一个很重要的一个字节数组处理缓冲工具,它封装了字节缓冲器及对字节缓冲区的操作,包括对缓冲区的写入、读取、扩展缓冲区大小等等,另外还提供相应字符编码的转码操作。

这是一个很重要的一个字节数组处理缓冲工具,它封装了字节缓冲器及对字节缓冲区的操作,包括对缓冲区的写入、读取、扩展缓冲区大小等等,另外还提供相应字符编码的转码操作。此工具让缓冲操作变得更加方便,除了缓冲区他还有两个channel——ByteInputChannel和ByteOutputChannel,这两个通道一个用于输入读取数据,一个用于输出数据,并且会自动判断缓冲区是否超出规定的缓冲大小,一旦超出则把缓冲区数据全部输出。

如上图,缓冲区buf负责存放待输出的字节数组,此区域有初始值及最大值,在运行时会根据实际进行扩充,一旦到达最大值则马上输出到指定目标。此外还定义了两个内部接口——ByteInputChannel和ByteOutputChannel,一般可以认为一个用于读取数据一个用于输出数据。另外它还包含Chartset对象,有了它可以方便转码工作。下面用一个简化例子说明字节块的工作机制,受篇幅影响,为使例子简洁这里省去了很多方法和Chartset对象,只展示缓冲的工作机制。

①   字节块ByteChunk的简洁实现,包含数据读取输出接口、内存分配方法allocate、缓冲区添加字节方法append、缓冲区扩容方法makeSpace及刷新缓冲区方法flushBuffer。

public final class ByteChunk {

       public static interface ByteInputChannel{

                public int realReadBytes(bytecbuf[], int off, int len)

                                   throwsIOException;

       }

       public static interface ByteOutputChannel{

                public void realWriteBytes(bytecbuf[], int off, int len)

                                   throwsIOException;

       }

 

       private byte[] buff;

       private int start = 0;

       private int end;

       private int limit = -1;

       private ByteInputChannel in = null;

       private ByteOutputChannel out = null;

 

       public ByteChunk() {

       }

 

       public void allocate(int initial, intlimit) {

                if (buff == null || buff.length< initial) {

                         buff = newbyte[initial];

                }

                this.limit = limit;

                start = 0;

                end = 0;

       }

       public void setByteInputChannel(ByteInputChannelin) {

                this.in = in;

       }

       public voidsetByteOutputChannel(ByteOutputChannel out) {

                this.out = out;

       }

       public void append(byte b) throwsIOException {

                makeSpace(1);

                if (limit > 0 && end>= limit) {

                         flushBuffer();

                }

                buff[end++]= b;

       }

       public void flushBuffer() throwsIOException {

                out.realWriteBytes(buff, start,end - start);

                end = start;

       }

       private void makeSpace(int count) {

                byte[] tmp = null;

                int newSize= buff.length * 2;

                if (limit > 0 &&newSize > limit) {

                         newSize = limit;

                }

                tmp = new byte[newSize];

                System.arraycopy(buff, start,tmp, 0, end - start);

                buff = tmp;

                tmp = null;

                end = end - start;

                start = 0;

       }

}

②   输出测试类OutputBuffer,此类使用字节块提供的缓冲机制对d盘的hello.txt文件进行写入操作,为更好说明缓冲区工作原理,把字节块的缓冲区初始大小设为3最大为7,我们要把八个字节码写到hello.txt文件,主要看加粗的三行代码,执行dowrite方法时因为长度为8,已经超过了缓冲区最大值,所以进行了一次真实写入操作,接着让程序睡眠十秒,期间你打开hello.txt文件只能看到7个字节数组,它们为1到7(使用十六进制打开)。十秒过后,由于执行了flush刷新操作才把剩下的一个字节写入文件。

public class OutputBuffer implements ByteChunk.ByteOutputChannel{

 

       private ByteChunk fileBuffer;

       FileOutputStream fileOutputStream;

 

       public OutputBuffer() {

                fileBuffer = new ByteChunk();

                fileBuffer.setByteOutputChannel(this);

                fileBuffer.allocate(3, 7);

                try {

                         fileOutputStream = newFileOutputStream("d:\\hello.txt");

                } catch (FileNotFoundExceptione) {

                         e.printStackTrace();

                }

       }

       public void realWriteBytes(byte cbuf[],int off, int len)

                         throws IOException {

                fileOutputStream.write(cbuf,off, len);

       }

       public void flush() throws IOException {

                fileBuffer.flushBuffer();

       }

       public int dowrite(byte[] bytes) throwsIOException {

                for (int i = 0; i <bytes.length; i++)

                         fileBuffer.append(bytes[i]);

                return bytes.length;

       }

       public static void main(String[] args)throws InterruptedException {

                OutputBuffer outputBuffer = newOutputBuffer();

                byte[] bytes = { 1, 2, 3, 4, 5,6, 7, 8 };

                try {

                         outputBuffer.dowrite(bytes);

                         Thread.currentThread().sleep(10*1000);

                         outputBuffer.flush();

                } catch (IOException e) {

                         e.printStackTrace();

                }

       }

}

 

字节块是一个很有用的工具类,它提供了缓冲工具方便我们对某些流添加缓冲区,类似的工具还有字符块CharChunk,顾名思义它是专门用为字符类型的数据提供缓冲操作。


点击订购作者《Tomcat内核设计剖析》




目录
相关文章
|
24天前
|
存储 C语言
用二进制方式向文本读写数据
用二进制方式向文本读写数据
13 3
|
8月前
字节输出流
字节输出流
56 0
|
8月前
字节输入流
字节输入流
43 0
|
8月前
|
网络架构
为什么udp流设置1316字节
为什么udp流设置1316字节
51 0
|
6月前
|
自然语言处理
转换流,字节字符的转换
转换流,字节字符的转换
|
算法 Java
字符串缓冲区
字符串缓冲区
98 1
内置了一个缓冲区(数组)缓冲流BufferInputStream为何要配合字节数组的使用?
内置了一个缓冲区(数组)缓冲流BufferInputStream为何要配合字节数组的使用?
166 0
|
存储 Java Maven
如何判断一个对象占用多少字节?
如何判断一个对象占用多少字节?
149 0
如何判断一个对象占用多少字节?
|
存储
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(一)
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(一)
168 0
|
机器学习/深度学习 索引
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(二)
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(二)
101 0
【Netty】NIO 缓冲区 ( Buffer ) ( 缓冲区读写类型 | 只读缓冲区 | 映射字节缓冲区 )(二)