输入流
概述
InputStream是字节输入流的根类,Reader是字符输入流的根类。我们所说的输入输出都是相对Java程序而言的,所以输入是把外存中的数据读取到内存中。而分成两个根类的原因是在流的基本单位是字节,但是Java字符使用UTF-16编码,在UTF-16编码中,绝大部分字符是双字节的,所以单独划分一个类别来表示字符输入流。
InputStream
概述
InputStream是字节输入流,常用的直接实现类有ByteArrayInputStream和FileInputStream,前者是把某byte数组指定为数据源,后者是把文件作为数据源。
API
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class Test {
public String test;
public static void main(String[] args) throws Exception {
byte []bs = new byte[100];
for(int i = 0; i < 100; i++)
bs[i] = (byte)i;
//以字节数组为数据源
InputStream isb = new ByteArrayInputStream(bs);
//以文件为数据源
InputStream isf = new FileInputStream("E:\\video\\10 IO流-基础\\视频\\avi\\10.01_IO流的概述和分类.avi");
/**
* 两个的演示API相同,但是字节数组更直观,所以使用字节数组作为数据源演示
*/
/**
* 读取当前数据源的下一个字节数据并返回:
* Console:
* 0
* 1
*/
System.out.println(isb.read());
System.out.println(isb.read());
/**
* 跳过指定字节的数据
* Console:
* 4
*/
isb.skip(2);
System.out.println(isb.read());
/**
* 还可以读取的字节数
* Console:
* 95
*/
System.out.println(isb.available());
/**
* 尽可能把数据读入temps中,即如果数据字节数大于数组容量,数组会被读满,
* 小于数据源数据会全部读进去, 返回真正读取的字节数
* Console:
* 5 6 7 8 9 10 11 12 13 14
* 10
*/
byte []temps = new byte[10];
int read = isb.read(temps);
for(byte e : temps)
System.out.print(e + " ");
System.out.println("\n" + read);
/**
* read(byte[] b, int off, int len)
* 从off位置开始开始读入len个字节的数据到b中,返回真正读取的字节数
* Console:
* 5 6 7 8 9 10 11 12 13 14
* 10
*/
int read2 = isb.read(temps, 3, 2);
for(byte e : temps)
System.out.print(e + " ");
System.out.println("\n" + read2);
/**
* mark(int readlimit) & reset()
* 再调用reset()之后,会返回最近的一次被mark的位置,
* 传入的参数:readLimit是说系统会保证在readLimit
* 个字节之内不会使mark失效,超过这个字节之后就不再保证了
* Console:
* 17
*/
isb.mark(isb.available());
isb.read();
isb.reset();
System.out.println(isb.read());
/**
* 查看当前流是否支持mark和reset。
* Console:
* true
*/
System.out.println(isb.markSupported());
/**
* 关闭此流并且释放系统资源
*/
isb.close();
}
}
FilterInputStream
这个类直译是过滤输入流,但是在Java中过滤的目的是为了增强某些功能,所以我更喜欢叫他增强输入流。虽然它不是抽象类,但是它却不能直接使用,因为它所有的属性和方法都是protected的,它有一个常用的实现类:BufferedInputStream。这个类的增强的功能就是采用开辟缓存区的方式使输入流读取数据能更快。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class Test2 {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("E:\\video\\10 IO流-基础\\视频\\avi\\10.01_IO流的概述和分类.avi");
long begin1 = System.currentTimeMillis();
while(is.read() != -1) {}
long end1 = System.currentTimeMillis();
System.out.println(end1 - begin1);
InputStream bis = new BufferedInputStream(new FileInputStream("E:\\video\\10 IO流-基础\\视频\\avi\\10.01_IO流的概述和分类.avi"));
long begin2= System.currentTimeMillis();
while(bis.read() != -1) {}
long end2 = System.currentTimeMillis();
System.out.println(end2 - begin2);
/**
* Console:
* 23175
* 53
*/
is.close();
bis.close();
}
}
Reader()
概述
这个类是处理字符文件的根类。它的常用实现类有FileReader和CharArrayReader。同样的,如果要加快读取速度,使用带缓冲区的BufferedReader类。
import java.io.CharArrayReader;
import java.io.FileReader;
import java.io.Reader;
public class Test2 {
public static void main(String[] args) throws Exception {
char []strs = new char[26];
for(int i = 0; i < 26; i++)
strs[i] = (char)(i + 97);
//以文件作为数据源
Reader fr = new FileReader("D:\\a.txt");
//以字符数组作为数据源
Reader car = new CharArrayReader(strs);
/**
* 为了方便,数据源使用字符数组
*/
/**
* 读取单个字符,并返回相应的int值
* Console:
* a
*/
int read = car.read();
System.out.println((char)read);
/**
* 尽可能读取到字符数组,并返回真实读取的字符数。如果数组容量小于数据源字符个数
* 数组会被全部读满,否则读至数据源结尾。
* Console:
* b c d e f g h i j k
* 10
*/
char []temps = new char[10];
int read2 = car.read(temps);
for(char e : temps)
System.out.print(e + " ");
System.out.println("\n" + read2);
/**
* read(char[] cbuf, int off, int len)
* 从字符数组的off位置开始,读入长度为len的数据进入,返回真正读取的字符数、
* Console:
* b c d l m g h i j k
* 2
*/
int read3 = car.read(temps, 3, 2);
for(char e : temps)
System.out.print(e + " ");
System.out.println("\n" + read3);
/**
* skip(long n)
* mark(int readAheadLimit)
* reset()
* markSupported()
*
* 和InputStream一致
*/
}
}
InputStreamReader
InputStreamReader是 a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset。它有且只有FileReader这个子类,所以FileReader实现从文件中读取的方法是从把文件按字节读入后按照指定编码规则进行解码,默认是平台解码集。