关于IO包装流中的两个read方法
2014-01-30 19:07
148 查看
刚开始学IO流,会经常感到奇怪,为什么read方法返回的都是int类型,而且,在包装流中经常会弄混淆,看了传智播客老师的视频,加上API文档的了解,总算是完全弄懂了。
下面贴出四个包装流的代码,分别包装了inputstream、outputstream、reader、writer:
public class MyBufferedInputStream extends InputStream {
private InputStream in;
private byte[] buf = new byte[1024]; //自定义字节数组作为缓冲区
private int len = 0; //定义一个变量,用于记住缓冲区可用字节数量
private int pos = 0; //定义一个变量,用于记住缓冲区当前可用字节的角标
//通过构造函数组合被包装的流
public MyBufferedInputStream(InputStream in) {
this.in = in;
}
@Override
public int read() throws IOException {
//判断缓冲区是否还有可用字节
if(len==0) {
//一次性填充缓冲区
len = in.read(buf);
//pos要置零
pos = 0;
}
//判断是否到了流的末尾
if(len==-1) {
return -1;
}
//返回一个字节,可用字节就少一个,所以len到减1
len--;
//返回当前可用字节,升级为int,前面加24个0
//11111111 & 00000000 00000000 00000000 11111111 0xff
return buf[pos++]&0xff;
}
public void close() throws IOException {
//关闭底层被包装的流
in.close();
}
}
所有这些包装流中,无参的read()方法,返回的int都是字符或字节的ASCII码,参数为数组的read(buf)返回的int是数组中的字符或字节个数,用来确定读取到的字符或字节在数组中的位置,两个read方法返回-1时都代表到了流的末尾。
下面贴出四个包装流的代码,分别包装了inputstream、outputstream、reader、writer:
public class MyBufferedInputStream extends InputStream {
private InputStream in;
private byte[] buf = new byte[1024]; //自定义字节数组作为缓冲区
private int len = 0; //定义一个变量,用于记住缓冲区可用字节数量
private int pos = 0; //定义一个变量,用于记住缓冲区当前可用字节的角标
//通过构造函数组合被包装的流
public MyBufferedInputStream(InputStream in) {
this.in = in;
}
@Override
public int read() throws IOException {
//判断缓冲区是否还有可用字节
if(len==0) {
//一次性填充缓冲区
len = in.read(buf);
//pos要置零
pos = 0;
}
//判断是否到了流的末尾
if(len==-1) {
return -1;
}
//返回一个字节,可用字节就少一个,所以len到减1
len--;
//返回当前可用字节,升级为int,前面加24个0
//11111111 & 00000000 00000000 00000000 11111111 0xff
return buf[pos++]&0xff;
}
public void close() throws IOException {
//关闭底层被包装的流
in.close();
}
}
public class MyBufferedOutputStream extends OutputStream { private OutputStream out; private byte[] buf = new byte[1024]; //自定义缓冲区 private int pos = 0; //定义一个变量,记住当前缓冲区可存储的位置 //组合被包装的流 public MyBufferedOutputStream(OutputStream out) { this.out = out; } @Override public void write(int b) throws IOException { //判断缓冲区是否已满 if(pos==1024) { //刷新缓冲区 flush(); //pos置零 pos = 0; } //将当前字节存入缓冲区对应的空位 buf[pos++] = (byte) b; } public void flush() throws IOException { //将缓冲区有用的字节写入底层流 out.write(buf, 0, pos); } public void close() throws IOException { //刷心缓冲区 flush(); //关闭底层的流 out.close(); } }
public class MyBufferedReader extends Reader { private Reader r; private char[] buf = new char[1024]; private int pos; private int len; public MyBufferedReader(Reader r) { this.r = r; } /* 实现read方法,实现缓冲的功能 * 分析: * 1.当别人第一次调用次方法时,一次性填充缓冲区 * 2.定义一个变量len记住缓冲区的可用字符数量 * 3.定义一个变量pos用于记住当前可用字符的角标 * 3.将数组的第一个元素返回, * 4.当别人第二次调用时,将数组的第二个元素返回, * 5.每次返回一个元素,len-- * 6.当len为0时,说明数组没有可用字符了,再次填充缓冲区,直到读到-1, * * 思路: * 1.定义两个成员变量,len记住可用字符数量,pos记住当前可用字符的位置 * 2.判断len,如果len为0,填充缓冲区,pos要置零 * 3.判断len,如果为-1,我们也返回-1 * 4.将pos位置的元素返回,pos要++ */ public int read() throws IOException { if(len==0) { len = r.read(buf); pos = 0; } if(len==-1) return -1; len--; return buf[pos++]; } /* 实现readLine方法,实现读一行的功能 * 1.循环调用自己的read方法,读取字符 * 2.直到遇上回车换行,方法结束 */ public String readLine() throws IOException { StringBuilder sb = new StringBuilder(); int ch; while((ch=read())!=-1) { if(ch=='\r') continue; if(ch=='\n') break; sb.append((char)ch); } if(ch==-1&&sb.length()==0) return null; return sb.toString(); } public void close() throws IOException { r.close(); } @Override public int read(char[] buf, int offset, int len) throws IOException { int count = 0; for(int i=offset; i<offset+len; i++) { int ch = read(); if(ch==-1) break; count++; buf[i] = (char) ch; } return count; } }
public class MyBufferedWriter extends Writer { private Writer w; private char[] buf = new char[1024]; private int pos = 0; public MyBufferedWriter(Writer w) { this.w = w; } /* * 定义write方法,实现写入一个字符,实现缓冲的功能 * 1.定义一个变量pos记住当前的写入位置, * 2.每次调用者调用此方法都会传入一个字符,将字符存入缓冲数组的pos位置, * 3.pos++; * 4.每次一上来都要判断,如果pos==1024,刷新缓冲区,pos=0; */ public void write(int ch) throws IOException { if(pos==1024) { flush(); pos = 0; } buf[pos++] = (char) ch; } @Override public void close() throws IOException { flush(); w.close(); } @Override public void flush() throws IOException { // 刷新缓冲区,将当前缓冲区有用字符一次性写入底层被包装的流 w.write(buf, 0, pos); } public void write(String data) throws IOException { char[] chars = data.toCharArray(); for(char c : chars) write(c); } public void newLine() throws IOException { write("\r\n"); } @Override public void write(char[] buf, int offset, int len) throws IOException { for(int i=offset; i<offset+len; i++) write(buf[i]); } }
所有这些包装流中,无参的read()方法,返回的int都是字符或字节的ASCII码,参数为数组的read(buf)返回的int是数组中的字符或字节个数,用来确定读取到的字符或字节在数组中的位置,两个read方法返回-1时都代表到了流的末尾。
相关文章推荐
- [置顶] Unity中关于场景漫游的两个方法(一)
- io学习之read(char[])方法的使用
- 关于百度富文本编辑器ueditor的.NET版本地图片上传提示uploader类同时存在于两个dll中的解决方法
- 关于VC++6.0时点打开文件时总弹出“ox5003eaed”指令引用的“ox00000000”内存。该内存不能为“read”的解决方法 .
- 关于java中BufferedReader的read()及readLine()方法的使用心得
- 关于Java中Scanner对象的hasNext()方法对实现Readable接口的对象中的read()方法调用的探讨
- python关于列表转为字典的两个小方法
- 关于servlet的两个init()方法
- 关于tomcat下java.io.NotSerializableException异常的解决方法
- Java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值
- 关于StreamReader.ReadToEnd方法
- 关于装完系统出现a disk read error occurred的解决方法
- io学习之read(char[])方法的使用
- python两个关于计算方法运行时间的修饰器
- Java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值(科普一下吧,某个大侠写的)
- 关于Socket IO模式下 read堵塞问题
- 关于两个时间(00:00:00)相加的实现方法
- java IO 管道流 关于两个线程通信的问题
- 关于object类的两个重要方法以及为什么重写equals一定要重写hashcode()
- java 编程下 IO 中的输入流的 read() 方法返回值为什么是 int 值