字节流
介绍一下所有字节流的父类,也就是在装饰模式中扮演“武器”这个角色的类。所有输入字节流的父类是InputStream,所有输出字节流的父类是OutputStream。
FileInputStream/FileOutputStream
1. int read() :这个方法每次都从文件中读取一个字节,并且把读到的内容返回。这个字节作为int四个字节中的最低位返回。而当读到流末尾时,返回-1。
示例:
FileInputStream fin = new FileInputStream("abc.txt");
System.out.println(fin.read());
System.out.println(fin.read());
System.out.println(fin.read());
System.out.println(fin.read());
fin.close();
FileInputStream fin = new FileInputStream("abc.txt");
int ch = 0;
while( (ch=fin.read()) != -1){
System.out.print((char)ch);
}
fin.close();
2. int read(byte[] bs):每次调用这个方法的时候,会把读取到的数据放入bs数组中,一次调用尽量读取bs.length个字节。而对于流中剩下的字节数少于bs.length的情况,read方法返回的就是实际读到的字节数。特别要注意的是,当读到流末尾时,返回-1。
示例:
FileInputStream fin = new FileInputStream("abc.txt");
byte[] bs = new byte[6];
int len = 0;
while( (len=fin.read(bs))!=-1){
for(int i = 0; I < len; i++){
System.out.print((char)bs[i]);
}
System.out.println();
}
fin.close();
3. void write(int v) : 这个write方法每次调用时写入一个字节。注意,虽然这个write方法
接受的参数类型是int 类型,虽然int 类型有4个字节,但是这个write方法每次只写入int
类型中最后的那个字节。
4. void write(byte[] bs) : 写入一个byte数组。
示例:
String hello = "Hello World";
byte[] bs = hello.getBytes();
FileOutputStream fout= new FileOutputStream("test.txt");
fout.write(bs);
fout.close();
过滤流
DataInputStream/DataOutputStream
1. 读八种类型:
DataOutputStream的方法:除了有OutputStream中有的几个write方法之外,还有writeBoolean, writeByte, writeShort ... 等一系列方法,这些方法接受某一种基本类型,把基本类型写入到流中。 需要注意的是,有一个writeInt(int n)方法,这个方法接受一个int 类型的参数。这个方
法和write(int v)方法不同。writeInt方法是DataOutputStream特有的方法,这个方法一次写入参数n的四个字节。而write方法则一次写入参数v的最后一个字节。
2. 与之对应的,DataInputStream的方法中,除了有几个read 方法之外,还有readBoolean,readByte,readInt 等一系列方法,这些方法能够读入若干个字节,然后拼成所需要的数据。例如readDouble方法,就会一次读入8个字节,然后把这8个字节拼接成一个double类型。
3. 最后要提示的是,DataXXXStream中有readUTF和writeUTF这两个方法用来读写字符串,但是一般来说,我们读写字符串的时候几乎不使用Data流。Data流主要是用在8种基本类型的读写上。
示例:
FileOutputStream fout = new FileOutputStream("pi.dat");
DataOutputStream dout = new DataOutputStream(fout);
dout.writeDouble(3.14);
dout.close();
FileInputStream fin= new FileInputStream ("pi.dat");
DataInputStream din = new DataInputStream(fin);
double pi = din.readDouble();
din.close();
BufferedInputStream/BufferedOutputStream
1. 增强了缓冲区的功能(没有读写八种基本类型的功能)
示例:
String data = "Hello World";
byte[] bs = data.getBytes();
FileOutputStream fout= new FileOutputStream("test.txt");
BufferedOutputStream bout = new BufferedOutputStream(fout);
bout.write(bs);
bout.close();
2. 需要注意的是,如果把bout.close()方法去掉,此时在看test.txt 文件,会发现文件的内容为空。这是因为,我们在调用write方法的时候,其实并没有真正把数据写入到文件中,而只是把数据写入到缓冲区中。那什么时候缓冲区中的数据会真正写入到文件中呢?有三种情况:第一种情况是缓冲区已满,第二种情况是调用close方法。 除了这两种情况之外,假设程序员希望在缓冲区没有满并且不关闭流的情况下,把缓冲区内的东西真正写入流中,应当调用一个方法:flush()。
ObjectInputStream/ObjectOutputStream(对象序列化)
1. 这两个也是过滤流,增强的功能如下:
(1)增强了缓冲区功能
(2)增强了读写八种基本类型和字符串的功能。读写基本类型和字符串的方式,与Data流完全一样。
(3)增强了读写对象的功能。这是这两个流最主要的作用。在ObjectInputStream类有一
个readObject 方法,这个方法能够从流中读取一个对象;而ObjectOutputStream类中有一个
writeObject方法,这个方法能够向流中写入一个对象。
PrintStream
1. PrintStream是一个比较特殊的过滤流,我们简单介绍一下,读者作为一般性的了解即可。
PrintStream作为过滤流,增强的功能有以下几个:
(1)缓冲区的功能
(2)写八种基本类型和字符串
(3)写对象
2. 需要注意的是,这个流写基本类型和写对象的时候,是按照字符串的方式写的。也就是说,这个流写八种基本类型的时候,会把基本类型转换成字符串以后再写,而写对象的时候,会写入对象的toString()方法返回值。我们所熟知的向屏幕输出数据的对象:System.out对象,这就是一个PrintStream类型的对象。
字符流
首先是字符流的父类。所有输入字符流的父类是Reader,所有输出字符流的父类是Writer。与InputStream和OutputStream类似,这两个类也是抽象类。
java.io.FileReader
FileReader/FileWriter
此外,与FileInputStream以及FileOutputStream类似,有两个类FileReader和FileWriter,这两个类分别表示文件输入字符流和文件输出字符流。这两个流的使用与FileInputStream以及FileOutputStream也非常雷同,在此不多介绍,需要注意的是,使用这两个流的时候,无法指定编解码方式。通过FileReader和FileWriter可以直接获得文件字符流。
示例:
FileWriter fw = new FileWriter("1.txt");
char[] cs={'b','c','d'};
//fw.write('a');
fw.write(cs);
fw.close();
InputStreamReader /OutputStreamWriter
1. 这个流所有构造方法,都可以接受一个InputStream(FileInputStream)类型的参数。也就是说,通过这个流,可以接受一个字节流作为参数,创建一个字符流。这个对象就起到了字节流向字符流转换的功能,我们往往称之为:桥转换。在桥转换的过程中,我们还可以指定编解码方式。如果不指定的话,则编码方式采用系统默认的编码方式。
2. 通过桥转换获得字符流,也是一个获得字符流的方式。这种方式有两个用法:
(1)如果需要指定编码方式,则应当使用桥转换。
(2)在无法直接获得字符流的情况下,可以先获得字节流,再通过桥转换获得字符流。
3. 利用桥转换进行编程,需要以下五个步骤:
(1)创建节点流
(2)桥转换为字符流
(3)在字符流的基础上封装过滤流
(4)读/写数据
(5)关闭外层流
字符过滤流
BufferedReader/PrintWriter
1. BufferedReader提供了缓冲区功能。但是更重要的是,BufferedReader中有一个readLine()方法,签名如下:
public String readLine()
这个方法也很容易理解:每次读入一行文本,并把读入的这一行文本当做返回值返回。当读到流末尾时,返回一个null值。对于Windows来说,默认的编码为GBK。
示例(没有使用桥转换):
//创建节点流
FileReader fr = new FileReader("D:/CoreJava/a.txt");
//包装过滤流
BufferedReader in = new BufferedReader(fr);
//读写数据
while(true){
String s = in.readLine();//从文件中读取一行字符串
if(s==null)break;
System.out.println(s);
}
//关闭连接
in.close();
示例(使用桥转换):
//创建节点流
FileInputStream fin = new FileInputStream("poem.txt");
//桥转换
InputStreamReader r = new InputStreamReader(fin, "GBK");
//封装过滤流
BufferedReader br = new BufferedReader(r);
String line = null;
while( (line=br.readLine()) !=null){
System.out.println(line);
}
br.close();
2. PrintWriter是一个很特殊的类。首先,PrintWriter可以作为一个过滤流。这个流可以接受一个Writer作为参数。增强了如下一些功能:
(1)缓冲区的功能。因此使用PrintWriter应当及时关闭或刷新
(2)写八种基本类型和字符串的功能。
(3)写对象的功能。
在PrintWriter类中,有一系列print方法,这些方法能够接受八种基本类型、字符串和对象。同样的,还有一系列println 方法,这些方法在写入数据之后,会在数据后面写入一个换行符。
要注意的是,PrintWriter写基本类型的方式,是把基本类型转换为字符串再写入流中,与Data流不同。举例来说,对于3.14这个double类型的数,Data流会把这个数拆分成8个字节写入文件,而PrintWriter会把这个数字转化为字符串“3.14”,写入文件中。
此外,PrintWriter写对象的时候,写入的是对象的toString()方法返回值,与对象序列化有本质区别。
3. PrintWriter除了可以作为过滤流之外,还可以作为节点流。PrintWriter类的构造方法中,可以直接接受一个文件名或File对象作为参数,直接获得一个输出到文件的PrintWriter。当然,编码方式采用的是系统默认的编码方式。
4. 最后,PrintWriter的构造方法可以接受一个InputStream(FileInputStream),也就是说,可以使用PrintWriter进行桥转换。只不过使用PrintWriter进行桥转换的时候,无法指定编码方式,采用的是系统默认的编码方式。
节点流、过滤流、桥转换
示例(节点流):
PrintWriter pw=new PrintWriter("a.txt");
pw.println("aaaaa");
pw.println("aaaaa");
pw.println("aaaaa");
pw.flush();
pw.close();
示例(过滤流):
FileWriter fw = new FileWriter("2.txt");
PrintWriter out = new PrintWriter(fw);
out.println("葡萄美酒夜光杯");
out.println("欲饮琵琶马上催");
out.println("醉卧沙场君莫笑");
out.println("古来征战几人回");
out.flush();
out.close();
FileOutputStream fout = new FileOutputStream("poem2.txt");
OutputStreamWriter w = new OutputStreamWriter(fout, "GBK");
PrintWriter pw = new PrintWriter(w);
pw.println("一个人在清华园");
pw.println("我写的Java程序");
pw.println("是全天下");
pw.println("最面向对象的");
pw.close();
示例(桥转换):
FileOutputStream fos = new FileOutputStream("test.txt");
PrintWriter out = new PrintWriter(fos);//自带桥转换功能,但是不能编码
out.println("葡萄美酒夜光杯");
out.println("欲饮琵琶马上催");
out.println("醉卧沙场君莫笑");
out.println("古来征战几人回");
out.flush();
out.close();
总结
InputStream/OutputStreamFileInputStream/FileOutputStream
DataInputStream/DataOutputStream
BufferedInputStream/BufferedOutputStream
ObjectInputStream/ObjectOutputStream
PrintStream
Reader/Writer
FileReader/FileWriter
InputStreamReader /OutputStreamWriter(桥转换)
BufferedReader/PrintWriter(过滤流)
八种基本类型、字符串、对象、缓冲
FileInputStream/FileOutputStream 字节
DataInputStream/ DataOutputStream 字节 八种基本类型 字符串
(读写字符串一般不用)
BufferInputStream/ BufferedOutputStream 字节 缓冲
ObjectInputStream/ ObjectOutputStream 八种基本类型 字符串 对象 缓冲
(读写八种基本类型与data的方法相同、读写字符串一般不用)
PrintStream 八种基本类型 字符串 对象 缓冲
(写八种基本类型和对象时要先转化为字符串、和object不同)
FileReader/FileWriter 字符
InputStreamReader /OutputStreamWriter 桥转换(指定编码)
BufferedReader/PrintWriter 缓冲 读入一行文本
PrintWriter 八种基本类型 字符串 写对象 缓冲 节点流、过滤流、桥转换
(写八种基本类型和对象时要先转化为字符串)