给你的流添加缓冲装置——字节块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 ...
随机推荐
- 字符串的最长回文串:Manacher’s Algorithm
题目链接:Longest Palindromic Substring 1. 问题描述 Given a string S, find the longest palindromic substring ...
- jenkins更新后出现JNLP-connect,JNLP2-connect警告
在更新jenkins后出现提示 This Jenkins instance uses deprecated protocols: JNLP-connect,JNLP2-connect. It may ...
- Jvm原理剖析与调优之内存结构
一些不得不说的概念 JVM JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机包括一套字节码指令集.一组寄存器.一个栈.一个 ...
- js中一个对象当做参数传递时候?
高程中讲到:'ECMAScript 中所有函数的参数都是按值传递'. 这就像把值从一个变量复制到另一个变量一样. 那引用类型的值也是像基本类型一样? 直接看栗子一: var person = { na ...
- 重写轮子之 kNN
# !/usr/bin/python # -*- coding:utf-8 -*- """ Re-implement kNN algorithm as a practic ...
- 关于Node.js中HTTP请求返回数据需要JSON解析的问题
在编写项目过程中,需要用到实时数据的推送需求, 所以首先想到了NodeJS的websocket模块 在网上找了一个聊天室的例子 然后将其改为自己需求的推送 其中遇到的问题 返回数据问题 : 由 ...
- 从头开始搭建一个VSCode+NetCore的项目
看这个前,先要对VS开发C#有所了解 获取作案工具 NetCore SDK https://www.microsoft.com/net/learn/get-started/windows 安装 建立工 ...
- windows资源管理器中配置右键bash here
windows下安装了git后有git bash here 但是安装了cygwin没有bash here 我们可以通过修改注册表的方式自己做一个 Win10下在注册表内有一般有两个默认的 cmd 和 ...
- PHP MySQL 创建数据表
PHP 创建 MySQL 表 一个数据表有一个唯一名称,并有行和列组成. 使用 MySQLi 和 PDO 创建 MySQL 表 CREATE TABLE 语句用于创建 MySQL 表. 我们将创建一个 ...
- DISC社交风格测试题--老虎 孔雀 考拉 猫头鹰
凭直觉,迅速回答 "我是谁",而不是"我应该是谁,或我想我是谁". 1.关于人生观,我的内心其实是: A 希望能够有尽量多的人生体验,所以会有非常多样化的想法. ...