流是一种抽象的概念,i/o流中的“i”代表“input”输入,而“o”代表“output”输出。io流可以理解为输入输出的途径。如图:
java中的io流是由四大抽象类组成:InputStream(字节输入流)、OutputStream(字节输出流)、Reader(字符输入流)、Writer(字符输出流)而这四大抽象类又有其相应的多种具体实现类。
java中的io流模型还用到了装饰器模式。如图:
现在就让我来给大家教教这些流如何来使用。
一、文件字节流
首先,文件字节流分为输出输入两类:FileInputStream、FileOutputStream。都是用字节的形式对文件进行字节上的操作。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test01{
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("text.txt");
FileOutputStream fos = new FileOutputStream("text01.txt");){
int len = -1;
byte[] flush = new byte[1024];
while((len = fis.read(flush))!=-1) {
fos.write(flush, 0, len);
/*write和read的参数都是字节或字节数组*/
String str = new String(flush);
System.out.print(str);
}
fos.flush();//完成写入的操作后一定要刷新
}catch(IOException e) {
e.printStackTrace();
}
}
}
二、文件字符流
文件字符流与文件字节流最大的区别在于字节流操作字节或字节数组,而字符流操作字符或字符数组。
即前者read/write方法参数为字节或字节数组,后者read/write方法参数为字符或字符数组。
同样一个字符文件,用字节流可能会导致汉字乱码问题,用字符流则不用担心。
使用字符流完成刚才的代码,只需要将字节流换成字符流,字节数组换成字符数组即可。如下:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test01{
public static void main(String[] args) {
try(FileReader fr = new FileReader("text.txt");
FileWriter fw = new FileWriter("text01.txt");){
int len = -1;
char[] flush = new char[3];
while((len = fr.read(flush))!=-1) {
fw.write(flush, 0, len);
/*write和read的参数都是字符或字符数组*/
String str = new String(flush);
System.out.print(str);
}
fw.flush();//完成写入的操作后一定要刷新
}catch(IOException e) {
e.printStackTrace();
}
}
}
三、字节数组流
字节数组流与刚才介绍的两种流的不同之处在于,他的输入流构造器参数为字节数组,输出流为空构造器。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class Test01{
public static void main(String[] args) {
byte[] b = "Hello World!".getBytes();
try(ByteArrayInputStream bais = new ByteArrayInputStream(b);
ByteArrayOutputStream baos = new ByteArrayOutputStream();){
int len = -1;
byte[] flush = new byte[1024];
while((len=bais.read(flush))!=-1) {
baos.write(flush, 0, len);
}
baos.flush();
System.out.println(baos.toString()+"\n字节数:"+baos.size());
}catch(IOException e) {
e.printStackTrace();
}
}
}
四、缓冲字节流
从缓冲字节流开始,下面介绍的一些流都属于装饰器模式中的具体装饰类。
刚才我们在介绍“一、文件字节流”时用到的代码,就可以用缓冲字节流进行如下的装饰。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test01{
public static void main(String[] args) {
try(BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream("text.txt"));
BufferedOutputStream bos =
new BufferedOutputStream(
new FileOutputStream("text01.txt"));){
int len = -1;
byte[] flush = new byte[1024];
while((len = bis.read(flush))!=-1) {
bos.write(flush, 0, len);
/*write和read的参数都是字节或字节数组*/
String str = new String(flush);
System.out.print(str);
}
bos.flush();//完成写入的操作后一定要刷新
}catch(IOException e) {
e.printStackTrace();
}
}
}
五、字符缓冲流
字节缓冲流与字符缓冲流的区别类似于文件字节流和文件字符流。
即前者操作字节或字节数组,后者操作字符或字符数组。
除此之外字节缓冲流对应的具体组件是文件字节流,而字符缓冲流对应的具体组件是文件字符流。
我们这里用到的例子一样是在“二、文件字符流”的例子的基础上进行的修改。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test01{
public static void main(String[] args) {
try(BufferedReader br =
new BufferedReader(
new FileReader("text.txt"));
BufferedWriter bw =
new BufferedWriter(
new FileWriter("text01.txt"));){
int len = -1;
char[] flush = new char[3];
while((len = br.read(flush))!=-1) {
bw.write(flush, 0, len);
/*write和read的参数都是字符或字符数组*/
String str = new String(flush);
System.out.print(str);
}
bw.flush();//完成写入的操作后一定要刷新
}catch(IOException e) {
e.printStackTrace();
}
}
}
六、数据流
其他几种流中的数据都是字节或字符的形式,而接下来介绍的数据流则是可以选定数据的格式并进行读写操作,无论字符数据,整形数据,字节数组数据,或是数组,都可以利用数据流进行读写操作。
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test01{
public static void main(String[] args) {
try(DataInputStream dis =
new DataInputStream(
new FileInputStream("text.txt"));
DataOutputStream dos =
new DataOutputStream(
new FileOutputStream("text.txt"));){
dos.writeBoolean(false);
dos.writeChar('a');
dos.writeInt(12);
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());
// System.out.println(dis.readChar());
/*第三个数据是整形数据,若将其按照字符型读取,运行时会报错*/
System.out.println(dis.readInt());
// System.out.println(dis.readInt());
/*数据已经读取完了,再读取必然会报错*/
}catch(IOException e) {
e.printStackTrace();
}
}
}
七、对象流
对象流相当于是数据流的升级版,不仅可以读写数据流可以读写的数据类型,还能读写任何实现了反序列化的类。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;
class Person{//Person类没有实现反序列化
String name;
int id;
public Person(String name,int id) {
this.name = name;
this.id = id;
}
}
class Book implements Serializable{//Book类实现了反序列化
String name;
float price;
public Book(String name,float price){
this.name = name;
this.price = price;
}
}
public class Test01{
public static void main(String[] args) {
try(ObjectOutputStream oos=
new ObjectOutputStream(
new BufferedOutputStream(
new FileOutputStream("text.txt")))){
Date date = new Date();
Person person = new Person("spd",123456);
Book book = new Book("java程序基础",38.8f);
oos.writeBoolean(false);
oos.writeChar('a');
oos.writeInt(12);
oos.writeObject("Hello World!");
oos.writeObject(date);
// oos.writeObject(person);
/*Person类没有实现反序列化,因而不能使用writeObject方法进行写入*/
oos.writeObject(book);
}catch(IOException e) {
e.printStackTrace();
}
}
}
八、转换流
转换流可以实现字节流与字符流之间的转换。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Test01{
public static void main(String[] args) {
try(BufferedReader br =
new BufferedReader(
new InputStreamReader(System.in));
BufferedWriter bw =
new BufferedWriter(
new OutputStreamWriter(System.out));){
/*无论是System.in还是System.out它们本身都不是字符流。*/
/*这里是利用了OutputStreamReader和InputStreamWriter对他们进行了转换。*/
String str = new String();
while((str = br.readLine())!=null) {
bw.write(str);
bw.newLine();
bw.flush();
}
}catch(IOException e) {
e.printStackTrace();
}
}
}