这是一个很重要的一个字节数组处理缓冲工具,它封装了字节缓冲器及对字节缓冲区的操作,包括对缓冲区的写入、读取、扩展缓冲区大小等等,另外还提供相应字符编码的转码操作。此工具让缓冲操作变得更加方便,除了缓冲区他还有两个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,顾名思义它是专门用为字符类型的数据提供缓冲操作。

喜欢研究java的同学可以交个朋友,下面是本人的微信号:

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

  1. xcode添加快捷代码块

    添加快捷代码块 在开发过程中,一些常用的代码段,我们可以设置成快捷代码段来快速实现代码的编写. 如上图中的属性的设置,它们都有相同重复的代码@property (nonatomic, strong), ...

  2. Eclipse用法和技巧九:自动添加try/catch块2

    上一篇介绍了如何给未检查异常快速增加try/catch语句,这里在补充一点其他相关操作.有时候我们增加了try/catch之后还需要在加一个finally块,比如android上每次分配一个curso ...

  3. Eclipse用法和技巧八:自动添加try/catch块1

    站在编译器的角度来看,java中的异常可以分为两种,已检查异常和未检查异常.对于已检查异常比如IO操作,编译器会要求设置try/catch语句块,在eclipse中也只要使用帮助快捷键ctrl+1,就 ...

  4. iOS - UICollectionView 瀑布流 添加表头视图的坑

    UICollectionView 瀑布流 添加表头视图的坑 首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不一样,TableView的表头只要设置tab ...

  5. Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream)

    Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在我们学习字 ...

  6. 36 异常机制 自定义异常 实际应用中的经验总结 尽量添加finally语句块去释放占用的资源

    自定义异常 概念 使用Java内置的异常可以描述在编辑时出现的大部分异常情况.除此之外,用户还可以自定义异常.用户自定义异常类,只需继承Exception类即可. 在程序中使用自定义异常类,大体可分为 ...

  7. Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)

    一.字节数组流: 类 ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数组. 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.内部计数器跟踪 read ...

  8. 内存流和null字节

    #include <stdio.h> #include <string.h> int main() { ]={}; FILE* fp = fmemopen(buf,," ...

  9. UIView添加支持代码块的手势

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(a ...

随机推荐

  1. select动态绑定vue.js

    <select v-model="selected"> <option v-for="option in options" v-bind:va ...

  2. css3部分整理

    1.css弹性盒子属性 父级元素属性的设置 #father{ width: 800px; height: 300px; background-color: darkgray; /*定义父级元素为弹性元 ...

  3. setuptools安装和错误解决

    错误解决:ImportError No module named setuptools GitHub: https://github.com/pypa/setuptools 下载安装 wget htt ...

  4. struts框架从.jsp页面直接访问action

    <%@ page language="java" pageEncoding="UTF-8"%><%String path = request. ...

  5. 读书学习-Python--描述符(python3)

    转自我的知乎文章(https://zhuanlan.zhihu.com/p/32487852) 何为描述符?描述符就是实现了__get__.__set__和__delete__三者中任意一个的类.是用 ...

  6. ubuntu 下查看caj文件

    知网的学位论文只有CAJ版,而我又偏偏使用Ubuntu,所以就有了这篇文章. 前端时间发现第一种方法在ubuntu 16 上不行, 请使用第二种方法. 第一种方法: 环境:Ubuntu 14.04 6 ...

  7. Swift 3.0项目迁移的一些记录

    刚执行完Convert后报错600+,真是令人奔溃. 之后重新编译,仔细分析后发现其实真实错误远没有那么多.最终实际修改到的错误也就几十个,而且其中某些还是同一种错误. 这个项目是一个供自己使用的浏览 ...

  8. popen() 使用举例 (转载)

    函数原型: #include "stdio.h" FILE *popen( const char* command, const char* mode ) 参数说明: comman ...

  9. Winform DevExpress控件库(三) 使用NavBarControl控件定制导航栏

    NavBarControl控件:主要作用是制作包含多个选项组并且每个组里包含多个子选项的导航栏: 位于 工具箱 -> Navigation & Layout(导航栏与布局类控件) 目录下 ...

  10. Android------Android.mk调用shell脚本

    $(info $(shell ($(LOCAL_PATH)/echo_test.sh)))