听到流这个词,我想很多人都会想到溪流,夏天的时候溪流清澈,蔚蓝的天空,一阵阵轻风吹过伴随着淙淙的流水声。但在编程里流的定义可没有这么美好,里面说流是一串连续不断的数据的集合。是不是一下子打断你美好的想像。
流分为很多种,例如有文件流、缓冲流、数据流。但不管是什么样的流,他们的本质还是流。 有很多人都这么比喻过,流就像水管里的水流,数据从一端流向另一端。文件流,数据流……。就好像不同的管子,有的管子是用来装文件的,有的管子是用来装数据的,也有的管子是套在另一个管子之上的,例如缓冲流。
Java.IO包中定义了很多类型的流。按数据流的方向不同可以分为输入流和输出流,按处理数据单位的不同可以分类字节流和字符流。按照功能不同可以分为节点流和处理流。
字节流 | 字符流 | |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
一、字节流
继承自InputStream的流都是输入流,继承自OutputStream的都是输出流,且他们的数据单位为字节(8bit),如下图:
FileInputStream Example
import java.io.FileInputStream; public class vvv { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("c:\\data1.txt"); int b = 0; long num = 0; while ((b = fis.read()) != -1) { System.out.print((char) b); num++; } fis.close(); System.out.println("\n共读取了" + num + "个字节的字符\n"); } }
FileOutputStream Example
import java.io.FileInputStream; import java.io.FileOutputStream; public class vvv { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("c:\\data1.txt"); FileOutputStream fos = new FileOutputStream("c:\\data2.txt"); int b = 0; while ((b = fis.read()) != -1) { fos.write(b); } fis.close(); fos.close(); System.out.println("执行完毕"); } }
二、字符流
继承自Reader的流都是输入流,继承自Writer的都是输出流,且他们的数据单位为字符(16bit),如下图
Reader | Writer |
FileWriter Example
import java.io.FileReader; public class vvv { public static void main(String[] args) throws Exception { FileReader fr = new FileReader("c:\\data1.txt"); int b =0; while((b=fr.read())!=-1){ System.out.print((char)b); } } }
FileReader Example
import java.io.FileReader; import java.io.FileWriter; public class vvv { public static void main(String[] args) throws Exception { FileReader fr = new FileReader("c:\\data1.txt"); FileWriter fw = new FileWriter("c:\\data2.txt",true); //后面加一个参数true后,可以追加内容 int b =0; while((b=fr.read())!=-1){ fw.write(b); } fr.close(); fw.close(); System.out.println("执行完毕!"); } }
三、缓冲流
缓冲流要”嵌套”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的之法。
J2DK提供了四种缓冲流。缓冲输入流支持其父类的MARK和RESET方法。
BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔)
BufferedWriter提供了newLine用于写入一个行分隔符
对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出。
BufferReader Example
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; public class vvv { public static void main(String[] args) throws Exception { FileReader fReader = new FileReader("c:\\data1.txt"); BufferedReader br = new BufferedReader(fReader); FileWriter fWriter = new FileWriter("c:\\data2.txt"); BufferedWriter bw = new BufferedWriter(fWriter); String s = null; while((s=br.readLine())!=null){ bw.write(s); bw.newLine();//写完一行需要新起一行! } bw.flush(); bw.close(); br.close(); System.out.println("执行完成!"); } }
四、转换流
InputStreamReader和OutputStreamWriter用字节数据转换成字符数据。InputStreamReader需要和InputStream套接。OutputStreamWriter需要和OutputStream套接。
Examlpe:
import java.io.FileOutputStream; import java.io.OutputStreamWriter; public class vvv { public static void main(String[] args) throws Exception { //将字节流转换成字符流 OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream("c:\\data1.txt",true) //注意后面的true,往原内容进行追加 ); //System.out.println(osw.getEncoding()); osw.write("Heelo OutputStreamWriter"); osw.close(); } }
五、数据流
DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流。需要分别”嵌套”在InputStream和OutputStream类型的节点流上。DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据,例如int,double类型。DataInputStream和DataOutputStream的构造方法: DataInputStream(InputStream in);
DataOutputStream(OutputStream out);
另外DataInputStream有readUTF, 而DataOutputStream有WriteUTF。这两个方法在网络编程TCP里非常好用。
Example:
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; public class vvv { public static void main(String[] args) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeDouble(0.6765451); dos.writeBoolean(true); //读取来 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); DataInputStream dis = new DataInputStream(bais); System.out.println(dis.readDouble()); System.out.println(dis.readBoolean()); } }
六、对象流
可以将对象序列化到一个文件中,使用的时候可以取出来使用。所以对需要进行序列化的对象类需要实现接口Serializeable
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class vvv { public static void main(String[] args) throws Exception { Goods good = new Goods("电脑",3012.1); //写出一个对象到C盘a.txt文件中 FileOutputStream fileOut = new FileOutputStream("c:\\a.txt"); ObjectOutputStream objectOut = new ObjectOutputStream(fileOut); objectOut.writeObject(good); //把对象输出出来 FileInputStream fileInput = new FileInputStream("c:\\a.txt"); ObjectInputStream objectInput = new ObjectInputStream(fileInput); Goods good2 = (Goods) objectInput.readObject(); System.out.println(good2.getName() + ":" + good2.getPrice()); } } class Goods implements Serializable { public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } String name = null; double price; Goods(String name, double price) { this.name = name; this.price = price; } }