给你的流添加缓冲装置——字节块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内核设计剖析》

时间: 2024-10-27 03:32:09

给你的流添加缓冲装置——字节块ByteChunk的相关文章

嵌入式 hi3518平台多路码流添加osd

[html] view plain copy     <span style="font-family:Courier New;">      /******************************************************************************   function : overlay process   1) create some overlay regions   2) display overlay regi

75篇关于Tomcat源码和机制的文章

整理下前面写过的75篇关于Tomcat源码和机制的文章 文章列表 如何设计一个Web容器 Web安全认证机制知多少 Tomcat集群实现源码级别剖析 Tomcat集群如何同步会话 从单机到集群会话的管理之集群模式一 从单机到集群会话的管理之集群模式二(更大的集群) Tomcat集群的failover机制 Tomcat集群应用部署的实现机制 Tomcat集群机制剖析及其生产部署选型 Tomcat如何实现WebSocket Tomcat如何实现Comet Tomcat怎么实现异步Servlet To

C#存取SQL Server数据库之一:二进制存取图片文件

创建项目 1.      添加一个名为RWTest的表到 SQL Server MYTest 数据库. 表字段设置如下:  a.      唯一标识字段名称为"ID",类型为Int.  b.       名称为"Description"的VarChar类型的字段,字段长度为50.  c.      名称为"ImgField" 的Image 类型的字段. 2.      启动 Visual Studio .NET, 并创建一个新的 Visual C

C#中文件和byte[]互换问题

    如何将图片和声音转化成byte[],并通过webservice进行传输?    如何将webservice传输过来的byte[],转化成我们想要的文件?    (一)文件转化为byte[]    方法一:使用MemoryStream(MemoryStream的数据来自内存中缓冲区)    System.IO.MemoryStream m = new System.IO.MemoryStream();    System.Drawing.Bitmap bp = new System.Dra

用C#实现文件分割合并器

文件分割器主要是为了解决实际生活中携带大文件的问题,由于存储介质容量的限制,大的文件往往不能够一下子拷贝到存储介质中,这只能通过分割程序把的文件分割多个可携带小文件,分步拷贝这些小文件,从而实现携带大文件的目的.而合并器的作用则能够把这些分割的小文件重新合并,恢复原来的文件..Net FrameWork SDK中提供的许多处理文件的类库,通过这些类能够简捷.灵活的实现对文件的操作.本文的主要内容就是探讨一下Visual C#在对文件编程中的一个比较流行的应用--文件分割器和合并器.下面就首先了解

buffer-大家帮帮忙!我这个上传文件的方法为什么会限制文件的大小啊?文件超过一定的大小,上传就失败了!

问题描述 大家帮帮忙!我这个上传文件的方法为什么会限制文件的大小啊?文件超过一定的大小,上传就失败了! private void PostFile(string filename) { FileStream stream = new FileInfo(filename).OpenRead(); var shortfilename = Path.GetFileName(filename); HttpWebRequest request = (HttpWebRequest)HttpWebReques

java学习笔记16--I/O流和文件

IO(Input  Output)流 IO流用来处理设备之间的数据传输,对数据的操作是通过流的方式,Java用于操作流的对象都在IO包中 输入/输出流可以从以下几个方面进行分类 从流的方向划分: 输入流.输出流 从流的分工划分: 节点流.处理流 从流的内容划分: 面向字符的流.面向字节的流 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象.本质其实就是基于字节流读取时,去查了指定的码表. 字节流和字符流的区别: 读写单位不同:字节流以字节(8bit)为单位,字

Node.js数据流Stream之Readable流和Writable流

一.前传 Stream在很多语言都会有,当然Node.js也不例外.数据流是可读.可写.或即可读又可写的内存结构.Node.js中主要包括Readable.Writable.Duplex(双工)和Transform(变换)流.但是在学这些之前先学会util模块中的一个从其他对象继承的功能. util模块提供了util.inherits()方法来允许你创建一个继承另一个对象的prototype(原形)方法的对象.当创建一个新对象时,prototype方法自动被使用. util.inherits(c

H264码流打包分析(精华)

H264码流打包分析 SODB 数据比特串-->最原始的编码数据 RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit"1")若干比特"0",以便字节对齐. EBSP 扩展字节序列载荷-- >在RBSP基础上填加了仿校验字节(0X03)它的原因是: 在NALU加到Annexb上时,需要填加每组NALU之前的开始码 StartCodePrefix,如果该NALU对应的slice为一帧的开始则