给你的流添加缓冲装置——字节块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,顾名思义它是专门用为字符类型的数据提供缓冲操作。
喜欢研究java的同学可以交个朋友,下面是本人的微信号:
给你的流添加缓冲装置——字节块ByteChunk的更多相关文章
- xcode添加快捷代码块
添加快捷代码块 在开发过程中,一些常用的代码段,我们可以设置成快捷代码段来快速实现代码的编写. 如上图中的属性的设置,它们都有相同重复的代码@property (nonatomic, strong), ...
- Eclipse用法和技巧九:自动添加try/catch块2
上一篇介绍了如何给未检查异常快速增加try/catch语句,这里在补充一点其他相关操作.有时候我们增加了try/catch之后还需要在加一个finally块,比如android上每次分配一个curso ...
- Eclipse用法和技巧八:自动添加try/catch块1
站在编译器的角度来看,java中的异常可以分为两种,已检查异常和未检查异常.对于已检查异常比如IO操作,编译器会要求设置try/catch语句块,在eclipse中也只要使用帮助快捷键ctrl+1,就 ...
- iOS - UICollectionView 瀑布流 添加表头视图的坑
UICollectionView 瀑布流 添加表头视图的坑 首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不一样,TableView的表头只要设置tab ...
- Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream)
Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在我们学习字 ...
- 36 异常机制 自定义异常 实际应用中的经验总结 尽量添加finally语句块去释放占用的资源
自定义异常 概念 使用Java内置的异常可以描述在编辑时出现的大部分异常情况.除此之外,用户还可以自定义异常.用户自定义异常类,只需继承Exception类即可. 在程序中使用自定义异常类,大体可分为 ...
- Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)
一.字节数组流: 类 ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数组. 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.内部计数器跟踪 read ...
- 内存流和null字节
#include <stdio.h> #include <string.h> int main() { ]={}; FILE* fp = fmemopen(buf,," ...
- UIView添加支持代码块的手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(a ...
随机推荐
- vsftpd详解(ubuntu)
安装 apt-get instll vsftpd 配置vsftp vim vsftpd.conf listen=YES listen_port= anonymous_enable=NO local_e ...
- Eclipse插件安装4种方法
第一种:直接复制法 假设Eclipse的安装目录在C:\eclipse,解压下载的eclipse 插件或者安装eclipse 插件到指定目录AA(如:c:\AA)文件夹,打开AA 文件夹,在AA文件夹 ...
- 浅谈 Axios 在 Vue 项目中的使用
介绍 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 特性 它主要有如下特性: 浏览器端发起XMLHttpRequests请求 Node端发起http ...
- Oracle知识梳理(一)理论篇:基本概念和术语整理
理论篇:基本概念和术语整理 一.关系数据库 关系数据库是目前应用最为广泛的数据库系统,它采用关系数据模型作为数据的组织方式,关系数据模型由关系的数据结构,关系的操作集合和关系的完整 ...
- Spring Boot消息队列应用实践
消息队列是大型复杂系统解耦利器.本文根据应用广泛的消息队列RabbitMQ,介绍Spring Boot应用程序中队列中间件的开发和应用. 一.RabbitMQ基础 1.RabbitMQ简介 Rabbi ...
- PHP 安全 E-mail
PHP E-mail 注入 首先,请看上一章中的 PHP 代码: <html> <body> <?php if (isset($_REQUEST['email'])) / ...
- PHP While 循环
PHP 循环 - While 循环 循环执行代码块指定的次数,或者当指定的条件为真时循环执行代码块. PHP 循环 在您编写代码时,您经常需要让相同的代码块一次又一次地重复运行.我们可以在代码中使用循 ...
- J-Link固件烧录以及使用J-Flash向arm硬件板下载固件程序
这篇文章的最初版本是在15年写的https://blog.csdn.net/u010592722/article/details/45575663,后来又遇到了一些新问题,故更新在了这里. 一.始于安 ...
- Android简易实战教程--第五十话《动画扫描》
祝新年快乐!2017(一起)前行. 转载博客请注明出处:道龙的博客 本篇简答的小案例,使用动画知识,完成一个类似雷达扫描效果,并且加入自定义进度条.对于自定义进度条前面有很详细的解析和案例了,本篇就结 ...
- Bootstrap3 排版-内联文本元素
标记文本 突出显示的文本由于其相关性在另一个上下文中,使用<mark>标记. You can use the mark tag to highlight text. You can use ...